Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Alexander Kuppe2013-10-21 14:28:32 +0000
committerMarkus Alexander Kuppe2013-10-21 14:28:32 +0000
commit1c721d9715664b587b0c3f9173d397bbc53617d1 (patch)
tree1866290c5f9a021ec7174ad376d0764fa3f15595 /protocols/bundles
parenta693df6386107b7b2d069fd65a78f5772f00b745 (diff)
parent3f59c78d45fb4856da8390f2ff21e106f3787e01 (diff)
downloadorg.eclipse.ecf-1c721d9715664b587b0c3f9173d397bbc53617d1.tar.gz
org.eclipse.ecf-1c721d9715664b587b0c3f9173d397bbc53617d1.tar.xz
org.eclipse.ecf-1c721d9715664b587b0c3f9173d397bbc53617d1.zip
Merge branch 'master' of ssh://git.eclipse.org:29418/ecf/org.eclipse.ecf
Diffstat (limited to 'protocols/bundles')
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/AbstractConnectionListener.java92
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/NonSASLAuthentication.java286
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/OpenTrustManager.java96
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PacketInterceptor.java98
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyList.java114
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyListListener.java100
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyListManager.java932
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/ReconnectionManager.java406
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/SASLAuthentication.java1180
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/SmackError.java48
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/UserAuthentication.java158
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/filter/IQTypeFilter.java96
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Bind.java142
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Privacy.java644
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/PrivacyItem.java890
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Session.java90
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/StreamError.java212
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/provider/EmbeddedExtensionProvider.java218
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/provider/PrivacyProvider.java268
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLAnonymous.java124
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLCramMD5Mechanism.java76
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLDigestMD5Mechanism.java76
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLExternalMechanism.java118
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLGSSAPIMechanism.java178
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLMechanism.java808
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLPlainMechanism.java68
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/util/Base64.java3364
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/util/SyncPacketSend.java128
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/LastActivityManager.java460
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/SharedGroupManager.java106
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamListener.java94
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamManager.java228
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamRequest.java118
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamSession.java162
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/CloseListener.java150
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/DataListener.java146
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamListener.java92
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamManager.java1092
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamRequest.java184
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java1590
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InitiationListener.java254
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/packet/Close.java130
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/packet/Data.java128
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/packet/DataPacketExtension.java298
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/packet/Open.java252
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/provider/CloseIQProvider.java66
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/provider/DataPacketProvider.java90
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/provider/OpenIQProvider.java90
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/socks5/InitiationListener.java238
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamListener.java86
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java1536
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamRequest.java632
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamSession.java162
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/socks5/Socks5Client.java408
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientForInitiator.java234
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java846
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/socks5/Socks5Utils.java146
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/socks5/packet/Bytestream.java948
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/socks5/provider/BytestreamsProvider.java164
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/commands/AdHocCommand.java898
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/commands/AdHocCommandManager.java1498
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/commands/AdHocCommandNote.java170
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/commands/LocalCommand.java336
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/filetransfer/FileTransfer.java760
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/filetransfer/FileTransferListener.java72
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/filetransfer/FileTransferManager.java364
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/filetransfer/FileTransferNegotiator.java970
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/filetransfer/FileTransferRequest.java276
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/filetransfer/IBBTransferNegotiator.java304
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/filetransfer/IncomingFileTransfer.java430
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/filetransfer/OutgoingFileTransfer.java898
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator.java328
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/filetransfer/StreamNegotiator.java334
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/AdHocCommandData.java556
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/AttentionExtension.java200
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/ChatStateExtension.java146
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/DelayInfo.java210
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/Header.java118
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/HeadersExtension.java138
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/Nick.java224
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/SharedGroupsInfo.java146
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/StreamInitiation.java838
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/AdHocCommandDataProvider.java310
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/DelayInfoProvider.java84
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/EmbeddedExtensionProvider.java222
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/HeaderProvider.java88
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/HeadersProvider.java74
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/StreamInitiationProvider.java248
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/AccessModel.java76
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/Affiliation.java180
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/AffiliationsExtension.java138
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/ChildrenAssociationPolicy.java64
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/CollectionNode.java24
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/ConfigurationEvent.java112
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/ConfigureForm.java1418
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/ConfigureNodeFields.java436
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/EmbeddedPacketExtension.java90
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/EventElement.java148
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/EventElementType.java82
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/FormNode.java198
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/FormNodeType.java100
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/FormType.java50
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/GetItemsRequest.java170
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/Item.java264
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/ItemDeleteEvent.java124
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/ItemPublishEvent.java246
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/ItemReply.java58
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/ItemsExtension.java392
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/LeafNode.java704
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/Node.java1044
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/NodeEvent.java32
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/NodeExtension.java170
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/NodeType.java50
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/OptionsExtension.java144
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/PayloadItem.java274
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/PresenceState.java50
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/PubSubElementType.java160
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/PubSubManager.java658
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/PublishItem.java140
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/PublishModel.java64
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/RetractItem.java118
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/SimplePayload.java130
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/SubscribeExtension.java120
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/SubscribeForm.java482
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/SubscribeOptionFields.java198
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/Subscription.java320
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/SubscriptionEvent.java150
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/SubscriptionsExtension.java192
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/UnsubscribeExtension.java146
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/listener/ItemDeleteListener.java82
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/listener/ItemEventListener.java72
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/listener/NodeConfigListener.java70
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/packet/PubSub.java212
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/packet/PubSubNamespace.java126
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/packet/SyncPacketSend.java126
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/provider/AffiliationProvider.java74
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/provider/AffiliationsProvider.java76
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/provider/ConfigEventProvider.java84
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/provider/EventProvider.java76
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/provider/FormNodeProvider.java78
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/provider/ItemProvider.java218
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/provider/ItemsProvider.java76
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/provider/PubSubProvider.java124
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/provider/RetractEventProvider.java76
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/provider/SimpleNodeProvider.java74
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/provider/SubscriptionProvider.java104
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/provider/SubscriptionsProvider.java76
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/util/NodeUtils.java86
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/pubsub/util/XmlUtils.java134
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/receipts/DeliveryReceipt.java154
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/receipts/DeliveryReceiptRequest.java108
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/receipts/ReceiptReceivedListener.java50
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/MetaData.java134
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/QueueUser.java170
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/WorkgroupInvitation.java268
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/WorkgroupInvitationListener.java78
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/Agent.java276
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/AgentRoster.java770
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/AgentRosterListener.java70
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/AgentSession.java2368
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/InvitationRequest.java124
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/Offer.java444
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/OfferConfirmation.java228
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/OfferConfirmationListener.java64
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/OfferContent.java110
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/OfferListener.java98
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/QueueUsersListener.java118
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/RevokedOffer.java194
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/TranscriptManager.java200
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/TranscriptSearchManager.java222
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/TransferRequest.java124
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/UserRequest.java94
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/agent/WorkgroupQueue.java446
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/ext/forms/WorkgroupForm.java164
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/ext/history/AgentChatHistory.java310
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/ext/history/AgentChatSession.java186
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/ext/history/ChatMetadata.java232
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/ext/macros/Macro.java136
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/ext/macros/MacroGroup.java286
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/ext/macros/Macros.java394
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/ext/notes/ChatNotes.java310
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/AgentInfo.java264
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/AgentStatus.java530
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/AgentStatusRequest.java324
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/AgentWorkgroups.java258
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/DepartQueuePacket.java148
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/MetaDataProvider.java96
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/OccupantsInfo.java346
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/OfferRequestProvider.java422
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/OfferRevokeProvider.java224
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/QueueDetails.java396
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/QueueOverview.java318
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/QueueUpdate.java242
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/RoomInvitation.java354
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/RoomTransfer.java354
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/SessionID.java154
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/Transcript.java196
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/TranscriptProvider.java132
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/TranscriptSearch.java174
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/Transcripts.java494
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/TranscriptsProvider.java296
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/UserID.java154
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/packet/WorkgroupInformation.java170
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/settings/ChatSetting.java112
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/settings/ChatSettings.java358
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/settings/OfflineSettings.java310
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/settings/SearchSettings.java224
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/user/QueueListener.java110
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/user/Workgroup.java1734
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/util/ListenerEventDispatcher.java262
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/util/MetaDataUtils.java206
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/workgroup/util/ModelUtil.java642
212 files changed, 32037 insertions, 32037 deletions
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/AbstractConnectionListener.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/AbstractConnectionListener.java
index 69acf9012..132da681e 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/AbstractConnectionListener.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/AbstractConnectionListener.java
@@ -1,46 +1,46 @@
-/**
- * All rights reserved. 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 org.jivesoftware.smack;
-
-/**
- * The AbstractConnectionListener class provides an empty implementation for all
- * methods defined by the {@link ConnectionListener} interface. This is a
- * convenience class which should be used in case you do not need to implement
- * all methods.
- *
- * @author Henning Staib
- */
-public class AbstractConnectionListener implements ConnectionListener {
-
- public void connectionClosed() {
- // do nothing
- }
-
- public void connectionClosedOnError(Exception e) {
- // do nothing
- }
-
- public void reconnectingIn(int seconds) {
- // do nothing
- }
-
- public void reconnectionFailed(Exception e) {
- // do nothing
- }
-
- public void reconnectionSuccessful() {
- // do nothing
- }
-
-}
+/**
+ * All rights reserved. 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 org.jivesoftware.smack;
+
+/**
+ * The AbstractConnectionListener class provides an empty implementation for all
+ * methods defined by the {@link ConnectionListener} interface. This is a
+ * convenience class which should be used in case you do not need to implement
+ * all methods.
+ *
+ * @author Henning Staib
+ */
+public class AbstractConnectionListener implements ConnectionListener {
+
+ public void connectionClosed() {
+ // do nothing
+ }
+
+ public void connectionClosedOnError(Exception e) {
+ // do nothing
+ }
+
+ public void reconnectingIn(int seconds) {
+ // do nothing
+ }
+
+ public void reconnectionFailed(Exception e) {
+ // do nothing
+ }
+
+ public void reconnectionSuccessful() {
+ // do nothing
+ }
+
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/NonSASLAuthentication.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/NonSASLAuthentication.java
index d7a479d1e..93511b731 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/NonSASLAuthentication.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/NonSASLAuthentication.java
@@ -1,143 +1,143 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- * Copyright 2003-2007 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smack;
-
-import org.jivesoftware.smack.filter.PacketIDFilter;
-import org.jivesoftware.smack.packet.Authentication;
-import org.jivesoftware.smack.packet.IQ;
-
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.Callback;
-
-/**
- * Implementation of JEP-0078: Non-SASL Authentication. Follow the following
- * <a href=http://www.jabber.org/jeps/jep-0078.html>link</a> to obtain more
- * information about the JEP.
- *
- * @author Gaston Dombiak
- */
-class NonSASLAuthentication implements UserAuthentication {
-
- private Connection connection;
-
- public NonSASLAuthentication(Connection connection) {
- super();
- this.connection = connection;
- }
-
- public String authenticate(String username, String resource, CallbackHandler cbh) throws XMPPException {
- //Use the callback handler to determine the password, and continue on.
- PasswordCallback pcb = new PasswordCallback("Password: ",false);
- try {
- cbh.handle(new Callback[]{pcb});
- return authenticate(username, String.valueOf(pcb.getPassword()),resource);
- } catch (Exception e) {
- throw new XMPPException("Unable to determine password.",e);
- }
- }
-
- public String authenticate(String username, String password, String resource) throws
- XMPPException {
- // If we send an authentication packet in "get" mode with just the username,
- // the server will return the list of authentication protocols it supports.
- Authentication discoveryAuth = new Authentication();
- discoveryAuth.setType(IQ.Type.GET);
- discoveryAuth.setUsername(username);
-
- PacketCollector collector =
- connection.createPacketCollector(new PacketIDFilter(discoveryAuth.getPacketID()));
- // Send the packet
- connection.sendPacket(discoveryAuth);
- // Wait up to a certain number of seconds for a response from the server.
- IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
- if (response == null) {
- throw new XMPPException("No response from the server.");
- }
- // If the server replied with an error, throw an exception.
- else if (response.getType() == IQ.Type.ERROR) {
- throw new XMPPException(response.getError());
- }
- // Otherwise, no error so continue processing.
- Authentication authTypes = (Authentication) response;
- collector.cancel();
-
- // Now, create the authentication packet we'll send to the server.
- Authentication auth = new Authentication();
- auth.setUsername(username);
-
- // Figure out if we should use digest or plain text authentication.
- if (authTypes.getDigest() != null) {
- auth.setDigest(connection.getConnectionID(), password);
- }
- else if (authTypes.getPassword() != null) {
- auth.setPassword(password);
- }
- else {
- throw new XMPPException("Server does not support compatible authentication mechanism.");
- }
-
- auth.setResource(resource);
-
- collector = connection.createPacketCollector(new PacketIDFilter(auth.getPacketID()));
- // Send the packet.
- connection.sendPacket(auth);
- // Wait up to a certain number of seconds for a response from the server.
- response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
- if (response == null) {
- throw new XMPPException("Authentication failed.");
- }
- else if (response.getType() == IQ.Type.ERROR) {
- throw new XMPPException(response.getError());
- }
- // We're done with the collector, so explicitly cancel it.
- collector.cancel();
-
- return response.getTo();
- }
-
- public String authenticateAnonymously() throws XMPPException {
- // Create the authentication packet we'll send to the server.
- Authentication auth = new Authentication();
-
- PacketCollector collector =
- connection.createPacketCollector(new PacketIDFilter(auth.getPacketID()));
- // Send the packet.
- connection.sendPacket(auth);
- // Wait up to a certain number of seconds for a response from the server.
- IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
- if (response == null) {
- throw new XMPPException("Anonymous login failed.");
- }
- else if (response.getType() == IQ.Type.ERROR) {
- throw new XMPPException(response.getError());
- }
- // We're done with the collector, so explicitly cancel it.
- collector.cancel();
-
- if (response.getTo() != null) {
- return response.getTo();
- }
- else {
- return connection.getServiceName() + "/" + ((Authentication) response).getResource();
- }
- }
-}
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2003-2007 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smack;
+
+import org.jivesoftware.smack.filter.PacketIDFilter;
+import org.jivesoftware.smack.packet.Authentication;
+import org.jivesoftware.smack.packet.IQ;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.Callback;
+
+/**
+ * Implementation of JEP-0078: Non-SASL Authentication. Follow the following
+ * <a href=http://www.jabber.org/jeps/jep-0078.html>link</a> to obtain more
+ * information about the JEP.
+ *
+ * @author Gaston Dombiak
+ */
+class NonSASLAuthentication implements UserAuthentication {
+
+ private Connection connection;
+
+ public NonSASLAuthentication(Connection connection) {
+ super();
+ this.connection = connection;
+ }
+
+ public String authenticate(String username, String resource, CallbackHandler cbh) throws XMPPException {
+ //Use the callback handler to determine the password, and continue on.
+ PasswordCallback pcb = new PasswordCallback("Password: ",false);
+ try {
+ cbh.handle(new Callback[]{pcb});
+ return authenticate(username, String.valueOf(pcb.getPassword()),resource);
+ } catch (Exception e) {
+ throw new XMPPException("Unable to determine password.",e);
+ }
+ }
+
+ public String authenticate(String username, String password, String resource) throws
+ XMPPException {
+ // If we send an authentication packet in "get" mode with just the username,
+ // the server will return the list of authentication protocols it supports.
+ Authentication discoveryAuth = new Authentication();
+ discoveryAuth.setType(IQ.Type.GET);
+ discoveryAuth.setUsername(username);
+
+ PacketCollector collector =
+ connection.createPacketCollector(new PacketIDFilter(discoveryAuth.getPacketID()));
+ // Send the packet
+ connection.sendPacket(discoveryAuth);
+ // Wait up to a certain number of seconds for a response from the server.
+ IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
+ if (response == null) {
+ throw new XMPPException("No response from the server.");
+ }
+ // If the server replied with an error, throw an exception.
+ else if (response.getType() == IQ.Type.ERROR) {
+ throw new XMPPException(response.getError());
+ }
+ // Otherwise, no error so continue processing.
+ Authentication authTypes = (Authentication) response;
+ collector.cancel();
+
+ // Now, create the authentication packet we'll send to the server.
+ Authentication auth = new Authentication();
+ auth.setUsername(username);
+
+ // Figure out if we should use digest or plain text authentication.
+ if (authTypes.getDigest() != null) {
+ auth.setDigest(connection.getConnectionID(), password);
+ }
+ else if (authTypes.getPassword() != null) {
+ auth.setPassword(password);
+ }
+ else {
+ throw new XMPPException("Server does not support compatible authentication mechanism.");
+ }
+
+ auth.setResource(resource);
+
+ collector = connection.createPacketCollector(new PacketIDFilter(auth.getPacketID()));
+ // Send the packet.
+ connection.sendPacket(auth);
+ // Wait up to a certain number of seconds for a response from the server.
+ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
+ if (response == null) {
+ throw new XMPPException("Authentication failed.");
+ }
+ else if (response.getType() == IQ.Type.ERROR) {
+ throw new XMPPException(response.getError());
+ }
+ // We're done with the collector, so explicitly cancel it.
+ collector.cancel();
+
+ return response.getTo();
+ }
+
+ public String authenticateAnonymously() throws XMPPException {
+ // Create the authentication packet we'll send to the server.
+ Authentication auth = new Authentication();
+
+ PacketCollector collector =
+ connection.createPacketCollector(new PacketIDFilter(auth.getPacketID()));
+ // Send the packet.
+ connection.sendPacket(auth);
+ // Wait up to a certain number of seconds for a response from the server.
+ IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
+ if (response == null) {
+ throw new XMPPException("Anonymous login failed.");
+ }
+ else if (response.getType() == IQ.Type.ERROR) {
+ throw new XMPPException(response.getError());
+ }
+ // We're done with the collector, so explicitly cancel it.
+ collector.cancel();
+
+ if (response.getTo() != null) {
+ return response.getTo();
+ }
+ else {
+ return connection.getServiceName() + "/" + ((Authentication) response).getResource();
+ }
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/OpenTrustManager.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/OpenTrustManager.java
index 61ed8c62a..2e47b1f16 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/OpenTrustManager.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/OpenTrustManager.java
@@ -1,49 +1,49 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- * Copyright 2003-2007 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smack;
-
-import javax.net.ssl.X509TrustManager;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-/**
- * Dummy trust manager that trust all certificates presented by the server. This class
- * is used during old SSL connections.
- *
- * @author Gaston Dombiak
- */
-class OpenTrustManager implements X509TrustManager {
-
- public OpenTrustManager() {
- }
-
- public X509Certificate[] getAcceptedIssuers() {
- return new X509Certificate[0];
- }
-
- public void checkClientTrusted(X509Certificate[] arg0, String arg1)
- throws CertificateException {
- }
-
- public void checkServerTrusted(X509Certificate[] arg0, String arg1)
- throws CertificateException {
- }
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2003-2007 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smack;
+
+import javax.net.ssl.X509TrustManager;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+/**
+ * Dummy trust manager that trust all certificates presented by the server. This class
+ * is used during old SSL connections.
+ *
+ * @author Gaston Dombiak
+ */
+class OpenTrustManager implements X509TrustManager {
+
+ public OpenTrustManager() {
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+
+ public void checkClientTrusted(X509Certificate[] arg0, String arg1)
+ throws CertificateException {
+ }
+
+ public void checkServerTrusted(X509Certificate[] arg0, String arg1)
+ throws CertificateException {
+ }
} \ No newline at end of file
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PacketInterceptor.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PacketInterceptor.java
index bd89031ec..af5632638 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PacketInterceptor.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PacketInterceptor.java
@@ -1,49 +1,49 @@
-/**
- * $Revision: 2408 $
- * $Date: 2004-11-02 20:53:30 -0300 (Tue, 02 Nov 2004) $
- *
- * Copyright 2003-2005 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smack;
-
-import org.jivesoftware.smack.packet.Packet;
-
-/**
- * Provides a mechanism to intercept and modify packets that are going to be
- * sent to the server. PacketInterceptors are added to the {@link Connection}
- * together with a {@link org.jivesoftware.smack.filter.PacketFilter} so that only
- * certain packets are intercepted and processed by the interceptor.<p>
- *
- * This allows event-style programming -- every time a new packet is found,
- * the {@link #interceptPacket(Packet)} method will be called.
- *
- * @see Connection#addPacketInterceptor(PacketInterceptor, org.jivesoftware.smack.filter.PacketFilter)
- * @author Gaston Dombiak
- */
-public interface PacketInterceptor {
-
- /**
- * Process the packet that is about to be sent to the server. The intercepted
- * packet can be modified by the interceptor.<p>
- *
- * Interceptors are invoked using the same thread that requested the packet
- * to be sent, so it's very important that implementations of this method
- * not block for any extended period of time.
- *
- * @param packet the packet to is going to be sent to the server.
- */
- public void interceptPacket(Packet packet);
-}
+/**
+ * $Revision: 2408 $
+ * $Date: 2004-11-02 20:53:30 -0300 (Tue, 02 Nov 2004) $
+ *
+ * Copyright 2003-2005 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smack;
+
+import org.jivesoftware.smack.packet.Packet;
+
+/**
+ * Provides a mechanism to intercept and modify packets that are going to be
+ * sent to the server. PacketInterceptors are added to the {@link Connection}
+ * together with a {@link org.jivesoftware.smack.filter.PacketFilter} so that only
+ * certain packets are intercepted and processed by the interceptor.<p>
+ *
+ * This allows event-style programming -- every time a new packet is found,
+ * the {@link #interceptPacket(Packet)} method will be called.
+ *
+ * @see Connection#addPacketInterceptor(PacketInterceptor, org.jivesoftware.smack.filter.PacketFilter)
+ * @author Gaston Dombiak
+ */
+public interface PacketInterceptor {
+
+ /**
+ * Process the packet that is about to be sent to the server. The intercepted
+ * packet can be modified by the interceptor.<p>
+ *
+ * Interceptors are invoked using the same thread that requested the packet
+ * to be sent, so it's very important that implementations of this method
+ * not block for any extended period of time.
+ *
+ * @param packet the packet to is going to be sent to the server.
+ */
+ public void interceptPacket(Packet packet);
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyList.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyList.java
index 67d731db7..e2d9f5e0b 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyList.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyList.java
@@ -15,60 +15,60 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jivesoftware.smack;
-
-import org.jivesoftware.smack.packet.PrivacyItem;
-
-import java.util.List;
-
-/**
- * A privacy list represents a list of contacts that is a read only class used to represent a set of allowed or blocked communications.
- * Basically it can:<ul>
- *
- * <li>Handle many {@link org.jivesoftware.smack.packet.PrivacyItem}.</li>
- * <li>Answer if it is the default list.</li>
- * <li>Answer if it is the active list.</li>
- * </ul>
- *
- * {@link PrivacyItem Privacy Items} can handle different kind of blocking communications based on JID, group,
- * subscription type or globally.
- *
- * @author Francisco Vives
- */
-public class PrivacyList {
-
- /** Holds if it is an active list or not **/
- private boolean isActiveList;
- /** Holds if it is an default list or not **/
- private boolean isDefaultList;
- /** Holds the list name used to print **/
- private String listName;
- /** Holds the list of {@see PrivacyItem} **/
- private List<PrivacyItem> items;
-
- protected PrivacyList(boolean isActiveList, boolean isDefaultList,
- String listName, List<PrivacyItem> privacyItems) {
- super();
- this.isActiveList = isActiveList;
- this.isDefaultList = isDefaultList;
- this.listName = listName;
- this.items = privacyItems;
- }
-
- public boolean isActiveList() {
- return isActiveList;
- }
-
- public boolean isDefaultList() {
- return isDefaultList;
- }
-
- public List<PrivacyItem> getItems() {
- return items;
- }
-
- public String toString() {
- return listName;
- }
-
-}
+package org.jivesoftware.smack;
+
+import org.jivesoftware.smack.packet.PrivacyItem;
+
+import java.util.List;
+
+/**
+ * A privacy list represents a list of contacts that is a read only class used to represent a set of allowed or blocked communications.
+ * Basically it can:<ul>
+ *
+ * <li>Handle many {@link org.jivesoftware.smack.packet.PrivacyItem}.</li>
+ * <li>Answer if it is the default list.</li>
+ * <li>Answer if it is the active list.</li>
+ * </ul>
+ *
+ * {@link PrivacyItem Privacy Items} can handle different kind of blocking communications based on JID, group,
+ * subscription type or globally.
+ *
+ * @author Francisco Vives
+ */
+public class PrivacyList {
+
+ /** Holds if it is an active list or not **/
+ private boolean isActiveList;
+ /** Holds if it is an default list or not **/
+ private boolean isDefaultList;
+ /** Holds the list name used to print **/
+ private String listName;
+ /** Holds the list of {@see PrivacyItem} **/
+ private List<PrivacyItem> items;
+
+ protected PrivacyList(boolean isActiveList, boolean isDefaultList,
+ String listName, List<PrivacyItem> privacyItems) {
+ super();
+ this.isActiveList = isActiveList;
+ this.isDefaultList = isDefaultList;
+ this.listName = listName;
+ this.items = privacyItems;
+ }
+
+ public boolean isActiveList() {
+ return isActiveList;
+ }
+
+ public boolean isDefaultList() {
+ return isDefaultList;
+ }
+
+ public List<PrivacyItem> getItems() {
+ return items;
+ }
+
+ public String toString() {
+ return listName;
+ }
+
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyListListener.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyListListener.java
index 5644ed7e2..20683f8a7 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyListListener.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyListListener.java
@@ -1,51 +1,51 @@
-/**
- * $Revision$
- * $Date$
- *
- * Copyright 2006-2007 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smack;
-
-import org.jivesoftware.smack.packet.PrivacyItem;
-
-import java.util.List;
-
-/**
- * Interface to implement classes to listen for server events about privacy communication.
- * Listeners are registered with the {@link PrivacyListManager}.
- *
- * @see PrivacyListManager#addListener
- *
- * @author Francisco Vives
- */
-public interface PrivacyListListener {
-
- /**
- * Set or update a privacy list with PrivacyItem.
- *
- * @param listName the name of the new or updated privacy list.
- * @param listItem the PrivacyItems that rules the list.
- */
- public void setPrivacyList(String listName, List<PrivacyItem> listItem);
-
- /**
- * A privacy list has been modified by another. It gets notified.
- *
- * @param listName the name of the updated privacy list.
- */
- public void updatedPrivacyList(String listName);
-
+/**
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2006-2007 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smack;
+
+import org.jivesoftware.smack.packet.PrivacyItem;
+
+import java.util.List;
+
+/**
+ * Interface to implement classes to listen for server events about privacy communication.
+ * Listeners are registered with the {@link PrivacyListManager}.
+ *
+ * @see PrivacyListManager#addListener
+ *
+ * @author Francisco Vives
+ */
+public interface PrivacyListListener {
+
+ /**
+ * Set or update a privacy list with PrivacyItem.
+ *
+ * @param listName the name of the new or updated privacy list.
+ * @param listItem the PrivacyItems that rules the list.
+ */
+ public void setPrivacyList(String listName, List<PrivacyItem> listItem);
+
+ /**
+ * A privacy list has been modified by another. It gets notified.
+ *
+ * @param listName the name of the updated privacy list.
+ */
+ public void updatedPrivacyList(String listName);
+
} \ No newline at end of file
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyListManager.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyListManager.java
index eb1d231d2..77b066a50 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyListManager.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/PrivacyListManager.java
@@ -1,466 +1,466 @@
-/**
- * $Revision$
- * $Date$
- *
- * Copyright 2006-2007 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smack;
-
-import org.jivesoftware.smack.filter.*;
-import org.jivesoftware.smack.packet.IQ;
-import org.jivesoftware.smack.packet.Packet;
-import org.jivesoftware.smack.packet.Privacy;
-import org.jivesoftware.smack.packet.PrivacyItem;
-
-import java.util.*;
-
-/**
- * A PrivacyListManager is used by XMPP clients to block or allow communications from other
- * users. Use the manager to: <ul>
- * <li>Retrieve privacy lists.
- * <li>Add, remove, and edit privacy lists.
- * <li>Set, change, or decline active lists.
- * <li>Set, change, or decline the default list (i.e., the list that is active by default).
- * </ul>
- * Privacy Items can handle different kind of permission communications based on JID, group,
- * subscription type or globally (@see PrivacyItem).
- *
- * @author Francisco Vives
- */
-public class PrivacyListManager {
-
- // Keep the list of instances of this class.
- private static Map<Connection, PrivacyListManager> instances = new Hashtable<Connection, PrivacyListManager>();
-
- private Connection connection;
- private final List<PrivacyListListener> listeners = new ArrayList<PrivacyListListener>();
- PacketFilter packetFilter = new AndFilter(new IQTypeFilter(IQ.Type.SET),
- new PacketExtensionFilter("query", "jabber:iq:privacy"));
-
- static {
- // Create a new PrivacyListManager on every established connection. In the init()
- // method of PrivacyListManager, we'll add a listener that will delete the
- // instance when the connection is closed.
- Connection.addConnectionCreationListener(new ConnectionCreationListener() {
- public void connectionCreated(Connection connection) {
- new PrivacyListManager(connection);
- }
- });
- }
- /**
- * Creates a new privacy manager to maintain the communication privacy. Note: no
- * information is sent to or received from the server until you attempt to
- * get or set the privacy communication.<p>
- *
- * @param connection the XMPP connection.
- */
- private PrivacyListManager(Connection connection) {
- this.connection = connection;
- this.init();
- }
-
- /** Answer the connection userJID that owns the privacy.
- * @return the userJID that owns the privacy
- */
- private String getUser() {
- return connection.getUser();
- }
-
- /**
- * Initializes the packet listeners of the connection that will notify for any set privacy
- * package.
- */
- private void init() {
- // Register the new instance and associate it with the connection
- instances.put(connection, this);
- // Add a listener to the connection that removes the registered instance when
- // the connection is closed
- connection.addConnectionListener(new ConnectionListener() {
- public void connectionClosed() {
- // Unregister this instance since the connection has been closed
- instances.remove(connection);
- }
-
- public void connectionClosedOnError(Exception e) {
- // ignore
- }
-
- public void reconnectionFailed(Exception e) {
- // ignore
- }
-
- public void reconnectingIn(int seconds) {
- // ignore
- }
-
- public void reconnectionSuccessful() {
- // ignore
- }
- });
-
- connection.addPacketListener(new PacketListener() {
- public void processPacket(Packet packet) {
-
- if (packet == null || packet.getError() != null) {
- return;
- }
- // The packet is correct.
- Privacy privacy = (Privacy) packet;
-
- // Notifies the event to the listeners.
- synchronized (listeners) {
- for (PrivacyListListener listener : listeners) {
- // Notifies the created or updated privacy lists
- for (Map.Entry<String,List<PrivacyItem>> entry : privacy.getItemLists().entrySet()) {
- String listName = entry.getKey();
- List<PrivacyItem> items = entry.getValue();
- if (items.isEmpty()) {
- listener.updatedPrivacyList(listName);
- } else {
- listener.setPrivacyList(listName, items);
- }
- }
- }
- }
-
- // Send a result package acknowledging the reception of a privacy package.
-
- // Prepare the IQ packet to send
- IQ iq = new IQ() {
- public String getChildElementXML() {
- return "";
- }
- };
- iq.setType(IQ.Type.RESULT);
- iq.setFrom(packet.getFrom());
- iq.setPacketID(packet.getPacketID());
-
- // Send create & join packet.
- connection.sendPacket(iq);
- }
- }, packetFilter);
- }
-
- /**
- * Returns the PrivacyListManager instance associated with a given Connection.
- *
- * @param connection the connection used to look for the proper PrivacyListManager.
- * @return the PrivacyListManager associated with a given Connection.
- */
- public static PrivacyListManager getInstanceFor(Connection connection) {
- return instances.get(connection);
- }
-
- /**
- * Send the {@link Privacy} packet to the server in order to know some privacy content and then
- * waits for the answer.
- *
- * @param requestPrivacy is the {@link Privacy} packet configured properly whose XML
- * will be sent to the server.
- * @return a new {@link Privacy} with the data received from the server.
- * @exception XMPPException if the request or the answer failed, it raises an exception.
- */
- private Privacy getRequest(Privacy requestPrivacy) throws XMPPException {
- // The request is a get iq type
- requestPrivacy.setType(Privacy.Type.GET);
- requestPrivacy.setFrom(this.getUser());
-
- // Filter packets looking for an answer from the server.
- PacketFilter responseFilter = new PacketIDFilter(requestPrivacy.getPacketID());
- PacketCollector response = connection.createPacketCollector(responseFilter);
-
- // Send create & join packet.
- connection.sendPacket(requestPrivacy);
-
- // Wait up to a certain number of seconds for a reply.
- Privacy privacyAnswer =
- (Privacy) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
-
- // Stop queuing results
- response.cancel();
-
- // Interprete the result and answer the privacy only if it is valid
- if (privacyAnswer == null) {
- throw new XMPPException("No response from server.");
- }
- else if (privacyAnswer.getError() != null) {
- throw new XMPPException(privacyAnswer.getError());
- }
- return privacyAnswer;
- }
-
- /**
- * Send the {@link Privacy} packet to the server in order to modify the server privacy and
- * waits for the answer.
- *
- * @param requestPrivacy is the {@link Privacy} packet configured properly whose xml will be sent
- * to the server.
- * @return a new {@link Privacy} with the data received from the server.
- * @exception XMPPException if the request or the answer failed, it raises an exception.
- */
- private Packet setRequest(Privacy requestPrivacy) throws XMPPException {
-
- // The request is a get iq type
- requestPrivacy.setType(Privacy.Type.SET);
- requestPrivacy.setFrom(this.getUser());
-
- // Filter packets looking for an answer from the server.
- PacketFilter responseFilter = new PacketIDFilter(requestPrivacy.getPacketID());
- PacketCollector response = connection.createPacketCollector(responseFilter);
-
- // Send create & join packet.
- connection.sendPacket(requestPrivacy);
-
- // Wait up to a certain number of seconds for a reply.
- Packet privacyAnswer = response.nextResult(SmackConfiguration.getPacketReplyTimeout());
-
- // Stop queuing results
- response.cancel();
-
- // Interprete the result and answer the privacy only if it is valid
- if (privacyAnswer == null) {
- throw new XMPPException("No response from server.");
- } else if (privacyAnswer.getError() != null) {
- throw new XMPPException(privacyAnswer.getError());
- }
- return privacyAnswer;
- }
-
- /**
- * Answer a privacy containing the list structre without {@link PrivacyItem}.
- *
- * @return a Privacy with the list names.
- * @throws XMPPException if an error occurs.
- */
- private Privacy getPrivacyWithListNames() throws XMPPException {
-
- // The request of the list is an empty privacy message
- Privacy request = new Privacy();
-
- // Send the package to the server and get the answer
- return getRequest(request);
- }
-
- /**
- * Answer the active privacy list.
- *
- * @return the privacy list of the active list.
- * @throws XMPPException if an error occurs.
- */
- public PrivacyList getActiveList() throws XMPPException {
- Privacy privacyAnswer = this.getPrivacyWithListNames();
- String listName = privacyAnswer.getActiveName();
- boolean isDefaultAndActive = privacyAnswer.getActiveName() != null
- && privacyAnswer.getDefaultName() != null
- && privacyAnswer.getActiveName().equals(
- privacyAnswer.getDefaultName());
- return new PrivacyList(true, isDefaultAndActive, listName, getPrivacyListItems(listName));
- }
-
- /**
- * Answer the default privacy list.
- *
- * @return the privacy list of the default list.
- * @throws XMPPException if an error occurs.
- */
- public PrivacyList getDefaultList() throws XMPPException {
- Privacy privacyAnswer = this.getPrivacyWithListNames();
- String listName = privacyAnswer.getDefaultName();
- boolean isDefaultAndActive = privacyAnswer.getActiveName() != null
- && privacyAnswer.getDefaultName() != null
- && privacyAnswer.getActiveName().equals(
- privacyAnswer.getDefaultName());
- return new PrivacyList(isDefaultAndActive, true, listName, getPrivacyListItems(listName));
- }
-
- /**
- * Answer the privacy list items under listName with the allowed and blocked permissions.
- *
- * @param listName the name of the list to get the allowed and blocked permissions.
- * @return a list of privacy items under the list listName.
- * @throws XMPPException if an error occurs.
- */
- private List<PrivacyItem> getPrivacyListItems(String listName) throws XMPPException {
-
- // The request of the list is an privacy message with an empty list
- Privacy request = new Privacy();
- request.setPrivacyList(listName, new ArrayList<PrivacyItem>());
-
- // Send the package to the server and get the answer
- Privacy privacyAnswer = getRequest(request);
-
- return privacyAnswer.getPrivacyList(listName);
- }
-
- /**
- * Answer the privacy list items under listName with the allowed and blocked permissions.
- *
- * @param listName the name of the list to get the allowed and blocked permissions.
- * @return a privacy list under the list listName.
- * @throws XMPPException if an error occurs.
- */
- public PrivacyList getPrivacyList(String listName) throws XMPPException {
-
- return new PrivacyList(false, false, listName, getPrivacyListItems(listName));
- }
-
- /**
- * Answer every privacy list with the allowed and blocked permissions.
- *
- * @return an array of privacy lists.
- * @throws XMPPException if an error occurs.
- */
- public PrivacyList[] getPrivacyLists() throws XMPPException {
- Privacy privacyAnswer = this.getPrivacyWithListNames();
- Set<String> names = privacyAnswer.getPrivacyListNames();
- PrivacyList[] lists = new PrivacyList[names.size()];
- boolean isActiveList;
- boolean isDefaultList;
- int index=0;
- for (String listName : names) {
- isActiveList = listName.equals(privacyAnswer.getActiveName());
- isDefaultList = listName.equals(privacyAnswer.getDefaultName());
- lists[index] = new PrivacyList(isActiveList, isDefaultList,
- listName, getPrivacyListItems(listName));
- index = index + 1;
- }
- return lists;
- }
-
-
- /**
- * Set or change the active list to listName.
- *
- * @param listName the list name to set as the active one.
- * @exception XMPPException if the request or the answer failed, it raises an exception.
- */
- public void setActiveListName(String listName) throws XMPPException {
-
- // The request of the list is an privacy message with an empty list
- Privacy request = new Privacy();
- request.setActiveName(listName);
-
- // Send the package to the server
- setRequest(request);
- }
-
- /**
- * Client declines the use of active lists.
- *
- * @throws XMPPException if an error occurs.
- */
- public void declineActiveList() throws XMPPException {
-
- // The request of the list is an privacy message with an empty list
- Privacy request = new Privacy();
- request.setDeclineActiveList(true);
-
- // Send the package to the server
- setRequest(request);
- }
-
- /**
- * Set or change the default list to listName.
- *
- * @param listName the list name to set as the default one.
- * @exception XMPPException if the request or the answer failed, it raises an exception.
- */
- public void setDefaultListName(String listName) throws XMPPException {
-
- // The request of the list is an privacy message with an empty list
- Privacy request = new Privacy();
- request.setDefaultName(listName);
-
- // Send the package to the server
- setRequest(request);
- }
-
- /**
- * Client declines the use of default lists.
- *
- * @throws XMPPException if an error occurs.
- */
- public void declineDefaultList() throws XMPPException {
-
- // The request of the list is an privacy message with an empty list
- Privacy request = new Privacy();
- request.setDeclineDefaultList(true);
-
- // Send the package to the server
- setRequest(request);
- }
-
- /**
- * The client has created a new list. It send the new one to the server.
- *
- * @param listName the list that has changed its content.
- * @param privacyItems a List with every privacy item in the list.
- * @throws XMPPException if an error occurs.
- */
- public void createPrivacyList(String listName, List<PrivacyItem> privacyItems) throws XMPPException {
-
- this.updatePrivacyList(listName, privacyItems);
- }
-
- /**
- * The client has edited an existing list. It updates the server content with the resulting
- * list of privacy items. The {@link PrivacyItem} list MUST contain all elements in the
- * list (not the "delta").
- *
- * @param listName the list that has changed its content.
- * @param privacyItems a List with every privacy item in the list.
- * @throws XMPPException if an error occurs.
- */
- public void updatePrivacyList(String listName, List<PrivacyItem> privacyItems) throws XMPPException {
-
- // Build the privacy package to add or update the new list
- Privacy request = new Privacy();
- request.setPrivacyList(listName, privacyItems);
-
- // Send the package to the server
- setRequest(request);
- }
-
- /**
- * Remove a privacy list.
- *
- * @param listName the list that has changed its content.
- * @throws XMPPException if an error occurs.
- */
- public void deletePrivacyList(String listName) throws XMPPException {
-
- // The request of the list is an privacy message with an empty list
- Privacy request = new Privacy();
- request.setPrivacyList(listName, new ArrayList<PrivacyItem>());
-
- // Send the package to the server
- setRequest(request);
- }
-
- /**
- * Adds a packet listener that will be notified of any new update in the user
- * privacy communication.
- *
- * @param listener a packet listener.
- */
- public void addListener(PrivacyListListener listener) {
- // Keep track of the listener so that we can manually deliver extra
- // messages to it later if needed.
- synchronized (listeners) {
- listeners.add(listener);
- }
- }
-}
+/**
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2006-2007 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smack;
+
+import org.jivesoftware.smack.filter.*;
+import org.jivesoftware.smack.packet.IQ;
+import org.jivesoftware.smack.packet.Packet;
+import org.jivesoftware.smack.packet.Privacy;
+import org.jivesoftware.smack.packet.PrivacyItem;
+
+import java.util.*;
+
+/**
+ * A PrivacyListManager is used by XMPP clients to block or allow communications from other
+ * users. Use the manager to: <ul>
+ * <li>Retrieve privacy lists.
+ * <li>Add, remove, and edit privacy lists.
+ * <li>Set, change, or decline active lists.
+ * <li>Set, change, or decline the default list (i.e., the list that is active by default).
+ * </ul>
+ * Privacy Items can handle different kind of permission communications based on JID, group,
+ * subscription type or globally (@see PrivacyItem).
+ *
+ * @author Francisco Vives
+ */
+public class PrivacyListManager {
+
+ // Keep the list of instances of this class.
+ private static Map<Connection, PrivacyListManager> instances = new Hashtable<Connection, PrivacyListManager>();
+
+ private Connection connection;
+ private final List<PrivacyListListener> listeners = new ArrayList<PrivacyListListener>();
+ PacketFilter packetFilter = new AndFilter(new IQTypeFilter(IQ.Type.SET),
+ new PacketExtensionFilter("query", "jabber:iq:privacy"));
+
+ static {
+ // Create a new PrivacyListManager on every established connection. In the init()
+ // method of PrivacyListManager, we'll add a listener that will delete the
+ // instance when the connection is closed.
+ Connection.addConnectionCreationListener(new ConnectionCreationListener() {
+ public void connectionCreated(Connection connection) {
+ new PrivacyListManager(connection);
+ }
+ });
+ }
+ /**
+ * Creates a new privacy manager to maintain the communication privacy. Note: no
+ * information is sent to or received from the server until you attempt to
+ * get or set the privacy communication.<p>
+ *
+ * @param connection the XMPP connection.
+ */
+ private PrivacyListManager(Connection connection) {
+ this.connection = connection;
+ this.init();
+ }
+
+ /** Answer the connection userJID that owns the privacy.
+ * @return the userJID that owns the privacy
+ */
+ private String getUser() {
+ return connection.getUser();
+ }
+
+ /**
+ * Initializes the packet listeners of the connection that will notify for any set privacy
+ * package.
+ */
+ private void init() {
+ // Register the new instance and associate it with the connection
+ instances.put(connection, this);
+ // Add a listener to the connection that removes the registered instance when
+ // the connection is closed
+ connection.addConnectionListener(new ConnectionListener() {
+ public void connectionClosed() {
+ // Unregister this instance since the connection has been closed
+ instances.remove(connection);
+ }
+
+ public void connectionClosedOnError(Exception e) {
+ // ignore
+ }
+
+ public void reconnectionFailed(Exception e) {
+ // ignore
+ }
+
+ public void reconnectingIn(int seconds) {
+ // ignore
+ }
+
+ public void reconnectionSuccessful() {
+ // ignore
+ }
+ });
+
+ connection.addPacketListener(new PacketListener() {
+ public void processPacket(Packet packet) {
+
+ if (packet == null || packet.getError() != null) {
+ return;
+ }
+ // The packet is correct.
+ Privacy privacy = (Privacy) packet;
+
+ // Notifies the event to the listeners.
+ synchronized (listeners) {
+ for (PrivacyListListener listener : listeners) {
+ // Notifies the created or updated privacy lists
+ for (Map.Entry<String,List<PrivacyItem>> entry : privacy.getItemLists().entrySet()) {
+ String listName = entry.getKey();
+ List<PrivacyItem> items = entry.getValue();
+ if (items.isEmpty()) {
+ listener.updatedPrivacyList(listName);
+ } else {
+ listener.setPrivacyList(listName, items);
+ }
+ }
+ }
+ }
+
+ // Send a result package acknowledging the reception of a privacy package.
+
+ // Prepare the IQ packet to send
+ IQ iq = new IQ() {
+ public String getChildElementXML() {
+ return "";
+ }
+ };
+ iq.setType(IQ.Type.RESULT);
+ iq.setFrom(packet.getFrom());
+ iq.setPacketID(packet.getPacketID());
+
+ // Send create & join packet.
+ connection.sendPacket(iq);
+ }
+ }, packetFilter);
+ }
+
+ /**
+ * Returns the PrivacyListManager instance associated with a given Connection.
+ *
+ * @param connection the connection used to look for the proper PrivacyListManager.
+ * @return the PrivacyListManager associated with a given Connection.
+ */
+ public static PrivacyListManager getInstanceFor(Connection connection) {
+ return instances.get(connection);
+ }
+
+ /**
+ * Send the {@link Privacy} packet to the server in order to know some privacy content and then
+ * waits for the answer.
+ *
+ * @param requestPrivacy is the {@link Privacy} packet configured properly whose XML
+ * will be sent to the server.
+ * @return a new {@link Privacy} with the data received from the server.
+ * @exception XMPPException if the request or the answer failed, it raises an exception.
+ */
+ private Privacy getRequest(Privacy requestPrivacy) throws XMPPException {
+ // The request is a get iq type
+ requestPrivacy.setType(Privacy.Type.GET);
+ requestPrivacy.setFrom(this.getUser());
+
+ // Filter packets looking for an answer from the server.
+ PacketFilter responseFilter = new PacketIDFilter(requestPrivacy.getPacketID());
+ PacketCollector response = connection.createPacketCollector(responseFilter);
+
+ // Send create & join packet.
+ connection.sendPacket(requestPrivacy);
+
+ // Wait up to a certain number of seconds for a reply.
+ Privacy privacyAnswer =
+ (Privacy) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
+
+ // Stop queuing results
+ response.cancel();
+
+ // Interprete the result and answer the privacy only if it is valid
+ if (privacyAnswer == null) {
+ throw new XMPPException("No response from server.");
+ }
+ else if (privacyAnswer.getError() != null) {
+ throw new XMPPException(privacyAnswer.getError());
+ }
+ return privacyAnswer;
+ }
+
+ /**
+ * Send the {@link Privacy} packet to the server in order to modify the server privacy and
+ * waits for the answer.
+ *
+ * @param requestPrivacy is the {@link Privacy} packet configured properly whose xml will be sent
+ * to the server.
+ * @return a new {@link Privacy} with the data received from the server.
+ * @exception XMPPException if the request or the answer failed, it raises an exception.
+ */
+ private Packet setRequest(Privacy requestPrivacy) throws XMPPException {
+
+ // The request is a get iq type
+ requestPrivacy.setType(Privacy.Type.SET);
+ requestPrivacy.setFrom(this.getUser());
+
+ // Filter packets looking for an answer from the server.
+ PacketFilter responseFilter = new PacketIDFilter(requestPrivacy.getPacketID());
+ PacketCollector response = connection.createPacketCollector(responseFilter);
+
+ // Send create & join packet.
+ connection.sendPacket(requestPrivacy);
+
+ // Wait up to a certain number of seconds for a reply.
+ Packet privacyAnswer = response.nextResult(SmackConfiguration.getPacketReplyTimeout());
+
+ // Stop queuing results
+ response.cancel();
+
+ // Interprete the result and answer the privacy only if it is valid
+ if (privacyAnswer == null) {
+ throw new XMPPException("No response from server.");
+ } else if (privacyAnswer.getError() != null) {
+ throw new XMPPException(privacyAnswer.getError());
+ }
+ return privacyAnswer;
+ }
+
+ /**
+ * Answer a privacy containing the list structre without {@link PrivacyItem}.
+ *
+ * @return a Privacy with the list names.
+ * @throws XMPPException if an error occurs.
+ */
+ private Privacy getPrivacyWithListNames() throws XMPPException {
+
+ // The request of the list is an empty privacy message
+ Privacy request = new Privacy();
+
+ // Send the package to the server and get the answer
+ return getRequest(request);
+ }
+
+ /**
+ * Answer the active privacy list.
+ *
+ * @return the privacy list of the active list.
+ * @throws XMPPException if an error occurs.
+ */
+ public PrivacyList getActiveList() throws XMPPException {
+ Privacy privacyAnswer = this.getPrivacyWithListNames();
+ String listName = privacyAnswer.getActiveName();
+ boolean isDefaultAndActive = privacyAnswer.getActiveName() != null
+ && privacyAnswer.getDefaultName() != null
+ && privacyAnswer.getActiveName().equals(
+ privacyAnswer.getDefaultName());
+ return new PrivacyList(true, isDefaultAndActive, listName, getPrivacyListItems(listName));
+ }
+
+ /**
+ * Answer the default privacy list.
+ *
+ * @return the privacy list of the default list.
+ * @throws XMPPException if an error occurs.
+ */
+ public PrivacyList getDefaultList() throws XMPPException {
+ Privacy privacyAnswer = this.getPrivacyWithListNames();
+ String listName = privacyAnswer.getDefaultName();
+ boolean isDefaultAndActive = privacyAnswer.getActiveName() != null
+ && privacyAnswer.getDefaultName() != null
+ && privacyAnswer.getActiveName().equals(
+ privacyAnswer.getDefaultName());
+ return new PrivacyList(isDefaultAndActive, true, listName, getPrivacyListItems(listName));
+ }
+
+ /**
+ * Answer the privacy list items under listName with the allowed and blocked permissions.
+ *
+ * @param listName the name of the list to get the allowed and blocked permissions.
+ * @return a list of privacy items under the list listName.
+ * @throws XMPPException if an error occurs.
+ */
+ private List<PrivacyItem> getPrivacyListItems(String listName) throws XMPPException {
+
+ // The request of the list is an privacy message with an empty list
+ Privacy request = new Privacy();
+ request.setPrivacyList(listName, new ArrayList<PrivacyItem>());
+
+ // Send the package to the server and get the answer
+ Privacy privacyAnswer = getRequest(request);
+
+ return privacyAnswer.getPrivacyList(listName);
+ }
+
+ /**
+ * Answer the privacy list items under listName with the allowed and blocked permissions.
+ *
+ * @param listName the name of the list to get the allowed and blocked permissions.
+ * @return a privacy list under the list listName.
+ * @throws XMPPException if an error occurs.
+ */
+ public PrivacyList getPrivacyList(String listName) throws XMPPException {
+
+ return new PrivacyList(false, false, listName, getPrivacyListItems(listName));
+ }
+
+ /**
+ * Answer every privacy list with the allowed and blocked permissions.
+ *
+ * @return an array of privacy lists.
+ * @throws XMPPException if an error occurs.
+ */
+ public PrivacyList[] getPrivacyLists() throws XMPPException {
+ Privacy privacyAnswer = this.getPrivacyWithListNames();
+ Set<String> names = privacyAnswer.getPrivacyListNames();
+ PrivacyList[] lists = new PrivacyList[names.size()];
+ boolean isActiveList;
+ boolean isDefaultList;
+ int index=0;
+ for (String listName : names) {
+ isActiveList = listName.equals(privacyAnswer.getActiveName());
+ isDefaultList = listName.equals(privacyAnswer.getDefaultName());
+ lists[index] = new PrivacyList(isActiveList, isDefaultList,
+ listName, getPrivacyListItems(listName));
+ index = index + 1;
+ }
+ return lists;
+ }
+
+
+ /**
+ * Set or change the active list to listName.
+ *
+ * @param listName the list name to set as the active one.
+ * @exception XMPPException if the request or the answer failed, it raises an exception.
+ */
+ public void setActiveListName(String listName) throws XMPPException {
+
+ // The request of the list is an privacy message with an empty list
+ Privacy request = new Privacy();
+ request.setActiveName(listName);
+
+ // Send the package to the server
+ setRequest(request);
+ }
+
+ /**
+ * Client declines the use of active lists.
+ *
+ * @throws XMPPException if an error occurs.
+ */
+ public void declineActiveList() throws XMPPException {
+
+ // The request of the list is an privacy message with an empty list
+ Privacy request = new Privacy();
+ request.setDeclineActiveList(true);
+
+ // Send the package to the server
+ setRequest(request);
+ }
+
+ /**
+ * Set or change the default list to listName.
+ *
+ * @param listName the list name to set as the default one.
+ * @exception XMPPException if the request or the answer failed, it raises an exception.
+ */
+ public void setDefaultListName(String listName) throws XMPPException {
+
+ // The request of the list is an privacy message with an empty list
+ Privacy request = new Privacy();
+ request.setDefaultName(listName);
+
+ // Send the package to the server
+ setRequest(request);
+ }
+
+ /**
+ * Client declines the use of default lists.
+ *
+ * @throws XMPPException if an error occurs.
+ */
+ public void declineDefaultList() throws XMPPException {
+
+ // The request of the list is an privacy message with an empty list
+ Privacy request = new Privacy();
+ request.setDeclineDefaultList(true);
+
+ // Send the package to the server
+ setRequest(request);
+ }
+
+ /**
+ * The client has created a new list. It send the new one to the server.
+ *
+ * @param listName the list that has changed its content.
+ * @param privacyItems a List with every privacy item in the list.
+ * @throws XMPPException if an error occurs.
+ */
+ public void createPrivacyList(String listName, List<PrivacyItem> privacyItems) throws XMPPException {
+
+ this.updatePrivacyList(listName, privacyItems);
+ }
+
+ /**
+ * The client has edited an existing list. It updates the server content with the resulting
+ * list of privacy items. The {@link PrivacyItem} list MUST contain all elements in the
+ * list (not the "delta").
+ *
+ * @param listName the list that has changed its content.
+ * @param privacyItems a List with every privacy item in the list.
+ * @throws XMPPException if an error occurs.
+ */
+ public void updatePrivacyList(String listName, List<PrivacyItem> privacyItems) throws XMPPException {
+
+ // Build the privacy package to add or update the new list
+ Privacy request = new Privacy();
+ request.setPrivacyList(listName, privacyItems);
+
+ // Send the package to the server
+ setRequest(request);
+ }
+
+ /**
+ * Remove a privacy list.
+ *
+ * @param listName the list that has changed its content.
+ * @throws XMPPException if an error occurs.
+ */
+ public void deletePrivacyList(String listName) throws XMPPException {
+
+ // The request of the list is an privacy message with an empty list
+ Privacy request = new Privacy();
+ request.setPrivacyList(listName, new ArrayList<PrivacyItem>());
+
+ // Send the package to the server
+ setRequest(request);
+ }
+
+ /**
+ * Adds a packet listener that will be notified of any new update in the user
+ * privacy communication.
+ *
+ * @param listener a packet listener.
+ */
+ public void addListener(PrivacyListListener listener) {
+ // Keep track of the listener so that we can manually deliver extra
+ // messages to it later if needed.
+ synchronized (listeners) {
+ listeners.add(listener);
+ }
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/ReconnectionManager.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/ReconnectionManager.java
index cc3e3af19..7e3c1dea3 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/ReconnectionManager.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/ReconnectionManager.java
@@ -15,213 +15,213 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jivesoftware.smack;
-
-import org.jivesoftware.smack.packet.StreamError;
-import java.util.Random;
-/**
- * Handles the automatic reconnection process. Every time a connection is dropped without
- * the application explictly closing it, the manager automatically tries to reconnect to
- * the server.<p>
- *
- * The reconnection mechanism will try to reconnect periodically:
- * <ol>
- * <li>For the first minute it will attempt to connect once every ten seconds.
- * <li>For the next five minutes it will attempt to connect once a minute.
- * <li>If that fails it will indefinitely try to connect once every five minutes.
- * </ol>
- *
- * @author Francisco Vives
- */
-public class ReconnectionManager implements ConnectionListener {
-
- // Holds the connection to the server
- private Connection connection;
- private Thread reconnectionThread;
- private int randomBase = new Random().nextInt(11) + 5; // between 5 and 15 seconds
-
- // Holds the state of the reconnection
- boolean done = false;
-
- static {
- // Create a new PrivacyListManager on every established connection. In the init()
- // method of PrivacyListManager, we'll add a listener that will delete the
- // instance when the connection is closed.
- Connection.addConnectionCreationListener(new ConnectionCreationListener() {
- public void connectionCreated(Connection connection) {
- connection.addConnectionListener(new ReconnectionManager(connection));
- }
- });
- }
-
- private ReconnectionManager(Connection connection) {
- this.connection = connection;
- }
-
-
- /**
- * Returns true if the reconnection mechanism is enabled.
- *
- * @return true if automatic reconnections are allowed.
- */
- private boolean isReconnectionAllowed() {
+package org.jivesoftware.smack;
+
+import org.jivesoftware.smack.packet.StreamError;
+import java.util.Random;
+/**
+ * Handles the automatic reconnection process. Every time a connection is dropped without
+ * the application explictly closing it, the manager automatically tries to reconnect to
+ * the server.<p>
+ *
+ * The reconnection mechanism will try to reconnect periodically:
+ * <ol>
+ * <li>For the first minute it will attempt to connect once every ten seconds.
+ * <li>For the next five minutes it will attempt to connect once a minute.
+ * <li>If that fails it will indefinitely try to connect once every five minutes.
+ * </ol>
+ *
+ * @author Francisco Vives
+ */
+public class ReconnectionManager implements ConnectionListener {
+
+ // Holds the connection to the server
+ private Connection connection;
+ private Thread reconnectionThread;
+ private int randomBase = new Random().nextInt(11) + 5; // between 5 and 15 seconds
+
+ // Holds the state of the reconnection
+ boolean done = false;
+
+ static {
+ // Create a new PrivacyListManager on every established connection. In the init()
+ // method of PrivacyListManager, we'll add a listener that will delete the
+ // instance when the connection is closed.
+ Connection.addConnectionCreationListener(new ConnectionCreationListener() {
+ public void connectionCreated(Connection connection) {
+ connection.addConnectionListener(new ReconnectionManager(connection));
+ }
+ });
+ }
+
+ private ReconnectionManager(Connection connection) {
+ this.connection = connection;
+ }
+
+
+ /**
+ * Returns true if the reconnection mechanism is enabled.
+ *
+ * @return true if automatic reconnections are allowed.
+ */
+ private boolean isReconnectionAllowed() {
return !done && !connection.isConnected()
&& connection.isReconnectionAllowed();
- }
-
- /**
- * Starts a reconnection mechanism if it was configured to do that.
- * The algorithm is been executed when the first connection error is detected.
- * <p/>
- * The reconnection mechanism will try to reconnect periodically in this way:
- * <ol>
- * <li>First it will try 6 times every 10 seconds.
- * <li>Then it will try 10 times every 1 minute.
- * <li>Finally it will try indefinitely every 5 minutes.
- * </ol>
- */
- synchronized protected void reconnect() {
- if (this.isReconnectionAllowed()) {
- // Since there is no thread running, creates a new one to attempt
- // the reconnection.
- // avoid to run duplicated reconnectionThread -- fd: 16/09/2010
- if (reconnectionThread!=null && reconnectionThread.isAlive()) return;
-
- reconnectionThread = new Thread() {
-
- /**
- * Holds the current number of reconnection attempts
- */
- private int attempts = 0;
-
- /**
- * Returns the number of seconds until the next reconnection attempt.
- *
- * @return the number of seconds until the next reconnection attempt.
- */
- private int timeDelay() {
- attempts++;
- if (attempts > 13) {
- return randomBase*6*5; // between 2.5 and 7.5 minutes (~5 minutes)
- }
- if (attempts > 7) {
- return randomBase*6; // between 30 and 90 seconds (~1 minutes)
- }
- return randomBase; // 10 seconds
- }
-
- /**
- * The process will try the reconnection until the connection succeed or the user
- * cancell it
- */
- public void run() {
- // The process will try to reconnect until the connection is established or
- // the user cancel the reconnection process {@link Connection#disconnect()}
- while (ReconnectionManager.this.isReconnectionAllowed()) {
- // Find how much time we should wait until the next reconnection
- int remainingSeconds = timeDelay();
- // Sleep until we're ready for the next reconnection attempt. Notify
- // listeners once per second about how much time remains before the next
- // reconnection attempt.
- while (ReconnectionManager.this.isReconnectionAllowed() &&
- remainingSeconds > 0)
- {
- try {
- Thread.sleep(1000);
- remainingSeconds--;
- ReconnectionManager.this
- .notifyAttemptToReconnectIn(remainingSeconds);
- }
- catch (InterruptedException e1) {
- e1.printStackTrace();
- // Notify the reconnection has failed
- ReconnectionManager.this.notifyReconnectionFailed(e1);
- }
- }
-
- // Makes a reconnection attempt
- try {
- if (ReconnectionManager.this.isReconnectionAllowed()) {
- connection.connect();
- }
- }
- catch (XMPPException e) {
- // Fires the failed reconnection notification
- ReconnectionManager.this.notifyReconnectionFailed(e);
- }
- }
- }
- };
- reconnectionThread.setName("Smack Reconnection Manager");
- reconnectionThread.setDaemon(true);
- reconnectionThread.start();
- }
- }
-
- /**
- * Fires listeners when a reconnection attempt has failed.
- *
- * @param exception the exception that occured.
- */
- protected void notifyReconnectionFailed(Exception exception) {
+ }
+
+ /**
+ * Starts a reconnection mechanism if it was configured to do that.
+ * The algorithm is been executed when the first connection error is detected.
+ * <p/>
+ * The reconnection mechanism will try to reconnect periodically in this way:
+ * <ol>
+ * <li>First it will try 6 times every 10 seconds.
+ * <li>Then it will try 10 times every 1 minute.
+ * <li>Finally it will try indefinitely every 5 minutes.
+ * </ol>
+ */
+ synchronized protected void reconnect() {
+ if (this.isReconnectionAllowed()) {
+ // Since there is no thread running, creates a new one to attempt
+ // the reconnection.
+ // avoid to run duplicated reconnectionThread -- fd: 16/09/2010
+ if (reconnectionThread!=null && reconnectionThread.isAlive()) return;
+
+ reconnectionThread = new Thread() {
+
+ /**
+ * Holds the current number of reconnection attempts
+ */
+ private int attempts = 0;
+
+ /**
+ * Returns the number of seconds until the next reconnection attempt.
+ *
+ * @return the number of seconds until the next reconnection attempt.
+ */
+ private int timeDelay() {
+ attempts++;
+ if (attempts > 13) {
+ return randomBase*6*5; // between 2.5 and 7.5 minutes (~5 minutes)
+ }
+ if (attempts > 7) {
+ return randomBase*6; // between 30 and 90 seconds (~1 minutes)
+ }
+ return randomBase; // 10 seconds
+ }
+
+ /**
+ * The process will try the reconnection until the connection succeed or the user
+ * cancell it
+ */
+ public void run() {
+ // The process will try to reconnect until the connection is established or
+ // the user cancel the reconnection process {@link Connection#disconnect()}
+ while (ReconnectionManager.this.isReconnectionAllowed()) {
+ // Find how much time we should wait until the next reconnection
+ int remainingSeconds = timeDelay();
+ // Sleep until we're ready for the next reconnection attempt. Notify
+ // listeners once per second about how much time remains before the next
+ // reconnection attempt.
+ while (ReconnectionManager.this.isReconnectionAllowed() &&
+ remainingSeconds > 0)
+ {
+ try {
+ Thread.sleep(1000);
+ remainingSeconds--;
+ ReconnectionManager.this
+ .notifyAttemptToReconnectIn(remainingSeconds);
+ }
+ catch (InterruptedException e1) {
+ e1.printStackTrace();
+ // Notify the reconnection has failed
+ ReconnectionManager.this.notifyReconnectionFailed(e1);
+ }
+ }
+
+ // Makes a reconnection attempt
+ try {
+ if (ReconnectionManager.this.isReconnectionAllowed()) {
+ connection.connect();
+ }
+ }
+ catch (XMPPException e) {
+ // Fires the failed reconnection notification
+ ReconnectionManager.this.notifyReconnectionFailed(e);
+ }
+ }
+ }
+ };
+ reconnectionThread.setName("Smack Reconnection Manager");
+ reconnectionThread.setDaemon(true);
+ reconnectionThread.start();
+ }
+ }
+
+ /**
+ * Fires listeners when a reconnection attempt has failed.
+ *
+ * @param exception the exception that occured.
+ */
+ protected void notifyReconnectionFailed(Exception exception) {
if (isReconnectionAllowed()) {
for (ConnectionListener listener : connection.connectionListeners) {
- listener.reconnectionFailed(exception);
- }
- }
- }
-
- /**
- * Fires listeners when The Connection will retry a reconnection. Expressed in seconds.
- *
- * @param seconds the number of seconds that a reconnection will be attempted in.
- */
- protected void notifyAttemptToReconnectIn(int seconds) {
+ listener.reconnectionFailed(exception);
+ }
+ }
+ }
+
+ /**
+ * Fires listeners when The Connection will retry a reconnection. Expressed in seconds.
+ *
+ * @param seconds the number of seconds that a reconnection will be attempted in.
+ */
+ protected void notifyAttemptToReconnectIn(int seconds) {
if (isReconnectionAllowed()) {
for (ConnectionListener listener : connection.connectionListeners) {
- listener.reconnectingIn(seconds);
- }
- }
- }
-
- public void connectionClosed() {
- done = true;
- }
-
- public void connectionClosedOnError(Exception e) {
- done = false;
- if (e instanceof XMPPException) {
- XMPPException xmppEx = (XMPPException) e;
- StreamError error = xmppEx.getStreamError();
-
- // Make sure the error is not null
- if (error != null) {
- String reason = error.getCode();
-
- if ("conflict".equals(reason)) {
- return;
- }
- }
- }
-
- if (this.isReconnectionAllowed()) {
- this.reconnect();
- }
- }
-
- public void reconnectingIn(int seconds) {
- // ignore
- }
-
- public void reconnectionFailed(Exception e) {
- // ignore
- }
-
- /**
- * The connection has successfull gotten connected.
- */
- public void reconnectionSuccessful() {
- // ignore
- }
-
+ listener.reconnectingIn(seconds);
+ }
+ }
+ }
+
+ public void connectionClosed() {
+ done = true;
+ }
+
+ public void connectionClosedOnError(Exception e) {
+ done = false;
+ if (e instanceof XMPPException) {
+ XMPPException xmppEx = (XMPPException) e;
+ StreamError error = xmppEx.getStreamError();
+
+ // Make sure the error is not null
+ if (error != null) {
+ String reason = error.getCode();
+
+ if ("conflict".equals(reason)) {
+ return;
+ }
+ }
+ }
+
+ if (this.isReconnectionAllowed()) {
+ this.reconnect();
+ }
+ }
+
+ public void reconnectingIn(int seconds) {
+ // ignore
+ }
+
+ public void reconnectionFailed(Exception e) {
+ // ignore
+ }
+
+ /**
+ * The connection has successfull gotten connected.
+ */
+ public void reconnectionSuccessful() {
+ // ignore
+ }
+
} \ No newline at end of file
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/SASLAuthentication.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/SASLAuthentication.java
index 6f8b5bf1e..abf08c8a8 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/SASLAuthentication.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/SASLAuthentication.java
@@ -1,591 +1,591 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- * Copyright 2003-2007 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smack;
-
-import org.jivesoftware.smack.filter.PacketIDFilter;
-import org.jivesoftware.smack.packet.Bind;
-import org.jivesoftware.smack.packet.IQ;
-import org.jivesoftware.smack.packet.Packet;
-import org.jivesoftware.smack.packet.Session;
-import org.jivesoftware.smack.sasl.*;
-
-import javax.security.auth.callback.CallbackHandler;
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.util.*;
-
-/**
- * <p>This class is responsible authenticating the user using SASL, binding the resource
- * to the connection and establishing a session with the server.</p>
- *
- * <p>Once TLS has been negotiated (i.e. the connection has been secured) it is possible to
- * register with the server, authenticate using Non-SASL or authenticate using SASL. If the
- * server supports SASL then Smack will first try to authenticate using SASL. But if that
- * fails then Non-SASL will be tried.</p>
- *
- * <p>The server may support many SASL mechanisms to use for authenticating. Out of the box
- * Smack provides several SASL mechanisms, but it is possible to register new SASL Mechanisms. Use
- * {@link #registerSASLMechanism(String, Class)} to register a new mechanisms. A registered
- * mechanism wont be used until {@link #supportSASLMechanism(String, int)} is called. By default,
- * the list of supported SASL mechanisms is determined from the {@link SmackConfiguration}. </p>
- *
- * <p>Once the user has been authenticated with SASL, it is necessary to bind a resource for
- * the connection. If no resource is passed in {@link #authenticate(String, String, String)}
- * then the server will assign a resource for the connection. In case a resource is passed
- * then the server will receive the desired resource but may assign a modified resource for
- * the connection.</p>
- *
- * <p>Once a resource has been binded and if the server supports sessions then Smack will establish
- * a session so that instant messaging and presence functionalities may be used.</p>
- *
- * @see org.jivesoftware.smack.sasl.SASLMechanism
- *
- * @author Gaston Dombiak
- * @author Jay Kline
- */
-public class SASLAuthentication implements UserAuthentication {
-
- private static Map<String, Class<? extends SASLMechanism>> implementedMechanisms = new HashMap<String, Class<? extends SASLMechanism>>();
- private static List<String> mechanismsPreferences = new ArrayList<String>();
-
- private Connection connection;
- private Collection<String> serverMechanisms = new ArrayList<String>();
- private SASLMechanism currentMechanism = null;
- /**
- * Boolean indicating if SASL negotiation has finished and was successful.
- */
- private boolean saslNegotiated;
- /**
- * Boolean indication if SASL authentication has failed. When failed the server may end
- * the connection.
- */
- private boolean saslFailed;
- private boolean resourceBinded;
- private boolean sessionSupported;
- /**
- * The SASL related error condition if there was one provided by the server.
- */
- private String errorCondition;
-
- static {
-
- // Register SASL mechanisms supported by Smack
- registerSASLMechanism("EXTERNAL", SASLExternalMechanism.class);
- registerSASLMechanism("GSSAPI", SASLGSSAPIMechanism.class);
- registerSASLMechanism("DIGEST-MD5", SASLDigestMD5Mechanism.class);
- registerSASLMechanism("CRAM-MD5", SASLCramMD5Mechanism.class);
- registerSASLMechanism("PLAIN", SASLPlainMechanism.class);
- registerSASLMechanism("ANONYMOUS", SASLAnonymous.class);
-
- supportSASLMechanism("GSSAPI",0);
- supportSASLMechanism("DIGEST-MD5",1);
- supportSASLMechanism("CRAM-MD5",2);
- supportSASLMechanism("PLAIN",3);
- supportSASLMechanism("ANONYMOUS",4);
-
- }
-
- /**
- * Registers a new SASL mechanism
- *
- * @param name common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or KERBEROS_V4.
- * @param mClass a SASLMechanism subclass.
- */
- public static void registerSASLMechanism(String name, Class<? extends SASLMechanism> mClass) {
- implementedMechanisms.put(name, mClass);
- }
-
- /**
- * Unregisters an existing SASL mechanism. Once the mechanism has been unregistered it won't
- * be possible to authenticate users using the removed SASL mechanism. It also removes the
- * mechanism from the supported list.
- *
- * @param name common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or KERBEROS_V4.
- */
- public static void unregisterSASLMechanism(String name) {
- implementedMechanisms.remove(name);
- mechanismsPreferences.remove(name);
- }
-
-
- /**
- * Registers a new SASL mechanism in the specified preference position. The client will try
- * to authenticate using the most prefered SASL mechanism that is also supported by the server.
- * The SASL mechanism must be registered via {@link #registerSASLMechanism(String, Class)}
- *
- * @param name common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or KERBEROS_V4.
- */
- public static void supportSASLMechanism(String name) {
- mechanismsPreferences.add(0, name);
- }
-
- /**
- * Registers a new SASL mechanism in the specified preference position. The client will try
- * to authenticate using the most prefered SASL mechanism that is also supported by the server.
- * Use the <tt>index</tt> parameter to set the level of preference of the new SASL mechanism.
- * A value of 0 means that the mechanism is the most prefered one. The SASL mechanism must be
- * registered via {@link #registerSASLMechanism(String, Class)}
- *
- * @param name common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or KERBEROS_V4.
- * @param index preference position amongst all the implemented SASL mechanism. Starts with 0.
- */
- public static void supportSASLMechanism(String name, int index) {
- mechanismsPreferences.add(index, name);
- }
-
- /**
- * Un-supports an existing SASL mechanism. Once the mechanism has been unregistered it won't
- * be possible to authenticate users using the removed SASL mechanism. Note that the mechanism
- * is still registered, but will just not be used.
- *
- * @param name common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or KERBEROS_V4.
- */
- public static void unsupportSASLMechanism(String name) {
- mechanismsPreferences.remove(name);
- }
-
- /**
- * Returns the registerd SASLMechanism classes sorted by the level of preference.
- *
- * @return the registerd SASLMechanism classes sorted by the level of preference.
- */
- public static List<Class<? extends SASLMechanism>> getRegisterSASLMechanisms() {
- List<Class<? extends SASLMechanism>> answer = new ArrayList<Class<? extends SASLMechanism>>();
- for (String mechanismsPreference : mechanismsPreferences) {
- answer.add(implementedMechanisms.get(mechanismsPreference));
- }
- return answer;
- }
-
- SASLAuthentication(Connection connection) {
- super();
- this.connection = connection;
- this.init();
- }
-
- /**
- * Returns true if the server offered ANONYMOUS SASL as a way to authenticate users.
- *
- * @return true if the server offered ANONYMOUS SASL as a way to authenticate users.
- */
- public boolean hasAnonymousAuthentication() {
- return serverMechanisms.contains("ANONYMOUS");
- }
-
- /**
- * Returns true if the server offered SASL authentication besides ANONYMOUS SASL.
- *
- * @return true if the server offered SASL authentication besides ANONYMOUS SASL.
- */
- public boolean hasNonAnonymousAuthentication() {
- return !serverMechanisms.isEmpty() && (serverMechanisms.size() != 1 || !hasAnonymousAuthentication());
- }
-
- /**
- * Performs SASL authentication of the specified user. If SASL authentication was successful
- * then resource binding and session establishment will be performed. This method will return
- * the full JID provided by the server while binding a resource to the connection.<p>
- *
- * The server may assign a full JID with a username or resource different than the requested
- * by this method.
- *
- * @param username the username that is authenticating with the server.
- * @param resource the desired resource.
- * @param cbh the CallbackHandler used to get information from the user
- * @return the full JID provided by the server while binding a resource to the connection.
- * @throws XMPPException if an error occures while authenticating.
- */
- public String authenticate(String username, String resource, CallbackHandler cbh)
- throws XMPPException {
- // Locate the SASLMechanism to use
- String selectedMechanism = null;
- for (String mechanism : mechanismsPreferences) {
- if (implementedMechanisms.containsKey(mechanism) &&
- serverMechanisms.contains(mechanism)) {
- selectedMechanism = mechanism;
- break;
- }
- }
- if (selectedMechanism != null) {
- // A SASL mechanism was found. Authenticate using the selected mechanism and then
- // proceed to bind a resource
- try {
- Class<? extends SASLMechanism> mechanismClass = implementedMechanisms.get(selectedMechanism);
- Constructor<? extends SASLMechanism> constructor = mechanismClass.getConstructor(SASLAuthentication.class);
- currentMechanism = constructor.newInstance(this);
- // Trigger SASL authentication with the selected mechanism. We use
- // connection.getHost() since GSAPI requires the FQDN of the server, which
- // may not match the XMPP domain.
- currentMechanism.authenticate(username, connection.getHost(), cbh);
-
- // Wait until SASL negotiation finishes
- synchronized (this) {
- if (!saslNegotiated && !saslFailed) {
- try {
- wait(30000);
- }
- catch (InterruptedException e) {
- // Ignore
- }
- }
- }
-
- if (saslFailed) {
- // SASL authentication failed and the server may have closed the connection
- // so throw an exception
- if (errorCondition != null) {
- throw new XMPPException("SASL authentication " +
- selectedMechanism + " failed: " + errorCondition);
- }
- else {
- throw new XMPPException("SASL authentication failed using mechanism " +
- selectedMechanism);
- }
- }
-
- if (saslNegotiated) {
- // Bind a resource for this connection and
- return bindResourceAndEstablishSession(resource);
- } else {
- // SASL authentication failed
- }
- }
- catch (XMPPException e) {
- throw e;
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
- else {
- throw new XMPPException("SASL Authentication failed. No known authentication mechanisims.");
- }
- throw new XMPPException("SASL authentication failed");
- }
-
- /**
- * Performs SASL authentication of the specified user. If SASL authentication was successful
- * then resource binding and session establishment will be performed. This method will return
- * the full JID provided by the server while binding a resource to the connection.<p>
- *
- * The server may assign a full JID with a username or resource different than the requested
- * by this method.
- *
- * @param username the username that is authenticating with the server.
- * @param password the password to send to the server.
- * @param resource the desired resource.
- * @return the full JID provided by the server while binding a resource to the connection.
- * @throws XMPPException if an error occures while authenticating.
- */
- public String authenticate(String username, String password, String resource)
- throws XMPPException {
- // Locate the SASLMechanism to use
- String selectedMechanism = null;
- for (String mechanism : mechanismsPreferences) {
- if (implementedMechanisms.containsKey(mechanism) &&
- serverMechanisms.contains(mechanism)) {
- selectedMechanism = mechanism;
- break;
- }
- }
- if (selectedMechanism != null) {
- // A SASL mechanism was found. Authenticate using the selected mechanism and then
- // proceed to bind a resource
- try {
- Class<? extends SASLMechanism> mechanismClass = implementedMechanisms.get(selectedMechanism);
- Constructor<? extends SASLMechanism> constructor = mechanismClass.getConstructor(SASLAuthentication.class);
- currentMechanism = constructor.newInstance(this);
- // Trigger SASL authentication with the selected mechanism. We use
- // connection.getHost() since GSAPI requires the FQDN of the server, which
- // may not match the XMPP domain.
-
- //The serviceName is basically the value that XMPP server sends to the client as being the location
- //of the XMPP service we are trying to connect to. This should have the format: host [ "/" serv-name ]
- //as per RFC-2831 guidelines
- String serviceName = connection.getServiceName();
- currentMechanism.authenticate(username, connection.getHost(), serviceName, password);
-
- // Wait until SASL negotiation finishes
- synchronized (this) {
- if (!saslNegotiated && !saslFailed) {
- try {
- wait(30000);
- }
- catch (InterruptedException e) {
- // Ignore
- }
- }
- }
-
- if (saslFailed) {
- // SASL authentication failed and the server may have closed the connection
- // so throw an exception
- if (errorCondition != null) {
- throw new XMPPException("SASL authentication " +
- selectedMechanism + " failed: " + errorCondition);
- }
- else {
- throw new XMPPException("SASL authentication failed using mechanism " +
- selectedMechanism);
- }
- }
-
- if (saslNegotiated) {
- // Bind a resource for this connection and
- return bindResourceAndEstablishSession(resource);
- }
- else {
- // SASL authentication failed so try a Non-SASL authentication
- return new NonSASLAuthentication(connection)
- .authenticate(username, password, resource);
- }
- }
- catch (XMPPException e) {
- throw e;
- }
- catch (Exception e) {
- e.printStackTrace();
- // SASL authentication failed so try a Non-SASL authentication
- return new NonSASLAuthentication(connection)
- .authenticate(username, password, resource);
- }
- }
- else {
- // No SASL method was found so try a Non-SASL authentication
- return new NonSASLAuthentication(connection).authenticate(username, password, resource);
- }
- }
-
- /**
- * Performs ANONYMOUS SASL authentication. If SASL authentication was successful
- * then resource binding and session establishment will be performed. This method will return
- * the full JID provided by the server while binding a resource to the connection.<p>
- *
- * The server will assign a full JID with a randomly generated resource and possibly with
- * no username.
- *
- * @return the full JID provided by the server while binding a resource to the connection.
- * @throws XMPPException if an error occures while authenticating.
- */
- public String authenticateAnonymously() throws XMPPException {
- try {
- currentMechanism = new SASLAnonymous(this);
- currentMechanism.authenticate(null,null,null,"");
-
- // Wait until SASL negotiation finishes
- synchronized (this) {
- if (!saslNegotiated && !saslFailed) {
- try {
- wait(5000);
- }
- catch (InterruptedException e) {
- // Ignore
- }
- }
- }
-
- if (saslFailed) {
- // SASL authentication failed and the server may have closed the connection
- // so throw an exception
- if (errorCondition != null) {
- throw new XMPPException("SASL authentication failed: " + errorCondition);
- }
- else {
- throw new XMPPException("SASL authentication failed");
- }
- }
-
- if (saslNegotiated) {
- // Bind a resource for this connection and
- return bindResourceAndEstablishSession(null);
- }
- else {
- return new NonSASLAuthentication(connection).authenticateAnonymously();
- }
- } catch (IOException e) {
- return new NonSASLAuthentication(connection).authenticateAnonymously();
- }
- }
-
- private String bindResourceAndEstablishSession(String resource) throws XMPPException {
- // Wait until server sends response containing the <bind> element
- synchronized (this) {
- if (!resourceBinded) {
- try {
- wait(30000);
- }
- catch (InterruptedException e) {
- // Ignore
- }
- }
- }
-
- if (!resourceBinded) {
- // Server never offered resource binding
- throw new XMPPException("Resource binding not offered by server");
- }
-
- Bind bindResource = new Bind();
- bindResource.setResource(resource);
-
- PacketCollector collector = connection
- .createPacketCollector(new PacketIDFilter(bindResource.getPacketID()));
- // Send the packet
- connection.sendPacket(bindResource);
- // Wait up to a certain number of seconds for a response from the server.
- Bind response = (Bind) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
- collector.cancel();
- if (response == null) {
- throw new XMPPException("No response from the server.");
- }
- // If the server replied with an error, throw an exception.
- else if (response.getType() == IQ.Type.ERROR) {
- throw new XMPPException(response.getError());
- }
- String userJID = response.getJid();
-
- if (sessionSupported) {
- Session session = new Session();
- collector = connection.createPacketCollector(new PacketIDFilter(session.getPacketID()));
- // Send the packet
- connection.sendPacket(session);
- // Wait up to a certain number of seconds for a response from the server.
- IQ ack = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
- collector.cancel();
- if (ack == null) {
- throw new XMPPException("No response from the server.");
- }
- // If the server replied with an error, throw an exception.
- else if (ack.getType() == IQ.Type.ERROR) {
- throw new XMPPException(ack.getError());
- }
- }
- return userJID;
- }
-
- /**
- * Sets the available SASL mechanism reported by the server. The server will report the
- * available SASL mechanism once the TLS negotiation was successful. This information is
- * stored and will be used when doing the authentication for logging in the user.
- *
- * @param mechanisms collection of strings with the available SASL mechanism reported
- * by the server.
- */
- void setAvailableSASLMethods(Collection<String> mechanisms) {
- this.serverMechanisms = mechanisms;
- }
-
- /**
- * Returns true if the user was able to authenticate with the server usins SASL.
- *
- * @return true if the user was able to authenticate with the server usins SASL.
- */
- public boolean isAuthenticated() {
- return saslNegotiated;
- }
-
- /**
- * The server is challenging the SASL authentication we just sent. Forward the challenge
- * to the current SASLMechanism we are using. The SASLMechanism will send a response to
- * the server. The length of the challenge-response sequence varies according to the
- * SASLMechanism in use.
- *
- * @param challenge a base64 encoded string representing the challenge.
- * @throws IOException If a network error occures while authenticating.
- */
- void challengeReceived(String challenge) throws IOException {
- currentMechanism.challengeReceived(challenge);
- }
-
- /**
- * Notification message saying that SASL authentication was successful. The next step
- * would be to bind the resource.
- */
- void authenticated() {
- synchronized (this) {
- saslNegotiated = true;
- // Wake up the thread that is waiting in the #authenticate method
- notify();
- }
- }
-
- /**
- * Notification message saying that SASL authentication has failed. The server may have
- * closed the connection depending on the number of possible retries.
- *
- * @deprecated replaced by {@see #authenticationFailed(String)}.
- */
- void authenticationFailed() {
- authenticationFailed(null);
- }
-
- /**
- * Notification message saying that SASL authentication has failed. The server may have
- * closed the connection depending on the number of possible retries.
- *
- * @param condition the error condition provided by the server.
- */
- void authenticationFailed(String condition) {
- synchronized (this) {
- saslFailed = true;
- errorCondition = condition;
- // Wake up the thread that is waiting in the #authenticate method
- notify();
- }
- }
-
- /**
- * Notification message saying that the server requires the client to bind a
- * resource to the stream.
- */
- void bindingRequired() {
- synchronized (this) {
- resourceBinded = true;
- // Wake up the thread that is waiting in the #authenticate method
- notify();
- }
- }
-
- public void send(Packet stanza) {
- connection.sendPacket(stanza);
- }
-
- /**
- * Notification message saying that the server supports sessions. When a server supports
- * sessions the client needs to send a Session packet after successfully binding a resource
- * for the session.
- */
- void sessionsSupported() {
- sessionSupported = true;
- }
-
- /**
- * Initializes the internal state in order to be able to be reused. The authentication
- * is used by the connection at the first login and then reused after the connection
- * is disconnected and then reconnected.
- */
- protected void init() {
- saslNegotiated = false;
- saslFailed = false;
- resourceBinded = false;
- sessionSupported = false;
- }
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2003-2007 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smack;
+
+import org.jivesoftware.smack.filter.PacketIDFilter;
+import org.jivesoftware.smack.packet.Bind;
+import org.jivesoftware.smack.packet.IQ;
+import org.jivesoftware.smack.packet.Packet;
+import org.jivesoftware.smack.packet.Session;
+import org.jivesoftware.smack.sasl.*;
+
+import javax.security.auth.callback.CallbackHandler;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.*;
+
+/**
+ * <p>This class is responsible authenticating the user using SASL, binding the resource
+ * to the connection and establishing a session with the server.</p>
+ *
+ * <p>Once TLS has been negotiated (i.e. the connection has been secured) it is possible to
+ * register with the server, authenticate using Non-SASL or authenticate using SASL. If the
+ * server supports SASL then Smack will first try to authenticate using SASL. But if that
+ * fails then Non-SASL will be tried.</p>
+ *
+ * <p>The server may support many SASL mechanisms to use for authenticating. Out of the box
+ * Smack provides several SASL mechanisms, but it is possible to register new SASL Mechanisms. Use
+ * {@link #registerSASLMechanism(String, Class)} to register a new mechanisms. A registered
+ * mechanism wont be used until {@link #supportSASLMechanism(String, int)} is called. By default,
+ * the list of supported SASL mechanisms is determined from the {@link SmackConfiguration}. </p>
+ *
+ * <p>Once the user has been authenticated with SASL, it is necessary to bind a resource for
+ * the connection. If no resource is passed in {@link #authenticate(String, String, String)}
+ * then the server will assign a resource for the connection. In case a resource is passed
+ * then the server will receive the desired resource but may assign a modified resource for
+ * the connection.</p>
+ *
+ * <p>Once a resource has been binded and if the server supports sessions then Smack will establish
+ * a session so that instant messaging and presence functionalities may be used.</p>
+ *
+ * @see org.jivesoftware.smack.sasl.SASLMechanism
+ *
+ * @author Gaston Dombiak
+ * @author Jay Kline
+ */
+public class SASLAuthentication implements UserAuthentication {
+
+ private static Map<String, Class<? extends SASLMechanism>> implementedMechanisms = new HashMap<String, Class<? extends SASLMechanism>>();
+ private static List<String> mechanismsPreferences = new ArrayList<String>();
+
+ private Connection connection;
+ private Collection<String> serverMechanisms = new ArrayList<String>();
+ private SASLMechanism currentMechanism = null;
+ /**
+ * Boolean indicating if SASL negotiation has finished and was successful.
+ */
+ private boolean saslNegotiated;
+ /**
+ * Boolean indication if SASL authentication has failed. When failed the server may end
+ * the connection.
+ */
+ private boolean saslFailed;
+ private boolean resourceBinded;
+ private boolean sessionSupported;
+ /**
+ * The SASL related error condition if there was one provided by the server.
+ */
+ private String errorCondition;
+
+ static {
+
+ // Register SASL mechanisms supported by Smack
+ registerSASLMechanism("EXTERNAL", SASLExternalMechanism.class);
+ registerSASLMechanism("GSSAPI", SASLGSSAPIMechanism.class);
+ registerSASLMechanism("DIGEST-MD5", SASLDigestMD5Mechanism.class);
+ registerSASLMechanism("CRAM-MD5", SASLCramMD5Mechanism.class);
+ registerSASLMechanism("PLAIN", SASLPlainMechanism.class);
+ registerSASLMechanism("ANONYMOUS", SASLAnonymous.class);
+
+ supportSASLMechanism("GSSAPI",0);
+ supportSASLMechanism("DIGEST-MD5",1);
+ supportSASLMechanism("CRAM-MD5",2);
+ supportSASLMechanism("PLAIN",3);
+ supportSASLMechanism("ANONYMOUS",4);
+
+ }
+
+ /**
+ * Registers a new SASL mechanism
+ *
+ * @param name common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or KERBEROS_V4.
+ * @param mClass a SASLMechanism subclass.
+ */
+ public static void registerSASLMechanism(String name, Class<? extends SASLMechanism> mClass) {
+ implementedMechanisms.put(name, mClass);
+ }
+
+ /**
+ * Unregisters an existing SASL mechanism. Once the mechanism has been unregistered it won't
+ * be possible to authenticate users using the removed SASL mechanism. It also removes the
+ * mechanism from the supported list.
+ *
+ * @param name common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or KERBEROS_V4.
+ */
+ public static void unregisterSASLMechanism(String name) {
+ implementedMechanisms.remove(name);
+ mechanismsPreferences.remove(name);
+ }
+
+
+ /**
+ * Registers a new SASL mechanism in the specified preference position. The client will try
+ * to authenticate using the most prefered SASL mechanism that is also supported by the server.
+ * The SASL mechanism must be registered via {@link #registerSASLMechanism(String, Class)}
+ *
+ * @param name common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or KERBEROS_V4.
+ */
+ public static void supportSASLMechanism(String name) {
+ mechanismsPreferences.add(0, name);
+ }
+
+ /**
+ * Registers a new SASL mechanism in the specified preference position. The client will try
+ * to authenticate using the most prefered SASL mechanism that is also supported by the server.
+ * Use the <tt>index</tt> parameter to set the level of preference of the new SASL mechanism.
+ * A value of 0 means that the mechanism is the most prefered one. The SASL mechanism must be
+ * registered via {@link #registerSASLMechanism(String, Class)}
+ *
+ * @param name common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or KERBEROS_V4.
+ * @param index preference position amongst all the implemented SASL mechanism. Starts with 0.
+ */
+ public static void supportSASLMechanism(String name, int index) {
+ mechanismsPreferences.add(index, name);
+ }
+
+ /**
+ * Un-supports an existing SASL mechanism. Once the mechanism has been unregistered it won't
+ * be possible to authenticate users using the removed SASL mechanism. Note that the mechanism
+ * is still registered, but will just not be used.
+ *
+ * @param name common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or KERBEROS_V4.
+ */
+ public static void unsupportSASLMechanism(String name) {
+ mechanismsPreferences.remove(name);
+ }
+
+ /**
+ * Returns the registerd SASLMechanism classes sorted by the level of preference.
+ *
+ * @return the registerd SASLMechanism classes sorted by the level of preference.
+ */
+ public static List<Class<? extends SASLMechanism>> getRegisterSASLMechanisms() {
+ List<Class<? extends SASLMechanism>> answer = new ArrayList<Class<? extends SASLMechanism>>();
+ for (String mechanismsPreference : mechanismsPreferences) {
+ answer.add(implementedMechanisms.get(mechanismsPreference));
+ }
+ return answer;
+ }
+
+ SASLAuthentication(Connection connection) {
+ super();
+ this.connection = connection;
+ this.init();
+ }
+
+ /**
+ * Returns true if the server offered ANONYMOUS SASL as a way to authenticate users.
+ *
+ * @return true if the server offered ANONYMOUS SASL as a way to authenticate users.
+ */
+ public boolean hasAnonymousAuthentication() {
+ return serverMechanisms.contains("ANONYMOUS");
+ }
+
+ /**
+ * Returns true if the server offered SASL authentication besides ANONYMOUS SASL.
+ *
+ * @return true if the server offered SASL authentication besides ANONYMOUS SASL.
+ */
+ public boolean hasNonAnonymousAuthentication() {
+ return !serverMechanisms.isEmpty() && (serverMechanisms.size() != 1 || !hasAnonymousAuthentication());
+ }
+
+ /**
+ * Performs SASL authentication of the specified user. If SASL authentication was successful
+ * then resource binding and session establishment will be performed. This method will return
+ * the full JID provided by the server while binding a resource to the connection.<p>
+ *
+ * The server may assign a full JID with a username or resource different than the requested
+ * by this method.
+ *
+ * @param username the username that is authenticating with the server.
+ * @param resource the desired resource.
+ * @param cbh the CallbackHandler used to get information from the user
+ * @return the full JID provided by the server while binding a resource to the connection.
+ * @throws XMPPException if an error occures while authenticating.
+ */
+ public String authenticate(String username, String resource, CallbackHandler cbh)
+ throws XMPPException {
+ // Locate the SASLMechanism to use
+ String selectedMechanism = null;
+ for (String mechanism : mechanismsPreferences) {
+ if (implementedMechanisms.containsKey(mechanism) &&
+ serverMechanisms.contains(mechanism)) {
+ selectedMechanism = mechanism;
+ break;
+ }
+ }
+ if (selectedMechanism != null) {
+ // A SASL mechanism was found. Authenticate using the selected mechanism and then
+ // proceed to bind a resource
+ try {
+ Class<? extends SASLMechanism> mechanismClass = implementedMechanisms.get(selectedMechanism);
+ Constructor<? extends SASLMechanism> constructor = mechanismClass.getConstructor(SASLAuthentication.class);
+ currentMechanism = constructor.newInstance(this);
+ // Trigger SASL authentication with the selected mechanism. We use
+ // connection.getHost() since GSAPI requires the FQDN of the server, which
+ // may not match the XMPP domain.
+ currentMechanism.authenticate(username, connection.getHost(), cbh);
+
+ // Wait until SASL negotiation finishes
+ synchronized (this) {
+ if (!saslNegotiated && !saslFailed) {
+ try {
+ wait(30000);
+ }
+ catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+ }
+
+ if (saslFailed) {
+ // SASL authentication failed and the server may have closed the connection
+ // so throw an exception
+ if (errorCondition != null) {
+ throw new XMPPException("SASL authentication " +
+ selectedMechanism + " failed: " + errorCondition);
+ }
+ else {
+ throw new XMPPException("SASL authentication failed using mechanism " +
+ selectedMechanism);
+ }
+ }
+
+ if (saslNegotiated) {
+ // Bind a resource for this connection and
+ return bindResourceAndEstablishSession(resource);
+ } else {
+ // SASL authentication failed
+ }
+ }
+ catch (XMPPException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ else {
+ throw new XMPPException("SASL Authentication failed. No known authentication mechanisims.");
+ }
+ throw new XMPPException("SASL authentication failed");
+ }
+
+ /**
+ * Performs SASL authentication of the specified user. If SASL authentication was successful
+ * then resource binding and session establishment will be performed. This method will return
+ * the full JID provided by the server while binding a resource to the connection.<p>
+ *
+ * The server may assign a full JID with a username or resource different than the requested
+ * by this method.
+ *
+ * @param username the username that is authenticating with the server.
+ * @param password the password to send to the server.
+ * @param resource the desired resource.
+ * @return the full JID provided by the server while binding a resource to the connection.
+ * @throws XMPPException if an error occures while authenticating.
+ */
+ public String authenticate(String username, String password, String resource)
+ throws XMPPException {
+ // Locate the SASLMechanism to use
+ String selectedMechanism = null;
+ for (String mechanism : mechanismsPreferences) {
+ if (implementedMechanisms.containsKey(mechanism) &&
+ serverMechanisms.contains(mechanism)) {
+ selectedMechanism = mechanism;
+ break;
+ }
+ }
+ if (selectedMechanism != null) {
+ // A SASL mechanism was found. Authenticate using the selected mechanism and then
+ // proceed to bind a resource
+ try {
+ Class<? extends SASLMechanism> mechanismClass = implementedMechanisms.get(selectedMechanism);
+ Constructor<? extends SASLMechanism> constructor = mechanismClass.getConstructor(SASLAuthentication.class);
+ currentMechanism = constructor.newInstance(this);
+ // Trigger SASL authentication with the selected mechanism. We use
+ // connection.getHost() since GSAPI requires the FQDN of the server, which
+ // may not match the XMPP domain.
+
+ //The serviceName is basically the value that XMPP server sends to the client as being the location
+ //of the XMPP service we are trying to connect to. This should have the format: host [ "/" serv-name ]
+ //as per RFC-2831 guidelines
+ String serviceName = connection.getServiceName();
+ currentMechanism.authenticate(username, connection.getHost(), serviceName, password);
+
+ // Wait until SASL negotiation finishes
+ synchronized (this) {
+ if (!saslNegotiated && !saslFailed) {
+ try {
+ wait(30000);
+ }
+ catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+ }
+
+ if (saslFailed) {
+ // SASL authentication failed and the server may have closed the connection
+ // so throw an exception
+ if (errorCondition != null) {
+ throw new XMPPException("SASL authentication " +
+ selectedMechanism + " failed: " + errorCondition);
+ }
+ else {
+ throw new XMPPException("SASL authentication failed using mechanism " +
+ selectedMechanism);
+ }
+ }
+
+ if (saslNegotiated) {
+ // Bind a resource for this connection and
+ return bindResourceAndEstablishSession(resource);
+ }
+ else {
+ // SASL authentication failed so try a Non-SASL authentication
+ return new NonSASLAuthentication(connection)
+ .authenticate(username, password, resource);
+ }
+ }
+ catch (XMPPException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ // SASL authentication failed so try a Non-SASL authentication
+ return new NonSASLAuthentication(connection)
+ .authenticate(username, password, resource);
+ }
+ }
+ else {
+ // No SASL method was found so try a Non-SASL authentication
+ return new NonSASLAuthentication(connection).authenticate(username, password, resource);
+ }
+ }
+
+ /**
+ * Performs ANONYMOUS SASL authentication. If SASL authentication was successful
+ * then resource binding and session establishment will be performed. This method will return
+ * the full JID provided by the server while binding a resource to the connection.<p>
+ *
+ * The server will assign a full JID with a randomly generated resource and possibly with
+ * no username.
+ *
+ * @return the full JID provided by the server while binding a resource to the connection.
+ * @throws XMPPException if an error occures while authenticating.
+ */
+ public String authenticateAnonymously() throws XMPPException {
+ try {
+ currentMechanism = new SASLAnonymous(this);
+ currentMechanism.authenticate(null,null,null,"");
+
+ // Wait until SASL negotiation finishes
+ synchronized (this) {
+ if (!saslNegotiated && !saslFailed) {
+ try {
+ wait(5000);
+ }
+ catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+ }
+
+ if (saslFailed) {
+ // SASL authentication failed and the server may have closed the connection
+ // so throw an exception
+ if (errorCondition != null) {
+ throw new XMPPException("SASL authentication failed: " + errorCondition);
+ }
+ else {
+ throw new XMPPException("SASL authentication failed");
+ }
+ }
+
+ if (saslNegotiated) {
+ // Bind a resource for this connection and
+ return bindResourceAndEstablishSession(null);
+ }
+ else {
+ return new NonSASLAuthentication(connection).authenticateAnonymously();
+ }
+ } catch (IOException e) {
+ return new NonSASLAuthentication(connection).authenticateAnonymously();
+ }
+ }
+
+ private String bindResourceAndEstablishSession(String resource) throws XMPPException {
+ // Wait until server sends response containing the <bind> element
+ synchronized (this) {
+ if (!resourceBinded) {
+ try {
+ wait(30000);
+ }
+ catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+ }
+
+ if (!resourceBinded) {
+ // Server never offered resource binding
+ throw new XMPPException("Resource binding not offered by server");
+ }
+
+ Bind bindResource = new Bind();
+ bindResource.setResource(resource);
+
+ PacketCollector collector = connection
+ .createPacketCollector(new PacketIDFilter(bindResource.getPacketID()));
+ // Send the packet
+ connection.sendPacket(bindResource);
+ // Wait up to a certain number of seconds for a response from the server.
+ Bind response = (Bind) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
+ collector.cancel();
+ if (response == null) {
+ throw new XMPPException("No response from the server.");
+ }
+ // If the server replied with an error, throw an exception.
+ else if (response.getType() == IQ.Type.ERROR) {
+ throw new XMPPException(response.getError());
+ }
+ String userJID = response.getJid();
+
+ if (sessionSupported) {
+ Session session = new Session();
+ collector = connection.createPacketCollector(new PacketIDFilter(session.getPacketID()));
+ // Send the packet
+ connection.sendPacket(session);
+ // Wait up to a certain number of seconds for a response from the server.
+ IQ ack = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
+ collector.cancel();
+ if (ack == null) {
+ throw new XMPPException("No response from the server.");
+ }
+ // If the server replied with an error, throw an exception.
+ else if (ack.getType() == IQ.Type.ERROR) {
+ throw new XMPPException(ack.getError());
+ }
+ }
+ return userJID;
+ }
+
+ /**
+ * Sets the available SASL mechanism reported by the server. The server will report the
+ * available SASL mechanism once the TLS negotiation was successful. This information is
+ * stored and will be used when doing the authentication for logging in the user.
+ *
+ * @param mechanisms collection of strings with the available SASL mechanism reported
+ * by the server.
+ */
+ void setAvailableSASLMethods(Collection<String> mechanisms) {
+ this.serverMechanisms = mechanisms;
+ }
+
+ /**
+ * Returns true if the user was able to authenticate with the server usins SASL.
+ *
+ * @return true if the user was able to authenticate with the server usins SASL.
+ */
+ public boolean isAuthenticated() {
+ return saslNegotiated;
+ }
+
+ /**
+ * The server is challenging the SASL authentication we just sent. Forward the challenge
+ * to the current SASLMechanism we are using. The SASLMechanism will send a response to
+ * the server. The length of the challenge-response sequence varies according to the
+ * SASLMechanism in use.
+ *
+ * @param challenge a base64 encoded string representing the challenge.
+ * @throws IOException If a network error occures while authenticating.
+ */
+ void challengeReceived(String challenge) throws IOException {
+ currentMechanism.challengeReceived(challenge);
+ }
+
+ /**
+ * Notification message saying that SASL authentication was successful. The next step
+ * would be to bind the resource.
+ */
+ void authenticated() {
+ synchronized (this) {
+ saslNegotiated = true;
+ // Wake up the thread that is waiting in the #authenticate method
+ notify();
+ }
+ }
+
+ /**
+ * Notification message saying that SASL authentication has failed. The server may have
+ * closed the connection depending on the number of possible retries.
+ *
+ * @deprecated replaced by {@see #authenticationFailed(String)}.
+ */
+ void authenticationFailed() {
+ authenticationFailed(null);
+ }
+
+ /**
+ * Notification message saying that SASL authentication has failed. The server may have
+ * closed the connection depending on the number of possible retries.
+ *
+ * @param condition the error condition provided by the server.
+ */
+ void authenticationFailed(String condition) {
+ synchronized (this) {
+ saslFailed = true;
+ errorCondition = condition;
+ // Wake up the thread that is waiting in the #authenticate method
+ notify();
+ }
+ }
+
+ /**
+ * Notification message saying that the server requires the client to bind a
+ * resource to the stream.
+ */
+ void bindingRequired() {
+ synchronized (this) {
+ resourceBinded = true;
+ // Wake up the thread that is waiting in the #authenticate method
+ notify();
+ }
+ }
+
+ public void send(Packet stanza) {
+ connection.sendPacket(stanza);
+ }
+
+ /**
+ * Notification message saying that the server supports sessions. When a server supports
+ * sessions the client needs to send a Session packet after successfully binding a resource
+ * for the session.
+ */
+ void sessionsSupported() {
+ sessionSupported = true;
+ }
+
+ /**
+ * Initializes the internal state in order to be able to be reused. The authentication
+ * is used by the connection at the first login and then reused after the connection
+ * is disconnected and then reconnected.
+ */
+ protected void init() {
+ saslNegotiated = false;
+ saslFailed = false;
+ resourceBinded = false;
+ sessionSupported = false;
+ }
} \ No newline at end of file
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/SmackError.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/SmackError.java
index af22e7c0e..8527876b6 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/SmackError.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/SmackError.java
@@ -1,24 +1,24 @@
-package org.jivesoftware.smack;
-
-public enum SmackError {
- NO_RESPONSE_FROM_SERVER("No response from server.");
-
- private String message;
-
- private SmackError(String errMessage) {
- message = errMessage;
- }
-
- public String getErrorMessage() {
- return message;
- }
-
- public static SmackError getErrorCode(String message) {
- for (SmackError code : values()) {
- if (code.message.equals(message)) {
- return code;
- }
- }
- return null;
- }
-}
+package org.jivesoftware.smack;
+
+public enum SmackError {
+ NO_RESPONSE_FROM_SERVER("No response from server.");
+
+ private String message;
+
+ private SmackError(String errMessage) {
+ message = errMessage;
+ }
+
+ public String getErrorMessage() {
+ return message;
+ }
+
+ public static SmackError getErrorCode(String message) {
+ for (SmackError code : values()) {
+ if (code.message.equals(message)) {
+ return code;
+ }
+ }
+ return null;
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/UserAuthentication.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/UserAuthentication.java
index 8f0dd505a..728428b65 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/UserAuthentication.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/UserAuthentication.java
@@ -1,79 +1,79 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- * Copyright 2003-2007 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smack;
-
-import javax.security.auth.callback.CallbackHandler;
-
-/**
- * There are two ways to authenticate a user with a server. Using SASL or Non-SASL
- * authentication. This interface makes {@link SASLAuthentication} and
- * {@link NonSASLAuthentication} polyphormic.
- *
- * @author Gaston Dombiak
- * @author Jay Kline
- */
-interface UserAuthentication {
-
- /**
- * Authenticates the user with the server. This method will return the full JID provided by
- * the server. The server may assign a full JID with a username and resource different than
- * requested by this method.
- *
- * Note that using callbacks is the prefered method of authenticating users since it allows
- * more flexability in the mechanisms used.
- *
- * @param username the requested username (authorization ID) for authenticating to the server
- * @param resource the requested resource.
- * @param cbh the CallbackHandler used to obtain authentication ID, password, or other
- * information
- * @return the full JID provided by the server while binding a resource for the connection.
- * @throws XMPPException if an error occurs while authenticating.
- */
- String authenticate(String username, String resource, CallbackHandler cbh) throws
- XMPPException;
-
- /**
- * Authenticates the user with the server. This method will return the full JID provided by
- * the server. The server may assign a full JID with a username and resource different than
- * the requested by this method.
- *
- * It is recommended that @{link #authenticate(String, String, CallbackHandler)} be used instead
- * since it provides greater flexability in authenticaiton and authorization.
- *
- * @param username the username that is authenticating with the server.
- * @param password the password to send to the server.
- * @param resource the desired resource.
- * @return the full JID provided by the server while binding a resource for the connection.
- * @throws XMPPException if an error occures while authenticating.
- */
- String authenticate(String username, String password, String resource) throws
- XMPPException;
-
- /**
- * Performs an anonymous authentication with the server. The server will created a new full JID
- * for this connection. An exception will be thrown if the server does not support anonymous
- * authentication.
- *
- * @return the full JID provided by the server while binding a resource for the connection.
- * @throws XMPPException if an error occures while authenticating.
- */
- String authenticateAnonymously() throws XMPPException;
-}
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2003-2007 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smack;
+
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ * There are two ways to authenticate a user with a server. Using SASL or Non-SASL
+ * authentication. This interface makes {@link SASLAuthentication} and
+ * {@link NonSASLAuthentication} polyphormic.
+ *
+ * @author Gaston Dombiak
+ * @author Jay Kline
+ */
+interface UserAuthentication {
+
+ /**
+ * Authenticates the user with the server. This method will return the full JID provided by
+ * the server. The server may assign a full JID with a username and resource different than
+ * requested by this method.
+ *
+ * Note that using callbacks is the prefered method of authenticating users since it allows
+ * more flexability in the mechanisms used.
+ *
+ * @param username the requested username (authorization ID) for authenticating to the server
+ * @param resource the requested resource.
+ * @param cbh the CallbackHandler used to obtain authentication ID, password, or other
+ * information
+ * @return the full JID provided by the server while binding a resource for the connection.
+ * @throws XMPPException if an error occurs while authenticating.
+ */
+ String authenticate(String username, String resource, CallbackHandler cbh) throws
+ XMPPException;
+
+ /**
+ * Authenticates the user with the server. This method will return the full JID provided by
+ * the server. The server may assign a full JID with a username and resource different than
+ * the requested by this method.
+ *
+ * It is recommended that @{link #authenticate(String, String, CallbackHandler)} be used instead
+ * since it provides greater flexability in authenticaiton and authorization.
+ *
+ * @param username the username that is authenticating with the server.
+ * @param password the password to send to the server.
+ * @param resource the desired resource.
+ * @return the full JID provided by the server while binding a resource for the connection.
+ * @throws XMPPException if an error occures while authenticating.
+ */
+ String authenticate(String username, String password, String resource) throws
+ XMPPException;
+
+ /**
+ * Performs an anonymous authentication with the server. The server will created a new full JID
+ * for this connection. An exception will be thrown if the server does not support anonymous
+ * authentication.
+ *
+ * @return the full JID provided by the server while binding a resource for the connection.
+ * @throws XMPPException if an error occures while authenticating.
+ */
+ String authenticateAnonymously() throws XMPPException;
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/filter/IQTypeFilter.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/filter/IQTypeFilter.java
index dbab1c3af..efe600307 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/filter/IQTypeFilter.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/filter/IQTypeFilter.java
@@ -1,48 +1,48 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- * Copyright 2003-2006 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smack.filter;
-
-import org.jivesoftware.smack.packet.IQ;
-import org.jivesoftware.smack.packet.Packet;
-
-/**
- * A filter for IQ packet types. Returns true only if the packet is an IQ packet
- * and it matches the type provided in the constructor.
- *
- * @author Alexander Wenckus
- *
- */
-public class IQTypeFilter implements PacketFilter {
-
- private IQ.Type type;
-
- public IQTypeFilter(IQ.Type type) {
- this.type = type;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.jivesoftware.smack.filter.PacketFilter#accept(org.jivesoftware.smack.packet.Packet)
- */
- public boolean accept(Packet packet) {
- return (packet instanceof IQ && ((IQ) packet).getType().equals(type));
- }
-}
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2003-2006 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smack.filter;
+
+import org.jivesoftware.smack.packet.IQ;
+import org.jivesoftware.smack.packet.Packet;
+
+/**
+ * A filter for IQ packet types. Returns true only if the packet is an IQ packet
+ * and it matches the type provided in the constructor.
+ *
+ * @author Alexander Wenckus
+ *
+ */
+public class IQTypeFilter implements PacketFilter {
+
+ private IQ.Type type;
+
+ public IQTypeFilter(IQ.Type type) {
+ this.type = type;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jivesoftware.smack.filter.PacketFilter#accept(org.jivesoftware.smack.packet.Packet)
+ */
+ public boolean accept(Packet packet) {
+ return (packet instanceof IQ && ((IQ) packet).getType().equals(type));
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Bind.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Bind.java
index 07cd1934e..fa150147f 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Bind.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Bind.java
@@ -1,71 +1,71 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- * Copyright 2003-2007 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smack.packet;
-
-/**
- * IQ packet used by Smack to bind a resource and to obtain the jid assigned by the server.
- * There are two ways to bind a resource. One is simply sending an empty Bind packet where the
- * server will assign a new resource for this connection. The other option is to set a desired
- * resource but the server may return a modified version of the sent resource.<p>
- *
- * For more information refer to the following
- * <a href=http://www.xmpp.org/specs/rfc3920.html#bind>link</a>.
- *
- * @author Gaston Dombiak
- */
-public class Bind extends IQ {
-
- private String resource = null;
- private String jid = null;
-
- public Bind() {
- setType(IQ.Type.SET);
- }
-
- public String getResource() {
- return resource;
- }
-
- public void setResource(String resource) {
- this.resource = resource;
- }
-
- public String getJid() {
- return jid;
- }
-
- public void setJid(String jid) {
- this.jid = jid;
- }
-
- public String getChildElementXML() {
- StringBuilder buf = new StringBuilder();
- buf.append("<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">");
- if (resource != null) {
- buf.append("<resource>").append(resource).append("</resource>");
- }
- if (jid != null) {
- buf.append("<jid>").append(jid).append("</jid>");
- }
- buf.append("</bind>");
- return buf.toString();
- }
-}
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2003-2007 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smack.packet;
+
+/**
+ * IQ packet used by Smack to bind a resource and to obtain the jid assigned by the server.
+ * There are two ways to bind a resource. One is simply sending an empty Bind packet where the
+ * server will assign a new resource for this connection. The other option is to set a desired
+ * resource but the server may return a modified version of the sent resource.<p>
+ *
+ * For more information refer to the following
+ * <a href=http://www.xmpp.org/specs/rfc3920.html#bind>link</a>.
+ *
+ * @author Gaston Dombiak
+ */
+public class Bind extends IQ {
+
+ private String resource = null;
+ private String jid = null;
+
+ public Bind() {
+ setType(IQ.Type.SET);
+ }
+
+ public String getResource() {
+ return resource;
+ }
+
+ public void setResource(String resource) {
+ this.resource = resource;
+ }
+
+ public String getJid() {
+ return jid;
+ }
+
+ public void setJid(String jid) {
+ this.jid = jid;
+ }
+
+ public String getChildElementXML() {
+ StringBuilder buf = new StringBuilder();
+ buf.append("<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">");
+ if (resource != null) {
+ buf.append("<resource>").append(resource).append("</resource>");
+ }
+ if (jid != null) {
+ buf.append("<jid>").append(jid).append("</jid>");
+ }
+ buf.append("</bind>");
+ return buf.toString();
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Privacy.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Privacy.java
index a62d578a8..3af6c4b72 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Privacy.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Privacy.java
@@ -1,323 +1,323 @@
-/**
- * $Revision$
- * $Date$
- *
- * Copyright 2006-2007 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smack.packet;
-
-import java.util.*;
-
-/**
- * A Privacy IQ Packet, is used by the {@link org.jivesoftware.smack.PrivacyListManager}
- * and {@link org.jivesoftware.smack.provider.PrivacyProvider} to allow and block
- * communications from other users. It contains the appropriate structure to suit
- * user-defined privacy lists. Different configured Privacy packages are used in the
- * server & manager communication in order to:
- * <ul>
- * <li>Retrieving one's privacy lists.
- * <li>Adding, removing, and editing one's privacy lists.
- * <li>Setting, changing, or declining active lists.
- * <li>Setting, changing, or declining the default list (i.e., the list that is active by default).
- * </ul>
- * Privacy Items can handle different kind of blocking communications based on JID, group,
- * subscription type or globally {@link PrivacyItem}
- *
- * @author Francisco Vives
- */
-public class Privacy extends IQ {
- /** declineActiveList is true when the user declines the use of the active list **/
- private boolean declineActiveList=false;
- /** activeName is the name associated with the active list set for the session **/
- private String activeName;
- /** declineDefaultList is true when the user declines the use of the default list **/
- private boolean declineDefaultList=false;
- /** defaultName is the name of the default list that applies to the user as a whole **/
- private String defaultName;
- /** itemLists holds the set of privacy items classified in lists. It is a map where the
- * key is the name of the list and the value a collection with privacy items. **/
- private Map<String, List<PrivacyItem>> itemLists = new HashMap<String, List<PrivacyItem>>();
-
- /**
- * Set or update a privacy list with privacy items.
- *
- * @param listName the name of the new privacy list.
- * @param listItem the {@link PrivacyItem} that rules the list.
- * @return the privacy List.
- */
- public List<PrivacyItem> setPrivacyList(String listName, List<PrivacyItem> listItem) {
- // Add new list to the itemLists
- this.getItemLists().put(listName, listItem);
- return listItem;
- }
-
- /**
- * Set the active list based on the default list.
- *
- * @return the active List.
- */
- public List<PrivacyItem> setActivePrivacyList() {
- this.setActiveName(this.getDefaultName());
- return this.getItemLists().get(this.getActiveName());
- }
-
- /**
- * Deletes an existing privacy list. If the privacy list being deleted was the default list
- * then the user will end up with no default list. Therefore, the user will have to set a new
- * default list.
- *
- * @param listName the name of the list being deleted.
- */
- public void deletePrivacyList(String listName) {
- // Remove the list from the cache
- this.getItemLists().remove(listName);
-
- // Check if deleted list was the default list
- if (this.getDefaultName() != null && listName.equals(this.getDefaultName())) {
- this.setDefaultName(null);
- }
- }
-
- /**
- * Returns the active privacy list or <tt>null</tt> if none was found.
- *
- * @return list with {@link PrivacyItem} or <tt>null</tt> if none was found.
- */
- public List<PrivacyItem> getActivePrivacyList() {
- // Check if we have the default list
- if (this.getActiveName() == null) {
- return null;
- } else {
- return this.getItemLists().get(this.getActiveName());
- }
- }
-
- /**
- * Returns the default privacy list or <tt>null</tt> if none was found.
- *
- * @return list with {@link PrivacyItem} or <tt>null</tt> if none was found.
- */
- public List<PrivacyItem> getDefaultPrivacyList() {
- // Check if we have the default list
- if (this.getDefaultName() == null) {
- return null;
- } else {
- return this.getItemLists().get(this.getDefaultName());
- }
- }
-
- /**
- * Returns a specific privacy list.
- *
- * @param listName the name of the list to get.
- * @return a List with {@link PrivacyItem}
- */
- public List<PrivacyItem> getPrivacyList(String listName) {
- return this.getItemLists().get(listName);
- }
-
- /**
- * Returns the privacy item in the specified order.
- *
- * @param listName the name of the privacy list.
- * @param order the order of the element.
- * @return a List with {@link PrivacyItem}
- */
- public PrivacyItem getItem(String listName, int order) {
- Iterator<PrivacyItem> values = getPrivacyList(listName).iterator();
- PrivacyItem itemFound = null;
- while (itemFound == null && values.hasNext()) {
- PrivacyItem element = values.next();
- if (element.getOrder() == order) {
- itemFound = element;
- }
- }
- return itemFound;
- }
-
- /**
- * Sets a given privacy list as the new user default list.
- *
- * @param newDefault the new default privacy list.
- * @return if the default list was changed.
- */
- public boolean changeDefaultList(String newDefault) {
- if (this.getItemLists().containsKey(newDefault)) {
- this.setDefaultName(newDefault);
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Remove the list.
- *
- * @param listName name of the list to remove.
- */
- public void deleteList(String listName) {
- this.getItemLists().remove(listName);
- }
-
- /**
- * Returns the name associated with the active list set for the session. Communications
- * will be verified against the active list.
- *
- * @return the name of the active list.
- */
- public String getActiveName() {
- return activeName;
- }
-
- /**
- * Sets the name associated with the active list set for the session. Communications
- * will be verified against the active list.
- *
- * @param activeName is the name of the active list.
- */
- public void setActiveName(String activeName) {
- this.activeName = activeName;
- }
-
- /**
- * Returns the name of the default list that applies to the user as a whole. Default list is
- * processed if there is no active list set for the target session/resource to which a stanza
- * is addressed, or if there are no current sessions for the user.
- *
- * @return the name of the default list.
- */
- public String getDefaultName() {
- return defaultName;
- }
-
- /**
- * Sets the name of the default list that applies to the user as a whole. Default list is
- * processed if there is no active list set for the target session/resource to which a stanza
- * is addressed, or if there are no current sessions for the user.
- *
- * If there is no default list set, then all Privacy Items are processed.
- *
- * @param defaultName is the name of the default list.
- */
- public void setDefaultName(String defaultName) {
- this.defaultName = defaultName;
- }
-
- /**
- * Returns the collection of privacy list that the user holds. A Privacy List contains a set of
- * rules that define if communication with the list owner is allowed or denied.
- * Users may have zero, one or more privacy items.
- *
- * @return a map where the key is the name of the list and the value the
- * collection of privacy items.
- */
- public Map<String, List<PrivacyItem>> getItemLists() {
- return itemLists;
- }
-
- /**
- * Returns whether the receiver allows or declines the use of an active list.
- *
- * @return the decline status of the list.
- */
- public boolean isDeclineActiveList() {
- return declineActiveList;
- }
-
- /**
- * Sets whether the receiver allows or declines the use of an active list.
- *
- * @param declineActiveList indicates if the receiver declines the use of an active list.
- */
- public void setDeclineActiveList(boolean declineActiveList) {
- this.declineActiveList = declineActiveList;
- }
-
- /**
- * Returns whether the receiver allows or declines the use of a default list.
- *
- * @return the decline status of the list.
- */
- public boolean isDeclineDefaultList() {
- return declineDefaultList;
- }
-
- /**
- * Sets whether the receiver allows or declines the use of a default list.
- *
- * @param declineDefaultList indicates if the receiver declines the use of a default list.
- */
- public void setDeclineDefaultList(boolean declineDefaultList) {
- this.declineDefaultList = declineDefaultList;
- }
-
- /**
- * Returns all the list names the user has defined to group restrictions.
- *
- * @return a Set with Strings containing every list names.
- */
- public Set<String> getPrivacyListNames() {
- return this.itemLists.keySet();
- }
-
- public String getChildElementXML() {
- StringBuilder buf = new StringBuilder();
- buf.append("<query xmlns=\"jabber:iq:privacy\">");
-
- // Add the active tag
- if (this.isDeclineActiveList()) {
- buf.append("<active/>");
- } else {
- if (this.getActiveName() != null) {
- buf.append("<active name=\"").append(this.getActiveName()).append("\"/>");
- }
- }
- // Add the default tag
- if (this.isDeclineDefaultList()) {
- buf.append("<default/>");
- } else {
- if (this.getDefaultName() != null) {
- buf.append("<default name=\"").append(this.getDefaultName()).append("\"/>");
- }
- }
-
- // Add the list with their privacy items
- for (Map.Entry<String, List<PrivacyItem>> entry : this.getItemLists().entrySet()) {
- String listName = entry.getKey();
- List<PrivacyItem> items = entry.getValue();
- // Begin the list tag
- if (items.isEmpty()) {
- buf.append("<list name=\"").append(listName).append("\"/>");
- } else {
- buf.append("<list name=\"").append(listName).append("\">");
- }
- for (PrivacyItem item : items) {
- // Append the item xml representation
- buf.append(item.toXML());
- }
- // Close the list tag
- if (!items.isEmpty()) {
- buf.append("</list>");
- }
- }
-
- // Add packet extensions, if any are defined.
- buf.append(getExtensionsXML());
- buf.append("</query>");
- return buf.toString();
- }
-
+/**
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2006-2007 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smack.packet;
+
+import java.util.*;
+
+/**
+ * A Privacy IQ Packet, is used by the {@link org.jivesoftware.smack.PrivacyListManager}
+ * and {@link org.jivesoftware.smack.provider.PrivacyProvider} to allow and block
+ * communications from other users. It contains the appropriate structure to suit
+ * user-defined privacy lists. Different configured Privacy packages are used in the
+ * server & manager communication in order to:
+ * <ul>
+ * <li>Retrieving one's privacy lists.
+ * <li>Adding, removing, and editing one's privacy lists.
+ * <li>Setting, changing, or declining active lists.
+ * <li>Setting, changing, or declining the default list (i.e., the list that is active by default).
+ * </ul>
+ * Privacy Items can handle different kind of blocking communications based on JID, group,
+ * subscription type or globally {@link PrivacyItem}
+ *
+ * @author Francisco Vives
+ */
+public class Privacy extends IQ {
+ /** declineActiveList is true when the user declines the use of the active list **/
+ private boolean declineActiveList=false;
+ /** activeName is the name associated with the active list set for the session **/
+ private String activeName;
+ /** declineDefaultList is true when the user declines the use of the default list **/
+ private boolean declineDefaultList=false;
+ /** defaultName is the name of the default list that applies to the user as a whole **/
+ private String defaultName;
+ /** itemLists holds the set of privacy items classified in lists. It is a map where the
+ * key is the name of the list and the value a collection with privacy items. **/
+ private Map<String, List<PrivacyItem>> itemLists = new HashMap<String, List<PrivacyItem>>();
+
+ /**
+ * Set or update a privacy list with privacy items.
+ *
+ * @param listName the name of the new privacy list.
+ * @param listItem the {@link PrivacyItem} that rules the list.
+ * @return the privacy List.
+ */
+ public List<PrivacyItem> setPrivacyList(String listName, List<PrivacyItem> listItem) {
+ // Add new list to the itemLists
+ this.getItemLists().put(listName, listItem);
+ return listItem;
+ }
+
+ /**
+ * Set the active list based on the default list.
+ *
+ * @return the active List.
+ */
+ public List<PrivacyItem> setActivePrivacyList() {
+ this.setActiveName(this.getDefaultName());
+ return this.getItemLists().get(this.getActiveName());
+ }
+
+ /**
+ * Deletes an existing privacy list. If the privacy list being deleted was the default list
+ * then the user will end up with no default list. Therefore, the user will have to set a new
+ * default list.
+ *
+ * @param listName the name of the list being deleted.
+ */
+ public void deletePrivacyList(String listName) {
+ // Remove the list from the cache
+ this.getItemLists().remove(listName);
+
+ // Check if deleted list was the default list
+ if (this.getDefaultName() != null && listName.equals(this.getDefaultName())) {
+ this.setDefaultName(null);
+ }
+ }
+
+ /**
+ * Returns the active privacy list or <tt>null</tt> if none was found.
+ *
+ * @return list with {@link PrivacyItem} or <tt>null</tt> if none was found.
+ */
+ public List<PrivacyItem> getActivePrivacyList() {
+ // Check if we have the default list
+ if (this.getActiveName() == null) {
+ return null;
+ } else {
+ return this.getItemLists().get(this.getActiveName());
+ }
+ }
+
+ /**
+ * Returns the default privacy list or <tt>null</tt> if none was found.
+ *
+ * @return list with {@link PrivacyItem} or <tt>null</tt> if none was found.
+ */
+ public List<PrivacyItem> getDefaultPrivacyList() {
+ // Check if we have the default list
+ if (this.getDefaultName() == null) {
+ return null;
+ } else {
+ return this.getItemLists().get(this.getDefaultName());
+ }
+ }
+
+ /**
+ * Returns a specific privacy list.
+ *
+ * @param listName the name of the list to get.
+ * @return a List with {@link PrivacyItem}
+ */
+ public List<PrivacyItem> getPrivacyList(String listName) {
+ return this.getItemLists().get(listName);
+ }
+
+ /**
+ * Returns the privacy item in the specified order.
+ *
+ * @param listName the name of the privacy list.
+ * @param order the order of the element.
+ * @return a List with {@link PrivacyItem}
+ */
+ public PrivacyItem getItem(String listName, int order) {
+ Iterator<PrivacyItem> values = getPrivacyList(listName).iterator();
+ PrivacyItem itemFound = null;
+ while (itemFound == null && values.hasNext()) {
+ PrivacyItem element = values.next();
+ if (element.getOrder() == order) {
+ itemFound = element;
+ }
+ }
+ return itemFound;
+ }
+
+ /**
+ * Sets a given privacy list as the new user default list.
+ *
+ * @param newDefault the new default privacy list.
+ * @return if the default list was changed.
+ */
+ public boolean changeDefaultList(String newDefault) {
+ if (this.getItemLists().containsKey(newDefault)) {
+ this.setDefaultName(newDefault);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Remove the list.
+ *
+ * @param listName name of the list to remove.
+ */
+ public void deleteList(String listName) {
+ this.getItemLists().remove(listName);
+ }
+
+ /**
+ * Returns the name associated with the active list set for the session. Communications
+ * will be verified against the active list.
+ *
+ * @return the name of the active list.
+ */
+ public String getActiveName() {
+ return activeName;
+ }
+
+ /**
+ * Sets the name associated with the active list set for the session. Communications
+ * will be verified against the active list.
+ *
+ * @param activeName is the name of the active list.
+ */
+ public void setActiveName(String activeName) {
+ this.activeName = activeName;
+ }
+
+ /**
+ * Returns the name of the default list that applies to the user as a whole. Default list is
+ * processed if there is no active list set for the target session/resource to which a stanza
+ * is addressed, or if there are no current sessions for the user.
+ *
+ * @return the name of the default list.
+ */
+ public String getDefaultName() {
+ return defaultName;
+ }
+
+ /**
+ * Sets the name of the default list that applies to the user as a whole. Default list is
+ * processed if there is no active list set for the target session/resource to which a stanza
+ * is addressed, or if there are no current sessions for the user.
+ *
+ * If there is no default list set, then all Privacy Items are processed.
+ *
+ * @param defaultName is the name of the default list.
+ */
+ public void setDefaultName(String defaultName) {
+ this.defaultName = defaultName;
+ }
+
+ /**
+ * Returns the collection of privacy list that the user holds. A Privacy List contains a set of
+ * rules that define if communication with the list owner is allowed or denied.
+ * Users may have zero, one or more privacy items.
+ *
+ * @return a map where the key is the name of the list and the value the
+ * collection of privacy items.
+ */
+ public Map<String, List<PrivacyItem>> getItemLists() {
+ return itemLists;
+ }
+
+ /**
+ * Returns whether the receiver allows or declines the use of an active list.
+ *
+ * @return the decline status of the list.
+ */
+ public boolean isDeclineActiveList() {
+ return declineActiveList;
+ }
+
+ /**
+ * Sets whether the receiver allows or declines the use of an active list.
+ *
+ * @param declineActiveList indicates if the receiver declines the use of an active list.
+ */
+ public void setDeclineActiveList(boolean declineActiveList) {
+ this.declineActiveList = declineActiveList;
+ }
+
+ /**
+ * Returns whether the receiver allows or declines the use of a default list.
+ *
+ * @return the decline status of the list.
+ */
+ public boolean isDeclineDefaultList() {
+ return declineDefaultList;
+ }
+
+ /**
+ * Sets whether the receiver allows or declines the use of a default list.
+ *
+ * @param declineDefaultList indicates if the receiver declines the use of a default list.
+ */
+ public void setDeclineDefaultList(boolean declineDefaultList) {
+ this.declineDefaultList = declineDefaultList;
+ }
+
+ /**
+ * Returns all the list names the user has defined to group restrictions.
+ *
+ * @return a Set with Strings containing every list names.
+ */
+ public Set<String> getPrivacyListNames() {
+ return this.itemLists.keySet();
+ }
+
+ public String getChildElementXML() {
+ StringBuilder buf = new StringBuilder();
+ buf.append("<query xmlns=\"jabber:iq:privacy\">");
+
+ // Add the active tag
+ if (this.isDeclineActiveList()) {
+ buf.append("<active/>");
+ } else {
+ if (this.getActiveName() != null) {
+ buf.append("<active name=\"").append(this.getActiveName()).append("\"/>");
+ }
+ }
+ // Add the default tag
+ if (this.isDeclineDefaultList()) {
+ buf.append("<default/>");
+ } else {
+ if (this.getDefaultName() != null) {
+ buf.append("<default name=\"").append(this.getDefaultName()).append("\"/>");
+ }
+ }
+
+ // Add the list with their privacy items
+ for (Map.Entry<String, List<PrivacyItem>> entry : this.getItemLists().entrySet()) {
+ String listName = entry.getKey();
+ List<PrivacyItem> items = entry.getValue();
+ // Begin the list tag
+ if (items.isEmpty()) {
+ buf.append("<list name=\"").append(listName).append("\"/>");
+ } else {
+ buf.append("<list name=\"").append(listName).append("\">");
+ }
+ for (PrivacyItem item : items) {
+ // Append the item xml representation
+ buf.append(item.toXML());
+ }
+ // Close the list tag
+ if (!items.isEmpty()) {
+ buf.append("</list>");
+ }
+ }
+
+ // Add packet extensions, if any are defined.
+ buf.append(getExtensionsXML());
+ buf.append("</query>");
+ return buf.toString();
+ }
+
} \ No newline at end of file
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/PrivacyItem.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/PrivacyItem.java
index 2e144eec6..e108f6897 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/PrivacyItem.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/PrivacyItem.java
@@ -15,448 +15,448 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jivesoftware.smack.packet;
-
-/**
- * A privacy item acts a rule that when matched defines if a packet should be blocked or not.
- *
- * Privacy Items can handle different kind of blocking communications based on JID, group,
- * subscription type or globally by:<ul>
- * <li>Allowing or blocking messages.
- * <li>Allowing or blocking inbound presence notifications.
- * <li>Allowing or blocking outbound presence notifications.
- * <li>Allowing or blocking IQ stanzas.
- * <li>Allowing or blocking all communications.
- * </ul>
- * @author Francisco Vives
- */
-public class PrivacyItem {
- /** allow is the action associated with the item, it can allow or deny the communication. */
- private boolean allow;
- /** order is a non-negative integer that is unique among all items in the list. */
- private int order;
- /** rule hold the kind of communication ([jid|group|subscription]) it will allow or block and
- * identifier to apply the action.
- * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
- * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
- * in the user's roster.
- * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
- * "from", or "none". */
- private PrivacyRule rule;
-
- /** blocks incoming IQ stanzas. */
- private boolean filterIQ = false;
- /** filterMessage blocks incoming message stanzas. */
- private boolean filterMessage = false;
- /** blocks incoming presence notifications. */
- private boolean filterPresence_in = false;
- /** blocks outgoing presence notifications. */
- private boolean filterPresence_out = false;
-
- /**
- * Creates a new privacy item.
- *
- * @param type the type.
- */
- public PrivacyItem(String type, boolean allow, int order) {
- this.setRule(PrivacyRule.fromString(type));
- this.setAllow(allow);
- this.setOrder(order);
- }
-
- /**
- * Returns the action associated with the item, it MUST be filled and will allow or deny
- * the communication.
- *
- * @return the allow communication status.
- */
- public boolean isAllow() {
- return allow;
- }
-
- /**
- * Sets the action associated with the item, it can allow or deny the communication.
- *
- * @param allow indicates if the receiver allow or deny the communication.
- */
- private void setAllow(boolean allow) {
- this.allow = allow;
- }
-
-
- /**
- * Returns whether the receiver allow or deny incoming IQ stanzas or not.
- *
- * @return the iq filtering status.
- */
- public boolean isFilterIQ() {
- return filterIQ;
- }
-
-
- /**
- * Sets whether the receiver allows or denies incoming IQ stanzas or not.
- *
- * @param filterIQ indicates if the receiver allows or denies incoming IQ stanzas.
- */
- public void setFilterIQ(boolean filterIQ) {
- this.filterIQ = filterIQ;
- }
-
-
- /**
- * Returns whether the receiver allows or denies incoming messages or not.
- *
- * @return the message filtering status.
- */
- public boolean isFilterMessage() {
- return filterMessage;
- }
-
-
- /**
- * Sets wheather the receiver allows or denies incoming messages or not.
- *
- * @param filterMessage indicates if the receiver allows or denies incoming messages or not.
- */
- public void setFilterMessage(boolean filterMessage) {
- this.filterMessage = filterMessage;
- }
-
-
- /**
- * Returns whether the receiver allows or denies incoming presence or not.
- *
- * @return the iq filtering incoming presence status.
- */
- public boolean isFilterPresence_in() {
- return filterPresence_in;
- }
-
-
- /**
- * Sets whether the receiver allows or denies incoming presence or not.
- *
- * @param filterPresence_in indicates if the receiver allows or denies filtering incoming presence.
- */
- public void setFilterPresence_in(boolean filterPresence_in) {
- this.filterPresence_in = filterPresence_in;
- }
-
-
- /**
- * Returns whether the receiver allows or denies incoming presence or not.
- *
- * @return the iq filtering incoming presence status.
- */
- public boolean isFilterPresence_out() {
- return filterPresence_out;
- }
-
-
- /**
- * Sets whether the receiver allows or denies outgoing presence or not.
- *
- * @param filterPresence_out indicates if the receiver allows or denies filtering outgoing presence
- */
- public void setFilterPresence_out(boolean filterPresence_out) {
- this.filterPresence_out = filterPresence_out;
- }
-
-
- /**
- * Returns the order where the receiver is processed. List items are processed in
- * ascending order.
- *
- * The order MUST be filled and its value MUST be a non-negative integer
- * that is unique among all items in the list.
- *
- * @return the order number.
- */
- public int getOrder() {
- return order;
- }
-
-
- /**
- * Sets the order where the receiver is processed.
- *
- * The order MUST be filled and its value MUST be a non-negative integer
- * that is unique among all items in the list.
- *
- * @param order indicates the order in the list.
- */
- public void setOrder(int order) {
- this.order = order;
- }
-
- /**
- * Sets the element identifier to apply the action.
- *
- * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
- * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
- * in the user's roster.
- * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
- * "from", or "none".
- *
- * @param value is the identifier to apply the action.
- */
- public void setValue(String value) {
- if (!(this.getRule() == null && value == null)) {
- this.getRule().setValue(value);
- }
- }
-
- /**
- * Returns the type hold the kind of communication it will allow or block.
- * It MUST be filled with one of these values: jid, group or subscription.
- *
- * @return the type of communication it represent.
- */
- public Type getType() {
- if (this.getRule() == null) {
- return null;
- } else {
- return this.getRule().getType();
- }
- }
-
- /**
- * Returns the element identifier to apply the action.
- *
- * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
- * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
- * in the user's roster.
- * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
- * "from", or "none".
- *
- * @return the identifier to apply the action.
- */
- public String getValue() {
- if (this.getRule() == null) {
- return null;
- } else {
- return this.getRule().getValue();
- }
- }
-
-
- /**
- * Returns whether the receiver allows or denies every kind of communication.
- *
- * When filterIQ, filterMessage, filterPresence_in and filterPresence_out are not set
- * the receiver will block all communications.
- *
- * @return the all communications status.
- */
- public boolean isFilterEverything() {
- return !(this.isFilterIQ() || this.isFilterMessage() || this.isFilterPresence_in()
- || this.isFilterPresence_out());
- }
-
-
- private PrivacyRule getRule() {
- return rule;
- }
-
- private void setRule(PrivacyRule rule) {
- this.rule = rule;
- }
- /**
- * Answer an xml representation of the receiver according to the RFC 3921.
- *
- * @return the text xml representation.
- */
- public String toXML() {
- StringBuilder buf = new StringBuilder();
- buf.append("<item");
- if (this.isAllow()) {
- buf.append(" action=\"allow\"");
- } else {
- buf.append(" action=\"deny\"");
- }
- buf.append(" order=\"").append(getOrder()).append("\"");
- if (getType() != null) {
- buf.append(" type=\"").append(getType()).append("\"");
- }
- if (getValue() != null) {
- buf.append(" value=\"").append(getValue()).append("\"");
- }
- if (isFilterEverything()) {
- buf.append("/>");
- } else {
- buf.append(">");
- if (this.isFilterIQ()) {
- buf.append("<iq/>");
- }
- if (this.isFilterMessage()) {
- buf.append("<message/>");
- }
- if (this.isFilterPresence_in()) {
- buf.append("<presence-in/>");
- }
- if (this.isFilterPresence_out()) {
- buf.append("<presence-out/>");
- }
- buf.append("</item>");
- }
- return buf.toString();
- }
-
-
- /**
- * Privacy Rule represents the kind of action to apply.
- * It holds the kind of communication ([jid|group|subscription]) it will allow or block and
- * identifier to apply the action.
- */
-
- public static class PrivacyRule {
- /**
- * Type defines if the rule is based on JIDs, roster groups or presence subscription types.
- * Available values are: [jid|group|subscription]
- */
- private Type type;
- /**
- * The value hold the element identifier to apply the action.
- * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
- * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
- * in the user's roster.
- * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
- * "from", or "none".
- */
- private String value;
-
- /**
- * If the type is "subscription", then the 'value' attribute MUST be one of "both",
- * "to", "from", or "none"
- */
- public static final String SUBSCRIPTION_BOTH = "both";
- public static final String SUBSCRIPTION_TO = "to";
- public static final String SUBSCRIPTION_FROM = "from";
- public static final String SUBSCRIPTION_NONE = "none";
-
- /**
- * Returns the type constant associated with the String value.
- */
- protected static PrivacyRule fromString(String value) {
- if (value == null) {
- return null;
- }
- PrivacyRule rule = new PrivacyRule();
- rule.setType(Type.valueOf(value.toLowerCase()));
- return rule;
- }
-
- /**
- * Returns the type hold the kind of communication it will allow or block.
- * It MUST be filled with one of these values: jid, group or subscription.
- *
- * @return the type of communication it represent.
- */
- public Type getType() {
- return type;
- }
-
- /**
- * Sets the action associated with the item, it can allow or deny the communication.
- *
- * @param type indicates if the receiver allows or denies the communication.
- */
- private void setType(Type type) {
- this.type = type;
- }
-
- /**
- * Returns the element identifier to apply the action.
- *
- * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
- * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
- * in the user's roster.
- * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
- * "from", or "none".
- *
- * @return the identifier to apply the action.
- */
- public String getValue() {
- return value;
- }
-
- /**
- * Sets the element identifier to apply the action.
- *
- * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
- * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
- * in the user's roster.
- * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
- * "from", or "none".
- *
- * @param value is the identifier to apply the action.
- */
- protected void setValue(String value) {
- if (this.isSuscription()) {
- setSuscriptionValue(value);
- } else {
- this.value = value;
- }
- }
-
- /**
- * Sets the element identifier to apply the action.
- *
- * The 'value' attribute MUST be one of "both", "to", "from", or "none".
- *
- * @param value is the identifier to apply the action.
- */
- private void setSuscriptionValue(String value) {
- String setValue;
- if (value == null) {
- // Do nothing
- }
- if (SUBSCRIPTION_BOTH.equalsIgnoreCase(value)) {
- setValue = SUBSCRIPTION_BOTH;
- }
- else if (SUBSCRIPTION_TO.equalsIgnoreCase(value)) {
- setValue = SUBSCRIPTION_TO;
- }
- else if (SUBSCRIPTION_FROM.equalsIgnoreCase(value)) {
- setValue = SUBSCRIPTION_FROM;
- }
- else if (SUBSCRIPTION_NONE.equalsIgnoreCase(value)) {
- setValue = SUBSCRIPTION_NONE;
- }
- // Default to available.
- else {
- setValue = null;
- }
- this.value = setValue;
- }
-
- /**
- * Returns if the receiver represents a subscription rule.
- *
- * @return if the receiver represents a subscription rule.
- */
- public boolean isSuscription () {
- return this.getType() == Type.subscription;
- }
- }
-
- /**
- * Type defines if the rule is based on JIDs, roster groups or presence subscription types.
- */
- public static enum Type {
- /**
- * JID being analyzed should belong to a roster group of the list's owner.
- */
- group,
- /**
- * JID being analyzed should have a resource match, domain match or bare JID match.
- */
- jid,
- /**
- * JID being analyzed should belong to a contact present in the owner's roster with
- * the specified subscription status.
- */
- subscription
- }
-}
+package org.jivesoftware.smack.packet;
+
+/**
+ * A privacy item acts a rule that when matched defines if a packet should be blocked or not.
+ *
+ * Privacy Items can handle different kind of blocking communications based on JID, group,
+ * subscription type or globally by:<ul>
+ * <li>Allowing or blocking messages.
+ * <li>Allowing or blocking inbound presence notifications.
+ * <li>Allowing or blocking outbound presence notifications.
+ * <li>Allowing or blocking IQ stanzas.
+ * <li>Allowing or blocking all communications.
+ * </ul>
+ * @author Francisco Vives
+ */
+public class PrivacyItem {
+ /** allow is the action associated with the item, it can allow or deny the communication. */
+ private boolean allow;
+ /** order is a non-negative integer that is unique among all items in the list. */
+ private int order;
+ /** rule hold the kind of communication ([jid|group|subscription]) it will allow or block and
+ * identifier to apply the action.
+ * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
+ * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
+ * in the user's roster.
+ * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
+ * "from", or "none". */
+ private PrivacyRule rule;
+
+ /** blocks incoming IQ stanzas. */
+ private boolean filterIQ = false;
+ /** filterMessage blocks incoming message stanzas. */
+ private boolean filterMessage = false;
+ /** blocks incoming presence notifications. */
+ private boolean filterPresence_in = false;
+ /** blocks outgoing presence notifications. */
+ private boolean filterPresence_out = false;
+
+ /**
+ * Creates a new privacy item.
+ *
+ * @param type the type.
+ */
+ public PrivacyItem(String type, boolean allow, int order) {
+ this.setRule(PrivacyRule.fromString(type));
+ this.setAllow(allow);
+ this.setOrder(order);
+ }
+
+ /**
+ * Returns the action associated with the item, it MUST be filled and will allow or deny
+ * the communication.
+ *
+ * @return the allow communication status.
+ */
+ public boolean isAllow() {
+ return allow;
+ }
+
+ /**
+ * Sets the action associated with the item, it can allow or deny the communication.
+ *
+ * @param allow indicates if the receiver allow or deny the communication.
+ */
+ private void setAllow(boolean allow) {
+ this.allow = allow;
+ }
+
+
+ /**
+ * Returns whether the receiver allow or deny incoming IQ stanzas or not.
+ *
+ * @return the iq filtering status.
+ */
+ public boolean isFilterIQ() {
+ return filterIQ;
+ }
+
+
+ /**
+ * Sets whether the receiver allows or denies incoming IQ stanzas or not.
+ *
+ * @param filterIQ indicates if the receiver allows or denies incoming IQ stanzas.
+ */
+ public void setFilterIQ(boolean filterIQ) {
+ this.filterIQ = filterIQ;
+ }
+
+
+ /**
+ * Returns whether the receiver allows or denies incoming messages or not.
+ *
+ * @return the message filtering status.
+ */
+ public boolean isFilterMessage() {
+ return filterMessage;
+ }
+
+
+ /**
+ * Sets wheather the receiver allows or denies incoming messages or not.
+ *
+ * @param filterMessage indicates if the receiver allows or denies incoming messages or not.
+ */
+ public void setFilterMessage(boolean filterMessage) {
+ this.filterMessage = filterMessage;
+ }
+
+
+ /**
+ * Returns whether the receiver allows or denies incoming presence or not.
+ *
+ * @return the iq filtering incoming presence status.
+ */
+ public boolean isFilterPresence_in() {
+ return filterPresence_in;
+ }
+
+
+ /**
+ * Sets whether the receiver allows or denies incoming presence or not.
+ *
+ * @param filterPresence_in indicates if the receiver allows or denies filtering incoming presence.
+ */
+ public void setFilterPresence_in(boolean filterPresence_in) {
+ this.filterPresence_in = filterPresence_in;
+ }
+
+
+ /**
+ * Returns whether the receiver allows or denies incoming presence or not.
+ *
+ * @return the iq filtering incoming presence status.
+ */
+ public boolean isFilterPresence_out() {
+ return filterPresence_out;
+ }
+
+
+ /**
+ * Sets whether the receiver allows or denies outgoing presence or not.
+ *
+ * @param filterPresence_out indicates if the receiver allows or denies filtering outgoing presence
+ */
+ public void setFilterPresence_out(boolean filterPresence_out) {
+ this.filterPresence_out = filterPresence_out;
+ }
+
+
+ /**
+ * Returns the order where the receiver is processed. List items are processed in
+ * ascending order.
+ *
+ * The order MUST be filled and its value MUST be a non-negative integer
+ * that is unique among all items in the list.
+ *
+ * @return the order number.
+ */
+ public int getOrder() {
+ return order;
+ }
+
+
+ /**
+ * Sets the order where the receiver is processed.
+ *
+ * The order MUST be filled and its value MUST be a non-negative integer
+ * that is unique among all items in the list.
+ *
+ * @param order indicates the order in the list.
+ */
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ /**
+ * Sets the element identifier to apply the action.
+ *
+ * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
+ * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
+ * in the user's roster.
+ * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
+ * "from", or "none".
+ *
+ * @param value is the identifier to apply the action.
+ */
+ public void setValue(String value) {
+ if (!(this.getRule() == null && value == null)) {
+ this.getRule().setValue(value);
+ }
+ }
+
+ /**
+ * Returns the type hold the kind of communication it will allow or block.
+ * It MUST be filled with one of these values: jid, group or subscription.
+ *
+ * @return the type of communication it represent.
+ */
+ public Type getType() {
+ if (this.getRule() == null) {
+ return null;
+ } else {
+ return this.getRule().getType();
+ }
+ }
+
+ /**
+ * Returns the element identifier to apply the action.
+ *
+ * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
+ * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
+ * in the user's roster.
+ * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
+ * "from", or "none".
+ *
+ * @return the identifier to apply the action.
+ */
+ public String getValue() {
+ if (this.getRule() == null) {
+ return null;
+ } else {
+ return this.getRule().getValue();
+ }
+ }
+
+
+ /**
+ * Returns whether the receiver allows or denies every kind of communication.
+ *
+ * When filterIQ, filterMessage, filterPresence_in and filterPresence_out are not set
+ * the receiver will block all communications.
+ *
+ * @return the all communications status.
+ */
+ public boolean isFilterEverything() {
+ return !(this.isFilterIQ() || this.isFilterMessage() || this.isFilterPresence_in()
+ || this.isFilterPresence_out());
+ }
+
+
+ private PrivacyRule getRule() {
+ return rule;
+ }
+
+ private void setRule(PrivacyRule rule) {
+ this.rule = rule;
+ }
+ /**
+ * Answer an xml representation of the receiver according to the RFC 3921.
+ *
+ * @return the text xml representation.
+ */
+ public String toXML() {
+ StringBuilder buf = new StringBuilder();
+ buf.append("<item");
+ if (this.isAllow()) {
+ buf.append(" action=\"allow\"");
+ } else {
+ buf.append(" action=\"deny\"");
+ }
+ buf.append(" order=\"").append(getOrder()).append("\"");
+ if (getType() != null) {
+ buf.append(" type=\"").append(getType()).append("\"");
+ }
+ if (getValue() != null) {
+ buf.append(" value=\"").append(getValue()).append("\"");
+ }
+ if (isFilterEverything()) {
+ buf.append("/>");
+ } else {
+ buf.append(">");
+ if (this.isFilterIQ()) {
+ buf.append("<iq/>");
+ }
+ if (this.isFilterMessage()) {
+ buf.append("<message/>");
+ }
+ if (this.isFilterPresence_in()) {
+ buf.append("<presence-in/>");
+ }
+ if (this.isFilterPresence_out()) {
+ buf.append("<presence-out/>");
+ }
+ buf.append("</item>");
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * Privacy Rule represents the kind of action to apply.
+ * It holds the kind of communication ([jid|group|subscription]) it will allow or block and
+ * identifier to apply the action.
+ */
+
+ public static class PrivacyRule {
+ /**
+ * Type defines if the rule is based on JIDs, roster groups or presence subscription types.
+ * Available values are: [jid|group|subscription]
+ */
+ private Type type;
+ /**
+ * The value hold the element identifier to apply the action.
+ * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
+ * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
+ * in the user's roster.
+ * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
+ * "from", or "none".
+ */
+ private String value;
+
+ /**
+ * If the type is "subscription", then the 'value' attribute MUST be one of "both",
+ * "to", "from", or "none"
+ */
+ public static final String SUBSCRIPTION_BOTH = "both";
+ public static final String SUBSCRIPTION_TO = "to";
+ public static final String SUBSCRIPTION_FROM = "from";
+ public static final String SUBSCRIPTION_NONE = "none";
+
+ /**
+ * Returns the type constant associated with the String value.
+ */
+ protected static PrivacyRule fromString(String value) {
+ if (value == null) {
+ return null;
+ }
+ PrivacyRule rule = new PrivacyRule();
+ rule.setType(Type.valueOf(value.toLowerCase()));
+ return rule;
+ }
+
+ /**
+ * Returns the type hold the kind of communication it will allow or block.
+ * It MUST be filled with one of these values: jid, group or subscription.
+ *
+ * @return the type of communication it represent.
+ */
+ public Type getType() {
+ return type;
+ }
+
+ /**
+ * Sets the action associated with the item, it can allow or deny the communication.
+ *
+ * @param type indicates if the receiver allows or denies the communication.
+ */
+ private void setType(Type type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns the element identifier to apply the action.
+ *
+ * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
+ * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
+ * in the user's roster.
+ * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
+ * "from", or "none".
+ *
+ * @return the identifier to apply the action.
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the element identifier to apply the action.
+ *
+ * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
+ * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
+ * in the user's roster.
+ * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
+ * "from", or "none".
+ *
+ * @param value is the identifier to apply the action.
+ */
+ protected void setValue(String value) {
+ if (this.isSuscription()) {
+ setSuscriptionValue(value);
+ } else {
+ this.value = value;
+ }
+ }
+
+ /**
+ * Sets the element identifier to apply the action.
+ *
+ * The 'value' attribute MUST be one of "both", "to", "from", or "none".
+ *
+ * @param value is the identifier to apply the action.
+ */
+ private void setSuscriptionValue(String value) {
+ String setValue;
+ if (value == null) {
+ // Do nothing
+ }
+ if (SUBSCRIPTION_BOTH.equalsIgnoreCase(value)) {
+ setValue = SUBSCRIPTION_BOTH;
+ }
+ else if (SUBSCRIPTION_TO.equalsIgnoreCase(value)) {
+ setValue = SUBSCRIPTION_TO;
+ }
+ else if (SUBSCRIPTION_FROM.equalsIgnoreCase(value)) {
+ setValue = SUBSCRIPTION_FROM;
+ }
+ else if (SUBSCRIPTION_NONE.equalsIgnoreCase(value)) {
+ setValue = SUBSCRIPTION_NONE;
+ }
+ // Default to available.
+ else {
+ setValue = null;
+ }
+ this.value = setValue;
+ }
+
+ /**
+ * Returns if the receiver represents a subscription rule.
+ *
+ * @return if the receiver represents a subscription rule.
+ */
+ public boolean isSuscription () {
+ return this.getType() == Type.subscription;
+ }
+ }
+
+ /**
+ * Type defines if the rule is based on JIDs, roster groups or presence subscription types.
+ */
+ public static enum Type {
+ /**
+ * JID being analyzed should belong to a roster group of the list's owner.
+ */
+ group,
+ /**
+ * JID being analyzed should have a resource match, domain match or bare JID match.
+ */
+ jid,
+ /**
+ * JID being analyzed should belong to a contact present in the owner's roster with
+ * the specified subscription status.
+ */
+ subscription
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Session.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Session.java
index fd403ae20..427c01a2a 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Session.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/Session.java
@@ -1,45 +1,45 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- * Copyright 2003-2007 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smack.packet;
-
-/**
- * IQ packet that will be sent to the server to establish a session.<p>
- *
- * If a server supports sessions, it MUST include a <i>session</i> element in the
- * stream features it advertises to a client after the completion of stream authentication.
- * Upon being informed that session establishment is required by the server the client MUST
- * establish a session if it desires to engage in instant messaging and presence functionality.<p>
- *
- * For more information refer to the following
- * <a href=http://www.xmpp.org/specs/rfc3921.html#session>link</a>.
- *
- * @author Gaston Dombiak
- */
-public class Session extends IQ {
-
- public Session() {
- setType(IQ.Type.SET);
- }
-
- public String getChildElementXML() {
- return "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>";
- }
-}
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2003-2007 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smack.packet;
+
+/**
+ * IQ packet that will be sent to the server to establish a session.<p>
+ *
+ * If a server supports sessions, it MUST include a <i>session</i> element in the
+ * stream features it advertises to a client after the completion of stream authentication.
+ * Upon being informed that session establishment is required by the server the client MUST
+ * establish a session if it desires to engage in instant messaging and presence functionality.<p>
+ *
+ * For more information refer to the following
+ * <a href=http://www.xmpp.org/specs/rfc3921.html#session>link</a>.
+ *
+ * @author Gaston Dombiak
+ */
+public class Session extends IQ {
+
+ public Session() {
+ setType(IQ.Type.SET);
+ }
+
+ public String getChildElementXML() {
+ return "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>";
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/StreamError.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/StreamError.java
index 8bb4c75bc..72679a8df 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/StreamError.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/packet/StreamError.java
@@ -1,106 +1,106 @@
-/**
- * $Revision: 2408 $
- * $Date: 2004-11-02 20:53:30 -0300 (Tue, 02 Nov 2004) $
- *
- * Copyright 2003-2005 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smack.packet;
-
-/**
- * Represents a stream error packet. Stream errors are unrecoverable errors where the server
- * will close the unrelying TCP connection after the stream error was sent to the client.
- * These is the list of stream errors as defined in the XMPP spec:<p>
- *
- * <table border=1>
- * <tr><td><b>Code</b></td><td><b>Description</b></td></tr>
- * <tr><td> bad-format </td><td> the entity has sent XML that cannot be processed </td></tr>
- * <tr><td> unsupported-encoding </td><td> the entity has sent a namespace prefix that is
- * unsupported </td></tr>
- * <tr><td> bad-namespace-prefix </td><td> Remote Server Timeout </td></tr>
- * <tr><td> conflict </td><td> the server is closing the active stream for this entity
- * because a new stream has been initiated that conflicts with the existing
- * stream. </td></tr>
- * <tr><td> connection-timeout </td><td> the entity has not generated any traffic over
- * the stream for some period of time. </td></tr>
- * <tr><td> host-gone </td><td> the value of the 'to' attribute provided by the initiating
- * entity in the stream header corresponds to a hostname that is no longer hosted by
- * the server. </td></tr>
- * <tr><td> host-unknown </td><td> the value of the 'to' attribute provided by the
- * initiating entity in the stream header does not correspond to a hostname that is
- * hosted by the server. </td></tr>
- * <tr><td> improper-addressing </td><td> a stanza sent between two servers lacks a 'to'
- * or 'from' attribute </td></tr>
- * <tr><td> internal-server-error </td><td> the server has experienced a
- * misconfiguration. </td></tr>
- * <tr><td> invalid-from </td><td> the JID or hostname provided in a 'from' address does
- * not match an authorized JID. </td></tr>
- * <tr><td> invalid-id </td><td> the stream ID or dialback ID is invalid or does not match
- * an ID previously provided. </td></tr>
- * <tr><td> invalid-namespace </td><td> the streams namespace name is invalid. </td></tr>
- * <tr><td> invalid-xml </td><td> the entity has sent invalid XML over the stream. </td></tr>
- * <tr><td> not-authorized </td><td> the entity has attempted to send data before the
- * stream has been authenticated </td></tr>
- * <tr><td> policy-violation </td><td> the entity has violated some local service
- * policy. </td></tr>
- * <tr><td> remote-connection-failed </td><td> Rthe server is unable to properly connect
- * to a remote entity. </td></tr>
- * <tr><td> resource-constraint </td><td> Rthe server lacks the system resources necessary
- * to service the stream. </td></tr>
- * <tr><td> restricted-xml </td><td> the entity has attempted to send restricted XML
- * features. </td></tr>
- * <tr><td> see-other-host </td><td> the server will not provide service to the initiating
- * entity but is redirecting traffic to another host. </td></tr>
- * <tr><td> system-shutdown </td><td> the server is being shut down and all active streams
- * are being closed. </td></tr>
- * <tr><td> undefined-condition </td><td> the error condition is not one of those defined
- * by the other conditions in this list. </td></tr>
- * <tr><td> unsupported-encoding </td><td> the initiating entity has encoded the stream in
- * an encoding that is not supported. </td></tr>
- * <tr><td> unsupported-stanza-type </td><td> the initiating entity has sent a first-level
- * child of the stream that is not supported. </td></tr>
- * <tr><td> unsupported-version </td><td> the value of the 'version' attribute provided by
- * the initiating entity in the stream header specifies a version of XMPP that is not
- * supported. </td></tr>
- * <tr><td> xml-not-well-formed </td><td> the initiating entity has sent XML that is
- * not well-formed. </td></tr>
- * </table>
- *
- * @author Gaston Dombiak
- */
-public class StreamError {
-
- private String code;
-
- public StreamError(String code) {
- super();
- this.code = code;
- }
-
- /**
- * Returns the error code.
- *
- * @return the error code.
- */
- public String getCode() {
- return code;
- }
-
- public String toString() {
- StringBuilder txt = new StringBuilder();
- txt.append("stream:error (").append(code).append(")");
- return txt.toString();
- }
-}
+/**
+ * $Revision: 2408 $
+ * $Date: 2004-11-02 20:53:30 -0300 (Tue, 02 Nov 2004) $
+ *
+ * Copyright 2003-2005 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smack.packet;
+
+/**
+ * Represents a stream error packet. Stream errors are unrecoverable errors where the server
+ * will close the unrelying TCP connection after the stream error was sent to the client.
+ * These is the list of stream errors as defined in the XMPP spec:<p>
+ *
+ * <table border=1>
+ * <tr><td><b>Code</b></td><td><b>Description</b></td></tr>
+ * <tr><td> bad-format </td><td> the entity has sent XML that cannot be processed </td></tr>
+ * <tr><td> unsupported-encoding </td><td> the entity has sent a namespace prefix that is
+ * unsupported </td></tr>
+ * <tr><td> bad-namespace-prefix </td><td> Remote Server Timeout </td></tr>
+ * <tr><td> conflict </td><td> the server is closing the active stream for this entity
+ * because a new stream has been initiated that conflicts with the existing
+ * stream. </td></tr>
+ * <tr><td> connection-timeout </td><td> the entity has not generated any traffic over
+ * the stream for some period of time. </td></tr>
+ * <tr><td> host-gone </td><td> the value of the 'to' attribute provided by the initiating
+ * entity in the stream header corresponds to a hostname that is no longer hosted by
+ * the server. </td></tr>
+ * <tr><td> host-unknown </td><td> the value of the 'to' attribute provided by the
+ * initiating entity in the stream header does not correspond to a hostname that is
+ * hosted by the server. </td></tr>
+ * <tr><td> improper-addressing </td><td> a stanza sent between two servers lacks a 'to'
+ * or 'from' attribute </td></tr>
+ * <tr><td> internal-server-error </td><td> the server has experienced a
+ * misconfiguration. </td></tr>
+ * <tr><td> invalid-from </td><td> the JID or hostname provided in a 'from' address does
+ * not match an authorized JID. </td></tr>
+ * <tr><td> invalid-id </td><td> the stream ID or dialback ID is invalid or does not match
+ * an ID previously provided. </td></tr>
+ * <tr><td> invalid-namespace </td><td> the streams namespace name is invalid. </td></tr>
+ * <tr><td> invalid-xml </td><td> the entity has sent invalid XML over the stream. </td></tr>
+ * <tr><td> not-authorized </td><td> the entity has attempted to send data before the
+ * stream has been authenticated </td></tr>
+ * <tr><td> policy-violation </td><td> the entity has violated some local service
+ * policy. </td></tr>
+ * <tr><td> remote-connection-failed </td><td> Rthe server is unable to properly connect
+ * to a remote entity. </td></tr>
+ * <tr><td> resource-constraint </td><td> Rthe server lacks the system resources necessary
+ * to service the stream. </td></tr>
+ * <tr><td> restricted-xml </td><td> the entity has attempted to send restricted XML
+ * features. </td></tr>
+ * <tr><td> see-other-host </td><td> the server will not provide service to the initiating
+ * entity but is redirecting traffic to another host. </td></tr>
+ * <tr><td> system-shutdown </td><td> the server is being shut down and all active streams
+ * are being closed. </td></tr>
+ * <tr><td> undefined-condition </td><td> the error condition is not one of those defined
+ * by the other conditions in this list. </td></tr>
+ * <tr><td> unsupported-encoding </td><td> the initiating entity has encoded the stream in
+ * an encoding that is not supported. </td></tr>
+ * <tr><td> unsupported-stanza-type </td><td> the initiating entity has sent a first-level
+ * child of the stream that is not supported. </td></tr>
+ * <tr><td> unsupported-version </td><td> the value of the 'version' attribute provided by
+ * the initiating entity in the stream header specifies a version of XMPP that is not
+ * supported. </td></tr>
+ * <tr><td> xml-not-well-formed </td><td> the initiating entity has sent XML that is
+ * not well-formed. </td></tr>
+ * </table>
+ *
+ * @author Gaston Dombiak
+ */
+public class StreamError {
+
+ private String code;
+
+ public StreamError(String code) {
+ super();
+ this.code = code;
+ }
+
+ /**
+ * Returns the error code.
+ *
+ * @return the error code.
+ */
+ public String getCode() {
+ return code;
+ }
+
+ public String toString() {
+ StringBuilder txt = new StringBuilder();
+ txt.append("stream:error (").append(code).append(")");
+ return txt.toString();
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/provider/EmbeddedExtensionProvider.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/provider/EmbeddedExtensionProvider.java
index e7b4b9317..84b5079f0 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/provider/EmbeddedExtensionProvider.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/provider/EmbeddedExtensionProvider.java
@@ -1,109 +1,109 @@
-/**
- * All rights reserved. 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 org.jivesoftware.smack.provider;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.jivesoftware.smack.packet.PacketExtension;
-import org.jivesoftware.smack.provider.PacketExtensionProvider;
-import org.jivesoftware.smack.util.PacketParserUtils;
-import org.jivesoftware.smackx.pubsub.provider.ItemProvider;
-import org.jivesoftware.smackx.pubsub.provider.ItemsProvider;
-import org.xmlpull.v1.XmlPullParser;
-
-/**
- *
- * This class simplifies parsing of embedded elements by using the
- * <a href="http://en.wikipedia.org/wiki/Template_method_pattern">Template Method Pattern</a>.
- * After extracting the current element attributes and content of any child elements, the template method
- * ({@link #createReturnExtension(String, String, Map, List)} is called. Subclasses
- * then override this method to create the specific return type.
- *
- * <p>To use this class, you simply register your subclasses as extension providers in the
- * <b>smack.properties</b> file. Then they will be automatically picked up and used to parse
- * any child elements.
- *
- * <pre>
- * For example, given the following message
- *
- * &lt;message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo&gt;
- * &lt;event xmlns='http://jabber.org/protocol/pubsub#event&gt;
- * &lt;items node='princely_musings'&gt;
- * &lt;item id='asdjkwei3i34234n356'&gt;
- * &lt;entry xmlns='http://www.w3.org/2005/Atom'&gt;
- * &lt;title&gt;Soliloquy&lt;/title&gt;
- * &lt;link rel='alternative' type='text/html'/&gt;
- * &lt;id>tag:denmark.lit,2003:entry-32397&lt;/id&gt;
- * &lt;/entry&gt;
- * &lt;/item&gt;
- * &lt;/items&gt;
- * &lt;/event&gt;
- * &lt;/message&gt;
- *
- * I would have a classes
- * {@link ItemsProvider} extends {@link EmbeddedExtensionProvider}
- * {@link ItemProvider} extends {@link EmbeddedExtensionProvider}
- * and
- * AtomProvider extends {@link PacketExtensionProvider}
- *
- * These classes are then registered in the meta-inf/smack.providers file
- * as follows.
- *
- * &lt;extensionProvider&gt;
- * &lt;elementName&gt;items&lt;/elementName&gt;
- * &lt;namespace&gt;http://jabber.org/protocol/pubsub#event&lt;/namespace&gt;
- * &lt;className&gt;org.jivesoftware.smackx.provider.ItemsEventProvider&lt;/className&gt;
- * &lt;/extensionProvider&gt;
- * &lt;extensionProvider&gt;
- * &lt;elementName&gt;item&lt;/elementName&gt;
- * &lt;namespace&gt;http://jabber.org/protocol/pubsub#event&lt;/namespace&gt;
- * &lt;className&gt;org.jivesoftware.smackx.provider.ItemProvider&lt;/className&gt;
- * &lt;/extensionProvider&gt;
- *
- * </pre>
- *
- * @author Robin Collier
- */
-abstract public class EmbeddedExtensionProvider implements PacketExtensionProvider
-{
-
- final public PacketExtension parseExtension(XmlPullParser parser) throws Exception
- {
- String namespace = parser.getNamespace();
- String name = parser.getName();
- Map<String, String> attMap = new HashMap<String, String>();
-
- for(int i=0; i<parser.getAttributeCount(); i++)
- {
- attMap.put(parser.getAttributeName(i), parser.getAttributeValue(i));
- }
- List<PacketExtension> extensions = new ArrayList<PacketExtension>();
-
- do
- {
- int tag = parser.next();
-
- if (tag == XmlPullParser.START_TAG)
- extensions.add(PacketParserUtils.parsePacketExtension(parser.getName(), parser.getNamespace(), parser));
- } while (!name.equals(parser.getName()));
-
- return createReturnExtension(name, namespace, attMap, extensions);
- }
-
- abstract protected PacketExtension createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attributeMap, List<? extends PacketExtension> content);
-}
+/**
+ * All rights reserved. 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 org.jivesoftware.smack.provider;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.jivesoftware.smack.packet.PacketExtension;
+import org.jivesoftware.smack.provider.PacketExtensionProvider;
+import org.jivesoftware.smack.util.PacketParserUtils;
+import org.jivesoftware.smackx.pubsub.provider.ItemProvider;
+import org.jivesoftware.smackx.pubsub.provider.ItemsProvider;
+import org.xmlpull.v1.XmlPullParser;
+
+/**
+ *
+ * This class simplifies parsing of embedded elements by using the
+ * <a href="http://en.wikipedia.org/wiki/Template_method_pattern">Template Method Pattern</a>.
+ * After extracting the current element attributes and content of any child elements, the template method
+ * ({@link #createReturnExtension(String, String, Map, List)} is called. Subclasses
+ * then override this method to create the specific return type.
+ *
+ * <p>To use this class, you simply register your subclasses as extension providers in the
+ * <b>smack.properties</b> file. Then they will be automatically picked up and used to parse
+ * any child elements.
+ *
+ * <pre>
+ * For example, given the following message
+ *
+ * &lt;message from='pubsub.shakespeare.lit' to='francisco@denmark.lit' id='foo&gt;
+ * &lt;event xmlns='http://jabber.org/protocol/pubsub#event&gt;
+ * &lt;items node='princely_musings'&gt;
+ * &lt;item id='asdjkwei3i34234n356'&gt;
+ * &lt;entry xmlns='http://www.w3.org/2005/Atom'&gt;
+ * &lt;title&gt;Soliloquy&lt;/title&gt;
+ * &lt;link rel='alternative' type='text/html'/&gt;
+ * &lt;id>tag:denmark.lit,2003:entry-32397&lt;/id&gt;
+ * &lt;/entry&gt;
+ * &lt;/item&gt;
+ * &lt;/items&gt;
+ * &lt;/event&gt;
+ * &lt;/message&gt;
+ *
+ * I would have a classes
+ * {@link ItemsProvider} extends {@link EmbeddedExtensionProvider}
+ * {@link ItemProvider} extends {@link EmbeddedExtensionProvider}
+ * and
+ * AtomProvider extends {@link PacketExtensionProvider}
+ *
+ * These classes are then registered in the meta-inf/smack.providers file
+ * as follows.
+ *
+ * &lt;extensionProvider&gt;
+ * &lt;elementName&gt;items&lt;/elementName&gt;
+ * &lt;namespace&gt;http://jabber.org/protocol/pubsub#event&lt;/namespace&gt;
+ * &lt;className&gt;org.jivesoftware.smackx.provider.ItemsEventProvider&lt;/className&gt;
+ * &lt;/extensionProvider&gt;
+ * &lt;extensionProvider&gt;
+ * &lt;elementName&gt;item&lt;/elementName&gt;
+ * &lt;namespace&gt;http://jabber.org/protocol/pubsub#event&lt;/namespace&gt;
+ * &lt;className&gt;org.jivesoftware.smackx.provider.ItemProvider&lt;/className&gt;
+ * &lt;/extensionProvider&gt;
+ *
+ * </pre>
+ *
+ * @author Robin Collier
+ */
+abstract public class EmbeddedExtensionProvider implements PacketExtensionProvider
+{
+
+ final public PacketExtension parseExtension(XmlPullParser parser) throws Exception
+ {
+ String namespace = parser.getNamespace();
+ String name = parser.getName();
+ Map<String, String> attMap = new HashMap<String, String>();
+
+ for(int i=0; i<parser.getAttributeCount(); i++)
+ {
+ attMap.put(parser.getAttributeName(i), parser.getAttributeValue(i));
+ }
+ List<PacketExtension> extensions = new ArrayList<PacketExtension>();
+
+ do
+ {
+ int tag = parser.next();
+
+ if (tag == XmlPullParser.START_TAG)
+ extensions.add(PacketParserUtils.parsePacketExtension(parser.getName(), parser.getNamespace(), parser));
+ } while (!name.equals(parser.getName()));
+
+ return createReturnExtension(name, namespace, attMap, extensions);
+ }
+
+ abstract protected PacketExtension createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attributeMap, List<? extends PacketExtension> content);
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/provider/PrivacyProvider.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/provider/PrivacyProvider.java
index 62b31205d..4ce9ea659 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/provider/PrivacyProvider.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/provider/PrivacyProvider.java
@@ -15,137 +15,137 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jivesoftware.smack.provider;
-
-import org.jivesoftware.smack.packet.DefaultPacketExtension;
-import org.jivesoftware.smack.packet.IQ;
-import org.jivesoftware.smack.packet.Privacy;
-import org.jivesoftware.smack.packet.PrivacyItem;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.util.ArrayList;
-
-/**
- * The PrivacyProvider parses {@link Privacy} packets. {@link Privacy}
- * Parses the <tt>query</tt> sub-document and creates an instance of {@link Privacy}.
- * For each <tt>item</tt> in the <tt>list</tt> element, it creates an instance
- * of {@link PrivacyItem} and {@link org.jivesoftware.smack.packet.PrivacyItem.PrivacyRule}.
- *
- * @author Francisco Vives
- */
-public class PrivacyProvider implements IQProvider {
-
- public PrivacyProvider() {
- }
-
- public IQ parseIQ(XmlPullParser parser) throws Exception {
- Privacy privacy = new Privacy();
- /* privacy.addExtension(PacketParserUtils.parsePacketExtension(parser
- .getName(), parser.getNamespace(), parser)); */
- privacy.addExtension(new DefaultPacketExtension(parser.getName(), parser.getNamespace()));
- boolean done = false;
- while (!done) {
- int eventType = parser.next();
- if (eventType == XmlPullParser.START_TAG) {
- if (parser.getName().equals("active")) {
- String activeName = parser.getAttributeValue("", "name");
- if (activeName == null) {
- privacy.setDeclineActiveList(true);
- } else {
- privacy.setActiveName(activeName);
- }
- }
- else if (parser.getName().equals("default")) {
- String defaultName = parser.getAttributeValue("", "name");
- if (defaultName == null) {
- privacy.setDeclineDefaultList(true);
- } else {
- privacy.setDefaultName(defaultName);
- }
- }
- else if (parser.getName().equals("list")) {
- parseList(parser, privacy);
- }
- }
- else if (eventType == XmlPullParser.END_TAG) {
- if (parser.getName().equals("query")) {
- done = true;
- }
- }
- }
-
- return privacy;
- }
-
- // Parse the list complex type
- public void parseList(XmlPullParser parser, Privacy privacy) throws Exception {
- boolean done = false;
- String listName = parser.getAttributeValue("", "name");
- ArrayList<PrivacyItem> items = new ArrayList<PrivacyItem>();
- while (!done) {
- int eventType = parser.next();
- if (eventType == XmlPullParser.START_TAG) {
- if (parser.getName().equals("item")) {
- items.add(parseItem(parser));
- }
- }
- else if (eventType == XmlPullParser.END_TAG) {
- if (parser.getName().equals("list")) {
- done = true;
- }
- }
- }
-
- privacy.setPrivacyList(listName, items);
- }
-
- // Parse the list complex type
- public PrivacyItem parseItem(XmlPullParser parser) throws Exception {
- boolean done = false;
- // Retrieves the required attributes
- String actionValue = parser.getAttributeValue("", "action");
- String orderValue = parser.getAttributeValue("", "order");
- String type = parser.getAttributeValue("", "type");
-
- /*
- * According the action value it sets the allow status. The fall-through action is assumed
- * to be "allow"
- */
- boolean allow = true;
- if ("allow".equalsIgnoreCase(actionValue)) {
- allow = true;
- } else if ("deny".equalsIgnoreCase(actionValue)) {
- allow = false;
- }
- // Set the order number
- int order = Integer.parseInt(orderValue);
-
- // Create the privacy item
- PrivacyItem item = new PrivacyItem(type, allow, order);
- item.setValue(parser.getAttributeValue("", "value"));
-
- while (!done) {
- int eventType = parser.next();
- if (eventType == XmlPullParser.START_TAG) {
- if (parser.getName().equals("iq")) {
- item.setFilterIQ(true);
- }
- if (parser.getName().equals("message")) {
- item.setFilterMessage(true);
- }
- if (parser.getName().equals("presence-in")) {
- item.setFilterPresence_in(true);
- }
- if (parser.getName().equals("presence-out")) {
- item.setFilterPresence_out(true);
- }
- }
- else if (eventType == XmlPullParser.END_TAG) {
- if (parser.getName().equals("item")) {
- done = true;
- }
- }
- }
- return item;
- }
-}
+package org.jivesoftware.smack.provider;
+
+import org.jivesoftware.smack.packet.DefaultPacketExtension;
+import org.jivesoftware.smack.packet.IQ;
+import org.jivesoftware.smack.packet.Privacy;
+import org.jivesoftware.smack.packet.PrivacyItem;
+import org.xmlpull.v1.XmlPullParser;
+
+import java.util.ArrayList;
+
+/**
+ * The PrivacyProvider parses {@link Privacy} packets. {@link Privacy}
+ * Parses the <tt>query</tt> sub-document and creates an instance of {@link Privacy}.
+ * For each <tt>item</tt> in the <tt>list</tt> element, it creates an instance
+ * of {@link PrivacyItem} and {@link org.jivesoftware.smack.packet.PrivacyItem.PrivacyRule}.
+ *
+ * @author Francisco Vives
+ */
+public class PrivacyProvider implements IQProvider {
+
+ public PrivacyProvider() {
+ }
+
+ public IQ parseIQ(XmlPullParser parser) throws Exception {
+ Privacy privacy = new Privacy();
+ /* privacy.addExtension(PacketParserUtils.parsePacketExtension(parser
+ .getName(), parser.getNamespace(), parser)); */
+ privacy.addExtension(new DefaultPacketExtension(parser.getName(), parser.getNamespace()));
+ boolean done = false;
+ while (!done) {
+ int eventType = parser.next();
+ if (eventType == XmlPullParser.START_TAG) {
+ if (parser.getName().equals("active")) {
+ String activeName = parser.getAttributeValue("", "name");
+ if (activeName == null) {
+ privacy.setDeclineActiveList(true);
+ } else {
+ privacy.setActiveName(activeName);
+ }
+ }
+ else if (parser.getName().equals("default")) {
+ String defaultName = parser.getAttributeValue("", "name");
+ if (defaultName == null) {
+ privacy.setDeclineDefaultList(true);
+ } else {
+ privacy.setDefaultName(defaultName);
+ }
+ }
+ else if (parser.getName().equals("list")) {
+ parseList(parser, privacy);
+ }
+ }
+ else if (eventType == XmlPullParser.END_TAG) {
+ if (parser.getName().equals("query")) {
+ done = true;
+ }
+ }
+ }
+
+ return privacy;
+ }
+
+ // Parse the list complex type
+ public void parseList(XmlPullParser parser, Privacy privacy) throws Exception {
+ boolean done = false;
+ String listName = parser.getAttributeValue("", "name");
+ ArrayList<PrivacyItem> items = new ArrayList<PrivacyItem>();
+ while (!done) {
+ int eventType = parser.next();
+ if (eventType == XmlPullParser.START_TAG) {
+ if (parser.getName().equals("item")) {
+ items.add(parseItem(parser));
+ }
+ }
+ else if (eventType == XmlPullParser.END_TAG) {
+ if (parser.getName().equals("list")) {
+ done = true;
+ }
+ }
+ }
+
+ privacy.setPrivacyList(listName, items);
+ }
+
+ // Parse the list complex type
+ public PrivacyItem parseItem(XmlPullParser parser) throws Exception {
+ boolean done = false;
+ // Retrieves the required attributes
+ String actionValue = parser.getAttributeValue("", "action");
+ String orderValue = parser.getAttributeValue("", "order");
+ String type = parser.getAttributeValue("", "type");
+
+ /*
+ * According the action value it sets the allow status. The fall-through action is assumed
+ * to be "allow"
+ */
+ boolean allow = true;
+ if ("allow".equalsIgnoreCase(actionValue)) {
+ allow = true;
+ } else if ("deny".equalsIgnoreCase(actionValue)) {
+ allow = false;
+ }
+ // Set the order number
+ int order = Integer.parseInt(orderValue);
+
+ // Create the privacy item
+ PrivacyItem item = new PrivacyItem(type, allow, order);
+ item.setValue(parser.getAttributeValue("", "value"));
+
+ while (!done) {
+ int eventType = parser.next();
+ if (eventType == XmlPullParser.START_TAG) {
+ if (parser.getName().equals("iq")) {
+ item.setFilterIQ(true);
+ }
+ if (parser.getName().equals("message")) {
+ item.setFilterMessage(true);
+ }
+ if (parser.getName().equals("presence-in")) {
+ item.setFilterPresence_in(true);
+ }
+ if (parser.getName().equals("presence-out")) {
+ item.setFilterPresence_out(true);
+ }
+ }
+ else if (eventType == XmlPullParser.END_TAG) {
+ if (parser.getName().equals("item")) {
+ done = true;
+ }
+ }
+ }
+ return item;
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLAnonymous.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLAnonymous.java
index 8ef9d1846..b959e968f 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLAnonymous.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLAnonymous.java
@@ -1,62 +1,62 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- *
- * All rights reserved. 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 org.jivesoftware.smack.sasl;
-
-import org.jivesoftware.smack.SASLAuthentication;
-
-import java.io.IOException;
-import javax.security.auth.callback.CallbackHandler;
-
-/**
- * Implementation of the SASL ANONYMOUS mechanism
- *
- * @author Jay Kline
- */
-public class SASLAnonymous extends SASLMechanism {
-
- public SASLAnonymous(SASLAuthentication saslAuthentication) {
- super(saslAuthentication);
- }
-
- protected String getName() {
- return "ANONYMOUS";
- }
-
- public void authenticate(String username, String host, CallbackHandler cbh) throws IOException {
- authenticate();
- }
-
- public void authenticate(String username, String host, String password) throws IOException {
- authenticate();
- }
-
- protected void authenticate() throws IOException {
- // Send the authentication to the server
- getSASLAuthentication().send(new AuthMechanism(getName(), null));
- }
-
- public void challengeReceived(String challenge) throws IOException {
- // Build the challenge response stanza encoding the response text
- // and send the authentication to the server
- getSASLAuthentication().send(new Response());
- }
-
-
-}
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ *
+ * All rights reserved. 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 org.jivesoftware.smack.sasl;
+
+import org.jivesoftware.smack.SASLAuthentication;
+
+import java.io.IOException;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ * Implementation of the SASL ANONYMOUS mechanism
+ *
+ * @author Jay Kline
+ */
+public class SASLAnonymous extends SASLMechanism {
+
+ public SASLAnonymous(SASLAuthentication saslAuthentication) {
+ super(saslAuthentication);
+ }
+
+ protected String getName() {
+ return "ANONYMOUS";
+ }
+
+ public void authenticate(String username, String host, CallbackHandler cbh) throws IOException {
+ authenticate();
+ }
+
+ public void authenticate(String username, String host, String password) throws IOException {
+ authenticate();
+ }
+
+ protected void authenticate() throws IOException {
+ // Send the authentication to the server
+ getSASLAuthentication().send(new AuthMechanism(getName(), null));
+ }
+
+ public void challengeReceived(String challenge) throws IOException {
+ // Build the challenge response stanza encoding the response text
+ // and send the authentication to the server
+ getSASLAuthentication().send(new Response());
+ }
+
+
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLCramMD5Mechanism.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLCramMD5Mechanism.java
index 82d218fd0..f2be038e0 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLCramMD5Mechanism.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLCramMD5Mechanism.java
@@ -1,38 +1,38 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- *
- * All rights reserved. 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 org.jivesoftware.smack.sasl;
-
-import org.jivesoftware.smack.SASLAuthentication;
-
-/**
- * Implementation of the SASL CRAM-MD5 mechanism
- *
- * @author Jay Kline
- */
-public class SASLCramMD5Mechanism extends SASLMechanism {
-
- public SASLCramMD5Mechanism(SASLAuthentication saslAuthentication) {
- super(saslAuthentication);
- }
-
- protected String getName() {
- return "CRAM-MD5";
- }
-}
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ *
+ * All rights reserved. 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 org.jivesoftware.smack.sasl;
+
+import org.jivesoftware.smack.SASLAuthentication;
+
+/**
+ * Implementation of the SASL CRAM-MD5 mechanism
+ *
+ * @author Jay Kline
+ */
+public class SASLCramMD5Mechanism extends SASLMechanism {
+
+ public SASLCramMD5Mechanism(SASLAuthentication saslAuthentication) {
+ super(saslAuthentication);
+ }
+
+ protected String getName() {
+ return "CRAM-MD5";
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLDigestMD5Mechanism.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLDigestMD5Mechanism.java
index 7af65fb96..bfaec0ab4 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLDigestMD5Mechanism.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLDigestMD5Mechanism.java
@@ -1,38 +1,38 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- *
- * All rights reserved. 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 org.jivesoftware.smack.sasl;
-
-import org.jivesoftware.smack.SASLAuthentication;
-
-/**
- * Implementation of the SASL DIGEST-MD5 mechanism
- *
- * @author Jay Kline
- */
-public class SASLDigestMD5Mechanism extends SASLMechanism {
-
- public SASLDigestMD5Mechanism(SASLAuthentication saslAuthentication) {
- super(saslAuthentication);
- }
-
- protected String getName() {
- return "DIGEST-MD5";
- }
-}
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ *
+ * All rights reserved. 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 org.jivesoftware.smack.sasl;
+
+import org.jivesoftware.smack.SASLAuthentication;
+
+/**
+ * Implementation of the SASL DIGEST-MD5 mechanism
+ *
+ * @author Jay Kline
+ */
+public class SASLDigestMD5Mechanism extends SASLMechanism {
+
+ public SASLDigestMD5Mechanism(SASLAuthentication saslAuthentication) {
+ super(saslAuthentication);
+ }
+
+ protected String getName() {
+ return "DIGEST-MD5";
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLExternalMechanism.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLExternalMechanism.java
index dff18fb58..248a650e6 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLExternalMechanism.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLExternalMechanism.java
@@ -1,59 +1,59 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- *
- * All rights reserved. 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 org.jivesoftware.smack.sasl;
-
-import org.jivesoftware.smack.SASLAuthentication;
-
-/**
- * Implementation of the SASL EXTERNAL mechanism.
- *
- * To effectively use this mechanism, Java must be configured to properly
- * supply a client SSL certificate (of some sort) to the server. It is up
- * to the implementer to determine how to do this. Here is one method:
- *
- * Create a java keystore with your SSL certificate in it:
- * keytool -genkey -alias username -dname "cn=username,ou=organizationalUnit,o=organizationaName,l=locality,s=state,c=country"
- *
- * Next, set the System Properties:
- * <ul>
- * <li>javax.net.ssl.keyStore to the location of the keyStore
- * <li>javax.net.ssl.keyStorePassword to the password of the keyStore
- * <li>javax.net.ssl.trustStore to the location of the trustStore
- * <li>javax.net.ssl.trustStorePassword to the the password of the trustStore
- * </ul>
- *
- * Then, when the server requests or requires the client certificate, java will
- * simply provide the one in the keyStore.
- *
- * Also worth noting is the EXTERNAL mechanism in Smack is not enabled by default.
- * To enable it, the implementer will need to call SASLAuthentication.supportSASLMechamism("EXTERNAL");
- *
- * @author Jay Kline
- */
-public class SASLExternalMechanism extends SASLMechanism {
-
- public SASLExternalMechanism(SASLAuthentication saslAuthentication) {
- super(saslAuthentication);
- }
-
- protected String getName() {
- return "EXTERNAL";
- }
-}
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ *
+ * All rights reserved. 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 org.jivesoftware.smack.sasl;
+
+import org.jivesoftware.smack.SASLAuthentication;
+
+/**
+ * Implementation of the SASL EXTERNAL mechanism.
+ *
+ * To effectively use this mechanism, Java must be configured to properly
+ * supply a client SSL certificate (of some sort) to the server. It is up
+ * to the implementer to determine how to do this. Here is one method:
+ *
+ * Create a java keystore with your SSL certificate in it:
+ * keytool -genkey -alias username -dname "cn=username,ou=organizationalUnit,o=organizationaName,l=locality,s=state,c=country"
+ *
+ * Next, set the System Properties:
+ * <ul>
+ * <li>javax.net.ssl.keyStore to the location of the keyStore
+ * <li>javax.net.ssl.keyStorePassword to the password of the keyStore
+ * <li>javax.net.ssl.trustStore to the location of the trustStore
+ * <li>javax.net.ssl.trustStorePassword to the the password of the trustStore
+ * </ul>
+ *
+ * Then, when the server requests or requires the client certificate, java will
+ * simply provide the one in the keyStore.
+ *
+ * Also worth noting is the EXTERNAL mechanism in Smack is not enabled by default.
+ * To enable it, the implementer will need to call SASLAuthentication.supportSASLMechamism("EXTERNAL");
+ *
+ * @author Jay Kline
+ */
+public class SASLExternalMechanism extends SASLMechanism {
+
+ public SASLExternalMechanism(SASLAuthentication saslAuthentication) {
+ super(saslAuthentication);
+ }
+
+ protected String getName() {
+ return "EXTERNAL";
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLGSSAPIMechanism.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLGSSAPIMechanism.java
index 3f0b7d899..8101ca5b2 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLGSSAPIMechanism.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLGSSAPIMechanism.java
@@ -1,89 +1,89 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- *
- * All rights reserved. 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 org.jivesoftware.smack.sasl;
-
-import org.jivesoftware.smack.SASLAuthentication;
-import org.jivesoftware.smack.XMPPException;
-
-import java.io.IOException;
-import java.util.Map;
-import java.util.HashMap;
-import javax.security.sasl.Sasl;
-import javax.security.auth.callback.CallbackHandler;
-
-/**
- * Implementation of the SASL GSSAPI mechanism
- *
- * @author Jay Kline
- */
-public class SASLGSSAPIMechanism extends SASLMechanism {
-
- public SASLGSSAPIMechanism(SASLAuthentication saslAuthentication) {
- super(saslAuthentication);
-
- System.setProperty("javax.security.auth.useSubjectCredsOnly","false");
- System.setProperty("java.security.auth.login.config","gss.conf");
-
- }
-
- protected String getName() {
- return "GSSAPI";
- }
-
- /**
- * Builds and sends the <tt>auth</tt> stanza to the server.
- * This overrides from the abstract class because the initial token
- * needed for GSSAPI is binary, and not safe to put in a string, thus
- * getAuthenticationText() cannot be used.
- *
- * @param username the username of the user being authenticated.
- * @param host the hostname where the user account resides.
- * @param cbh the CallbackHandler (not used with GSSAPI)
- * @throws IOException If a network error occures while authenticating.
- */
- public void authenticate(String username, String host, CallbackHandler cbh) throws IOException, XMPPException {
- String[] mechanisms = { getName() };
- Map<String,String> props = new HashMap<String,String>();
- props.put(Sasl.SERVER_AUTH,"TRUE");
- sc = Sasl.createSaslClient(mechanisms, username, "xmpp", host, props, cbh);
- authenticate();
- }
-
- /**
- * Builds and sends the <tt>auth</tt> stanza to the server.
- * This overrides from the abstract class because the initial token
- * needed for GSSAPI is binary, and not safe to put in a string, thus
- * getAuthenticationText() cannot be used.
- *
- * @param username the username of the user being authenticated.
- * @param host the hostname where the user account resides.
- * @param password the password of the user (ignored for GSSAPI)
- * @throws IOException If a network error occures while authenticating.
- */
- public void authenticate(String username, String host, String password) throws IOException, XMPPException {
- String[] mechanisms = { getName() };
- Map<String,String> props = new HashMap<String, String>();
- props.put(Sasl.SERVER_AUTH,"TRUE");
- sc = Sasl.createSaslClient(mechanisms, username, "xmpp", host, props, this);
- authenticate();
- }
-
-
-}
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ *
+ * All rights reserved. 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 org.jivesoftware.smack.sasl;
+
+import org.jivesoftware.smack.SASLAuthentication;
+import org.jivesoftware.smack.XMPPException;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.HashMap;
+import javax.security.sasl.Sasl;
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ * Implementation of the SASL GSSAPI mechanism
+ *
+ * @author Jay Kline
+ */
+public class SASLGSSAPIMechanism extends SASLMechanism {
+
+ public SASLGSSAPIMechanism(SASLAuthentication saslAuthentication) {
+ super(saslAuthentication);
+
+ System.setProperty("javax.security.auth.useSubjectCredsOnly","false");
+ System.setProperty("java.security.auth.login.config","gss.conf");
+
+ }
+
+ protected String getName() {
+ return "GSSAPI";
+ }
+
+ /**
+ * Builds and sends the <tt>auth</tt> stanza to the server.
+ * This overrides from the abstract class because the initial token
+ * needed for GSSAPI is binary, and not safe to put in a string, thus
+ * getAuthenticationText() cannot be used.
+ *
+ * @param username the username of the user being authenticated.
+ * @param host the hostname where the user account resides.
+ * @param cbh the CallbackHandler (not used with GSSAPI)
+ * @throws IOException If a network error occures while authenticating.
+ */
+ public void authenticate(String username, String host, CallbackHandler cbh) throws IOException, XMPPException {
+ String[] mechanisms = { getName() };
+ Map<String,String> props = new HashMap<String,String>();
+ props.put(Sasl.SERVER_AUTH,"TRUE");
+ sc = Sasl.createSaslClient(mechanisms, username, "xmpp", host, props, cbh);
+ authenticate();
+ }
+
+ /**
+ * Builds and sends the <tt>auth</tt> stanza to the server.
+ * This overrides from the abstract class because the initial token
+ * needed for GSSAPI is binary, and not safe to put in a string, thus
+ * getAuthenticationText() cannot be used.
+ *
+ * @param username the username of the user being authenticated.
+ * @param host the hostname where the user account resides.
+ * @param password the password of the user (ignored for GSSAPI)
+ * @throws IOException If a network error occures while authenticating.
+ */
+ public void authenticate(String username, String host, String password) throws IOException, XMPPException {
+ String[] mechanisms = { getName() };
+ Map<String,String> props = new HashMap<String, String>();
+ props.put(Sasl.SERVER_AUTH,"TRUE");
+ sc = Sasl.createSaslClient(mechanisms, username, "xmpp", host, props, this);
+ authenticate();
+ }
+
+
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLMechanism.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLMechanism.java
index 0d096f2a2..45212e460 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLMechanism.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLMechanism.java
@@ -1,404 +1,404 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- * Copyright 2003-2007 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smack.sasl;
-
-import org.jivesoftware.smack.XMPPException;
-import org.jivesoftware.smack.SASLAuthentication;
-import org.jivesoftware.smack.packet.Packet;
-import org.jivesoftware.smack.util.StringUtils;
-
-import java.io.IOException;
-import java.util.Map;
-import java.util.HashMap;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.sasl.RealmCallback;
-import javax.security.sasl.RealmChoiceCallback;
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
-
-/**
- * Base class for SASL mechanisms. Subclasses must implement these methods:
- * <ul>
- * <li>{@link #getName()} -- returns the common name of the SASL mechanism.</li>
- * </ul>
- * Subclasses will likely want to implement their own versions of these mthods:
- * <li>{@link #authenticate(String, String, String)} -- Initiate authentication stanza using the
- * deprecated method.</li>
- * <li>{@link #authenticate(String, String, CallbackHandler)} -- Initiate authentication stanza
- * using the CallbackHandler method.</li>
- * <li>{@link #challengeReceived(String)} -- Handle a challenge from the server.</li>
- * </ul>
- *
- * Basic XMPP SASL authentication steps:
- * 1. Client authentication initialization, stanza sent to the server (Base64 encoded):
- * <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>
- * 2. Server sends back to the client the challenge response (Base64 encoded)
- * sample:
- * realm=<sasl server realm>,nonce="OA6MG9tEQGm2hh",qop="auth",charset=utf-8,algorithm=md5-sess
- * 3. The client responds back to the server (Base 64 encoded):
- * sample:
- * username=<userid>,realm=<sasl server realm from above>,nonce="OA6MG9tEQGm2hh",
- * cnonce="OA6MHXh6VqTrRk",nc=00000001,qop=auth,
- * digest-uri=<digesturi>,
- * response=d388dad90d4bbd760a152321f2143af7,
- * charset=utf-8,
- * authzid=<id>
- * 4. The server evaluates if the user is present and contained in the REALM
- * if successful it sends: <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/> (Base64 encoded)
- * if not successful it sends:
- * sample:
- * <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
- * cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZA==
- * </challenge>
- *
-
- *
- * @author Jay Kline
- */
-public abstract class SASLMechanism implements CallbackHandler {
-
- private SASLAuthentication saslAuthentication;
- protected SaslClient sc;
- protected String authenticationId;
- protected String password;
- protected String hostname;
-
- public SASLMechanism(SASLAuthentication saslAuthentication) {
- this.saslAuthentication = saslAuthentication;
- }
-
- /**
- * Builds and sends the <tt>auth</tt> stanza to the server. Note that this method of
- * authentication is not recommended, since it is very inflexable. Use
- * {@link #authenticate(String, String, CallbackHandler)} whenever possible.
- *
- * Explanation of auth stanza:
- *
- * The client authentication stanza needs to include the digest-uri of the form: xmpp/serverName
- * From RFC-2831:
- * digest-uri = "digest-uri" "=" digest-uri-value
- * digest-uri-value = serv-type "/" host [ "/" serv-name ]
- *
- * digest-uri:
- * Indicates the principal name of the service with which the client
- * wishes to connect, formed from the serv-type, host, and serv-name.
- * For example, the FTP service
- * on "ftp.example.com" would have a "digest-uri" value of "ftp/ftp.example.com"; the SMTP
- * server from the example above would have a "digest-uri" value of
- * "smtp/mail3.example.com/example.com".
- *
- * host:
- * The DNS host name or IP address for the service requested. The DNS host name
- * must be the fully-qualified canonical name of the host. The DNS host name is the
- * preferred form; see notes on server processing of the digest-uri.
- *
- * serv-name:
- * Indicates the name of the service if it is replicated. The service is
- * considered to be replicated if the client's service-location process involves resolution
- * using standard DNS lookup operations, and if these operations involve DNS records (such
- * as SRV, or MX) which resolve one DNS name into a set of other DNS names. In this case,
- * the initial name used by the client is the "serv-name", and the final name is the "host"
- * component. For example, the incoming mail service for "example.com" may be replicated
- * through the use of MX records stored in the DNS, one of which points at an SMTP server
- * called "mail3.example.com"; it's "serv-name" would be "example.com", it's "host" would be
- * "mail3.example.com". If the service is not replicated, or the serv-name is identical to
- * the host, then the serv-name component MUST be omitted
- *
- * digest-uri verification is needed for ejabberd 2.0.3 and higher
- *
- * @param username the username of the user being authenticated.
- * @param host the hostname where the user account resides.
- * @param serviceName the xmpp service location - used by the SASL client in digest-uri creation
- * serviceName format is: host [ "/" serv-name ] as per RFC-2831
- * @param password the password for this account.
- * @throws IOException If a network error occurs while authenticating.
- * @throws XMPPException If a protocol error occurs or the user is not authenticated.
- */
- public void authenticate(String username, String host, String serviceName, String password) throws IOException, XMPPException {
- //Since we were not provided with a CallbackHandler, we will use our own with the given
- //information
-
- //Set the authenticationID as the username, since they must be the same in this case.
- this.authenticationId = username;
- this.password = password;
- this.hostname = host;
-
- String[] mechanisms = { getName() };
- Map<String,String> props = new HashMap<String,String>();
- sc = Sasl.createSaslClient(mechanisms, username, "xmpp", serviceName, props, this);
- authenticate();
- }
-
- /**
- * Same as {@link #authenticate(String, String, String, String)}, but with the hostname used as the serviceName.
- * <p>
- * Kept for backward compatibility only.
- *
- * @param username the username of the user being authenticated.
- * @param host the hostname where the user account resides.
- * @param password the password for this account.
- * @throws IOException If a network error occurs while authenticating.
- * @throws XMPPException If a protocol error occurs or the user is not authenticated.
- * @deprecated Please use {@link #authenticate(String, String, String, String)} instead.
- */
- public void authenticate(String username, String host, String password) throws IOException, XMPPException {
- authenticate(username, host, host, password);
- }
-
- /**
- * Builds and sends the <tt>auth</tt> stanza to the server. The callback handler will handle
- * any additional information, such as the authentication ID or realm, if it is needed.
- *
- * @param username the username of the user being authenticated.
- * @param host the hostname where the user account resides.
- * @param cbh the CallbackHandler to obtain user information.
- * @throws IOException If a network error occures while authenticating.
- * @throws XMPPException If a protocol error occurs or the user is not authenticated.
- */
- public void authenticate(String username, String host, CallbackHandler cbh) throws IOException, XMPPException {
- String[] mechanisms = { getName() };
- Map<String,String> props = new HashMap<String,String>();
- sc = Sasl.createSaslClient(mechanisms, username, "xmpp", host, props, cbh);
- authenticate();
- }
-
- protected void authenticate() throws IOException, XMPPException {
- String authenticationText = null;
- try {
- if(sc.hasInitialResponse()) {
- byte[] response = sc.evaluateChallenge(new byte[0]);
- authenticationText = StringUtils.encodeBase64(response, false);
- }
- } catch (SaslException e) {
- throw new XMPPException("SASL authentication failed", e);
- }
-
- // Send the authentication to the server
- getSASLAuthentication().send(new AuthMechanism(getName(), authenticationText));
- }
-
-
- /**
- * The server is challenging the SASL mechanism for the stanza he just sent. Send a
- * response to the server's challenge.
- *
- * @param challenge a base64 encoded string representing the challenge.
- * @throws IOException if an exception sending the response occurs.
- */
- public void challengeReceived(String challenge) throws IOException {
- byte response[];
- if(challenge != null) {
- response = sc.evaluateChallenge(StringUtils.decodeBase64(challenge));
- } else {
- response = sc.evaluateChallenge(new byte[0]);
- }
-
- Packet responseStanza;
- if (response == null) {
- responseStanza = new Response();
- }
- else {
- responseStanza = new Response(StringUtils.encodeBase64(response, false));
- }
-
- // Send the authentication to the server
- getSASLAuthentication().send(responseStanza);
- }
-
- /**
- * Returns the common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or GSSAPI.
- *
- * @return the common name of the SASL mechanism.
- */
- protected abstract String getName();
-
-
- protected SASLAuthentication getSASLAuthentication() {
- return saslAuthentication;
- }
-
- /**
- *
- */
- public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
- for (int i = 0; i < callbacks.length; i++) {
- if (callbacks[i] instanceof NameCallback) {
- NameCallback ncb = (NameCallback)callbacks[i];
- ncb.setName(authenticationId);
- } else if(callbacks[i] instanceof PasswordCallback) {
- PasswordCallback pcb = (PasswordCallback)callbacks[i];
- pcb.setPassword(password.toCharArray());
- } else if(callbacks[i] instanceof RealmCallback) {
- RealmCallback rcb = (RealmCallback)callbacks[i];
- //Retrieve the REALM from the challenge response that the server returned when the client initiated the authentication
- //exchange. If this value is not null or empty, *this value* has to be sent back to the server in the client's response
- //to the server's challenge
- String text = rcb.getDefaultText();
- //The SASL client (sc) created in smack uses rcb.getText when creating the negotiatedRealm to send it back to the server
- //Make sure that this value matches the server's realm
- rcb.setText(text);
- } else if(callbacks[i] instanceof RealmChoiceCallback){
- //unused
- //RealmChoiceCallback rccb = (RealmChoiceCallback)callbacks[i];
- } else {
- throw new UnsupportedCallbackException(callbacks[i]);
- }
- }
- }
-
- /**
- * Initiating SASL authentication by select a mechanism.
- */
- public class AuthMechanism extends Packet {
- final private String name;
- final private String authenticationText;
-
- public AuthMechanism(String name, String authenticationText) {
- if (name == null) {
- throw new NullPointerException("SASL mechanism name shouldn't be null.");
- }
- this.name = name;
- this.authenticationText = authenticationText;
- }
-
- public String toXML() {
- StringBuilder stanza = new StringBuilder();
- stanza.append("<auth mechanism=\"").append(name);
- stanza.append("\" xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
- if (authenticationText != null &&
- authenticationText.trim().length() > 0) {
- stanza.append(authenticationText);
- }
- stanza.append("</auth>");
- return stanza.toString();
- }
- }
-
- /**
- * A SASL challenge stanza.
- */
- public static class Challenge extends Packet {
- final private String data;
-
- public Challenge(String data) {
- this.data = data;
- }
-
- public String toXML() {
- StringBuilder stanza = new StringBuilder();
- stanza.append("<challenge xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
- if (data != null &&
- data.trim().length() > 0) {
- stanza.append(data);
- }
- stanza.append("</challenge>");
- return stanza.toString();
- }
- }
-
- /**
- * A SASL response stanza.
- */
- public class Response extends Packet {
- final private String authenticationText;
-
- public Response() {
- authenticationText = null;
- }
-
- public Response(String authenticationText) {
- if (authenticationText == null || authenticationText.trim().length() == 0) {
- this.authenticationText = null;
- }
- else {
- this.authenticationText = authenticationText;
- }
- }
-
- public String toXML() {
- StringBuilder stanza = new StringBuilder();
- stanza.append("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
- if (authenticationText != null) {
- stanza.append(authenticationText);
- }
- stanza.append("</response>");
- return stanza.toString();
- }
- }
-
- /**
- * A SASL success stanza.
- */
- public static class Success extends Packet {
- final private String data;
-
- public Success(String data) {
- this.data = data;
- }
-
- public String toXML() {
- StringBuilder stanza = new StringBuilder();
- stanza.append("<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
- if (data != null &&
- data.trim().length() > 0) {
- stanza.append(data);
- }
- stanza.append("</success>");
- return stanza.toString();
- }
- }
-
- /**
- * A SASL failure stanza.
- */
- public static class Failure extends Packet {
- final private String condition;
-
- public Failure(String condition) {
- this.condition = condition;
- }
-
- /**
- * Get the SASL related error condition.
- *
- * @return the SASL related error condition.
- */
- public String getCondition() {
- return condition;
- }
-
- public String toXML() {
- StringBuilder stanza = new StringBuilder();
- stanza.append("<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
- if (condition != null &&
- condition.trim().length() > 0) {
- stanza.append("<").append(condition).append("/>");
- }
- stanza.append("</failure>");
- return stanza.toString();
- }
- }
-}
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2003-2007 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smack.sasl;
+
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smack.SASLAuthentication;
+import org.jivesoftware.smack.packet.Packet;
+import org.jivesoftware.smack.util.StringUtils;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.HashMap;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.sasl.RealmCallback;
+import javax.security.sasl.RealmChoiceCallback;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+/**
+ * Base class for SASL mechanisms. Subclasses must implement these methods:
+ * <ul>
+ * <li>{@link #getName()} -- returns the common name of the SASL mechanism.</li>
+ * </ul>
+ * Subclasses will likely want to implement their own versions of these mthods:
+ * <li>{@link #authenticate(String, String, String)} -- Initiate authentication stanza using the
+ * deprecated method.</li>
+ * <li>{@link #authenticate(String, String, CallbackHandler)} -- Initiate authentication stanza
+ * using the CallbackHandler method.</li>
+ * <li>{@link #challengeReceived(String)} -- Handle a challenge from the server.</li>
+ * </ul>
+ *
+ * Basic XMPP SASL authentication steps:
+ * 1. Client authentication initialization, stanza sent to the server (Base64 encoded):
+ * <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>
+ * 2. Server sends back to the client the challenge response (Base64 encoded)
+ * sample:
+ * realm=<sasl server realm>,nonce="OA6MG9tEQGm2hh",qop="auth",charset=utf-8,algorithm=md5-sess
+ * 3. The client responds back to the server (Base 64 encoded):
+ * sample:
+ * username=<userid>,realm=<sasl server realm from above>,nonce="OA6MG9tEQGm2hh",
+ * cnonce="OA6MHXh6VqTrRk",nc=00000001,qop=auth,
+ * digest-uri=<digesturi>,
+ * response=d388dad90d4bbd760a152321f2143af7,
+ * charset=utf-8,
+ * authzid=<id>
+ * 4. The server evaluates if the user is present and contained in the REALM
+ * if successful it sends: <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/> (Base64 encoded)
+ * if not successful it sends:
+ * sample:
+ * <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
+ * cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZA==
+ * </challenge>
+ *
+
+ *
+ * @author Jay Kline
+ */
+public abstract class SASLMechanism implements CallbackHandler {
+
+ private SASLAuthentication saslAuthentication;
+ protected SaslClient sc;
+ protected String authenticationId;
+ protected String password;
+ protected String hostname;
+
+ public SASLMechanism(SASLAuthentication saslAuthentication) {
+ this.saslAuthentication = saslAuthentication;
+ }
+
+ /**
+ * Builds and sends the <tt>auth</tt> stanza to the server. Note that this method of
+ * authentication is not recommended, since it is very inflexable. Use
+ * {@link #authenticate(String, String, CallbackHandler)} whenever possible.
+ *
+ * Explanation of auth stanza:
+ *
+ * The client authentication stanza needs to include the digest-uri of the form: xmpp/serverName
+ * From RFC-2831:
+ * digest-uri = "digest-uri" "=" digest-uri-value
+ * digest-uri-value = serv-type "/" host [ "/" serv-name ]
+ *
+ * digest-uri:
+ * Indicates the principal name of the service with which the client
+ * wishes to connect, formed from the serv-type, host, and serv-name.
+ * For example, the FTP service
+ * on "ftp.example.com" would have a "digest-uri" value of "ftp/ftp.example.com"; the SMTP
+ * server from the example above would have a "digest-uri" value of
+ * "smtp/mail3.example.com/example.com".
+ *
+ * host:
+ * The DNS host name or IP address for the service requested. The DNS host name
+ * must be the fully-qualified canonical name of the host. The DNS host name is the
+ * preferred form; see notes on server processing of the digest-uri.
+ *
+ * serv-name:
+ * Indicates the name of the service if it is replicated. The service is
+ * considered to be replicated if the client's service-location process involves resolution
+ * using standard DNS lookup operations, and if these operations involve DNS records (such
+ * as SRV, or MX) which resolve one DNS name into a set of other DNS names. In this case,
+ * the initial name used by the client is the "serv-name", and the final name is the "host"
+ * component. For example, the incoming mail service for "example.com" may be replicated
+ * through the use of MX records stored in the DNS, one of which points at an SMTP server
+ * called "mail3.example.com"; it's "serv-name" would be "example.com", it's "host" would be
+ * "mail3.example.com". If the service is not replicated, or the serv-name is identical to
+ * the host, then the serv-name component MUST be omitted
+ *
+ * digest-uri verification is needed for ejabberd 2.0.3 and higher
+ *
+ * @param username the username of the user being authenticated.
+ * @param host the hostname where the user account resides.
+ * @param serviceName the xmpp service location - used by the SASL client in digest-uri creation
+ * serviceName format is: host [ "/" serv-name ] as per RFC-2831
+ * @param password the password for this account.
+ * @throws IOException If a network error occurs while authenticating.
+ * @throws XMPPException If a protocol error occurs or the user is not authenticated.
+ */
+ public void authenticate(String username, String host, String serviceName, String password) throws IOException, XMPPException {
+ //Since we were not provided with a CallbackHandler, we will use our own with the given
+ //information
+
+ //Set the authenticationID as the username, since they must be the same in this case.
+ this.authenticationId = username;
+ this.password = password;
+ this.hostname = host;
+
+ String[] mechanisms = { getName() };
+ Map<String,String> props = new HashMap<String,String>();
+ sc = Sasl.createSaslClient(mechanisms, username, "xmpp", serviceName, props, this);
+ authenticate();
+ }
+
+ /**
+ * Same as {@link #authenticate(String, String, String, String)}, but with the hostname used as the serviceName.
+ * <p>
+ * Kept for backward compatibility only.
+ *
+ * @param username the username of the user being authenticated.
+ * @param host the hostname where the user account resides.
+ * @param password the password for this account.
+ * @throws IOException If a network error occurs while authenticating.
+ * @throws XMPPException If a protocol error occurs or the user is not authenticated.
+ * @deprecated Please use {@link #authenticate(String, String, String, String)} instead.
+ */
+ public void authenticate(String username, String host, String password) throws IOException, XMPPException {
+ authenticate(username, host, host, password);
+ }
+
+ /**
+ * Builds and sends the <tt>auth</tt> stanza to the server. The callback handler will handle
+ * any additional information, such as the authentication ID or realm, if it is needed.
+ *
+ * @param username the username of the user being authenticated.
+ * @param host the hostname where the user account resides.
+ * @param cbh the CallbackHandler to obtain user information.
+ * @throws IOException If a network error occures while authenticating.
+ * @throws XMPPException If a protocol error occurs or the user is not authenticated.
+ */
+ public void authenticate(String username, String host, CallbackHandler cbh) throws IOException, XMPPException {
+ String[] mechanisms = { getName() };
+ Map<String,String> props = new HashMap<String,String>();
+ sc = Sasl.createSaslClient(mechanisms, username, "xmpp", host, props, cbh);
+ authenticate();
+ }
+
+ protected void authenticate() throws IOException, XMPPException {
+ String authenticationText = null;
+ try {
+ if(sc.hasInitialResponse()) {
+ byte[] response = sc.evaluateChallenge(new byte[0]);
+ authenticationText = StringUtils.encodeBase64(response, false);
+ }
+ } catch (SaslException e) {
+ throw new XMPPException("SASL authentication failed", e);
+ }
+
+ // Send the authentication to the server
+ getSASLAuthentication().send(new AuthMechanism(getName(), authenticationText));
+ }
+
+
+ /**
+ * The server is challenging the SASL mechanism for the stanza he just sent. Send a
+ * response to the server's challenge.
+ *
+ * @param challenge a base64 encoded string representing the challenge.
+ * @throws IOException if an exception sending the response occurs.
+ */
+ public void challengeReceived(String challenge) throws IOException {
+ byte response[];
+ if(challenge != null) {
+ response = sc.evaluateChallenge(StringUtils.decodeBase64(challenge));
+ } else {
+ response = sc.evaluateChallenge(new byte[0]);
+ }
+
+ Packet responseStanza;
+ if (response == null) {
+ responseStanza = new Response();
+ }
+ else {
+ responseStanza = new Response(StringUtils.encodeBase64(response, false));
+ }
+
+ // Send the authentication to the server
+ getSASLAuthentication().send(responseStanza);
+ }
+
+ /**
+ * Returns the common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or GSSAPI.
+ *
+ * @return the common name of the SASL mechanism.
+ */
+ protected abstract String getName();
+
+
+ protected SASLAuthentication getSASLAuthentication() {
+ return saslAuthentication;
+ }
+
+ /**
+ *
+ */
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof NameCallback) {
+ NameCallback ncb = (NameCallback)callbacks[i];
+ ncb.setName(authenticationId);
+ } else if(callbacks[i] instanceof PasswordCallback) {
+ PasswordCallback pcb = (PasswordCallback)callbacks[i];
+ pcb.setPassword(password.toCharArray());
+ } else if(callbacks[i] instanceof RealmCallback) {
+ RealmCallback rcb = (RealmCallback)callbacks[i];
+ //Retrieve the REALM from the challenge response that the server returned when the client initiated the authentication
+ //exchange. If this value is not null or empty, *this value* has to be sent back to the server in the client's response
+ //to the server's challenge
+ String text = rcb.getDefaultText();
+ //The SASL client (sc) created in smack uses rcb.getText when creating the negotiatedRealm to send it back to the server
+ //Make sure that this value matches the server's realm
+ rcb.setText(text);
+ } else if(callbacks[i] instanceof RealmChoiceCallback){
+ //unused
+ //RealmChoiceCallback rccb = (RealmChoiceCallback)callbacks[i];
+ } else {
+ throw new UnsupportedCallbackException(callbacks[i]);
+ }
+ }
+ }
+
+ /**
+ * Initiating SASL authentication by select a mechanism.
+ */
+ public class AuthMechanism extends Packet {
+ final private String name;
+ final private String authenticationText;
+
+ public AuthMechanism(String name, String authenticationText) {
+ if (name == null) {
+ throw new NullPointerException("SASL mechanism name shouldn't be null.");
+ }
+ this.name = name;
+ this.authenticationText = authenticationText;
+ }
+
+ public String toXML() {
+ StringBuilder stanza = new StringBuilder();
+ stanza.append("<auth mechanism=\"").append(name);
+ stanza.append("\" xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
+ if (authenticationText != null &&
+ authenticationText.trim().length() > 0) {
+ stanza.append(authenticationText);
+ }
+ stanza.append("</auth>");
+ return stanza.toString();
+ }
+ }
+
+ /**
+ * A SASL challenge stanza.
+ */
+ public static class Challenge extends Packet {
+ final private String data;
+
+ public Challenge(String data) {
+ this.data = data;
+ }
+
+ public String toXML() {
+ StringBuilder stanza = new StringBuilder();
+ stanza.append("<challenge xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
+ if (data != null &&
+ data.trim().length() > 0) {
+ stanza.append(data);
+ }
+ stanza.append("</challenge>");
+ return stanza.toString();
+ }
+ }
+
+ /**
+ * A SASL response stanza.
+ */
+ public class Response extends Packet {
+ final private String authenticationText;
+
+ public Response() {
+ authenticationText = null;
+ }
+
+ public Response(String authenticationText) {
+ if (authenticationText == null || authenticationText.trim().length() == 0) {
+ this.authenticationText = null;
+ }
+ else {
+ this.authenticationText = authenticationText;
+ }
+ }
+
+ public String toXML() {
+ StringBuilder stanza = new StringBuilder();
+ stanza.append("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
+ if (authenticationText != null) {
+ stanza.append(authenticationText);
+ }
+ stanza.append("</response>");
+ return stanza.toString();
+ }
+ }
+
+ /**
+ * A SASL success stanza.
+ */
+ public static class Success extends Packet {
+ final private String data;
+
+ public Success(String data) {
+ this.data = data;
+ }
+
+ public String toXML() {
+ StringBuilder stanza = new StringBuilder();
+ stanza.append("<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
+ if (data != null &&
+ data.trim().length() > 0) {
+ stanza.append(data);
+ }
+ stanza.append("</success>");
+ return stanza.toString();
+ }
+ }
+
+ /**
+ * A SASL failure stanza.
+ */
+ public static class Failure extends Packet {
+ final private String condition;
+
+ public Failure(String condition) {
+ this.condition = condition;
+ }
+
+ /**
+ * Get the SASL related error condition.
+ *
+ * @return the SASL related error condition.
+ */
+ public String getCondition() {
+ return condition;
+ }
+
+ public String toXML() {
+ StringBuilder stanza = new StringBuilder();
+ stanza.append("<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
+ if (condition != null &&
+ condition.trim().length() > 0) {
+ stanza.append("<").append(condition).append("/>");
+ }
+ stanza.append("</failure>");
+ return stanza.toString();
+ }
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLPlainMechanism.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLPlainMechanism.java
index cd973eb87..c341d6761 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLPlainMechanism.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/sasl/SASLPlainMechanism.java
@@ -1,34 +1,34 @@
-/**
- *
- * All rights reserved. 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 org.jivesoftware.smack.sasl;
-
-import org.jivesoftware.smack.SASLAuthentication;
-
-/**
- * Implementation of the SASL PLAIN mechanism
- *
- * @author Jay Kline
- */
-public class SASLPlainMechanism extends SASLMechanism {
-
- public SASLPlainMechanism(SASLAuthentication saslAuthentication) {
- super(saslAuthentication);
- }
-
- protected String getName() {
- return "PLAIN";
- }
-}
+/**
+ *
+ * All rights reserved. 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 org.jivesoftware.smack.sasl;
+
+import org.jivesoftware.smack.SASLAuthentication;
+
+/**
+ * Implementation of the SASL PLAIN mechanism
+ *
+ * @author Jay Kline
+ */
+public class SASLPlainMechanism extends SASLMechanism {
+
+ public SASLPlainMechanism(SASLAuthentication saslAuthentication) {
+ super(saslAuthentication);
+ }
+
+ protected String getName() {
+ return "PLAIN";
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/util/Base64.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/util/Base64.java
index ba6eb371f..0923f037f 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/util/Base64.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/util/Base64.java
@@ -4,1686 +4,1686 @@
* $Date$
*
*/
-package org.jivesoftware.smack.util;
-
-/**
+package org.jivesoftware.smack.util;
+
+/**
* <p>Encodes and decodes to and from Base64 notation.</p>
- * This code was obtained from <a href="http://iharder.net/base64">http://iharder.net/base64</a></p>
- *
- *
- * @author Robert Harder
- * @author rob@iharder.net
- * @version 2.2.1
- */
-public class Base64
-{
-
-/* ******** P U B L I C F I E L D S ******** */
-
-
- /** No options specified. Value is zero. */
- public final static int NO_OPTIONS = 0;
-
- /** Specify encoding. */
- public final static int ENCODE = 1;
-
-
- /** Specify decoding. */
- public final static int DECODE = 0;
-
-
- /** Specify that data should be gzip-compressed. */
- public final static int GZIP = 2;
-
-
- /** Don't break lines when encoding (violates strict Base64 specification) */
- public final static int DONT_BREAK_LINES = 8;
-
- /**
- * Encode using Base64-like encoding that is URL- and Filename-safe as described
- * in Section 4 of RFC3548:
- * <a href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>.
- * It is important to note that data encoded this way is <em>not</em> officially valid Base64,
- * or at the very least should not be called Base64 without also specifying that is
- * was encoded using the URL- and Filename-safe dialect.
- */
- public final static int URL_SAFE = 16;
-
-
- /**
- * Encode using the special "ordered" dialect of Base64 described here:
- * <a href="http://www.faqs.org/qa/rfcc-1940.html">http://www.faqs.org/qa/rfcc-1940.html</a>.
- */
- public final static int ORDERED = 32;
-
-
-/* ******** P R I V A T E F I E L D S ******** */
-
-
- /** Maximum line length (76) of Base64 output. */
- private final static int MAX_LINE_LENGTH = 76;
-
-
- /** The equals sign (=) as a byte. */
- private final static byte EQUALS_SIGN = (byte)'=';
-
-
- /** The new line character (\n) as a byte. */
- private final static byte NEW_LINE = (byte)'\n';
-
-
- /** Preferred encoding. */
- private final static String PREFERRED_ENCODING = "UTF-8";
-
-
- // I think I end up not using the BAD_ENCODING indicator.
- //private final static byte BAD_ENCODING = -9; // Indicates error in encoding
- private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding
- private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding
-
-
-/* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */
-
- /** The 64 valid Base64 values. */
- //private final static byte[] ALPHABET;
- /* Host platform me be something funny like EBCDIC, so we hardcode these values. */
- private final static byte[] _STANDARD_ALPHABET =
- {
- (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
- (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
- (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
- (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
- (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
- (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
- (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
- (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/'
- };
-
-
- /**
- * Translates a Base64 value to either its 6-bit reconstruction value
- * or a negative number indicating some other meaning.
- **/
- private final static byte[] _STANDARD_DECODABET =
- {
- -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
- -5,-5, // Whitespace: Tab and Linefeed
- -9,-9, // Decimal 11 - 12
- -5, // Whitespace: Carriage Return
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26
- -9,-9,-9,-9,-9, // Decimal 27 - 31
- -5, // Whitespace: Space
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42
- 62, // Plus sign at decimal 43
- -9,-9,-9, // Decimal 44 - 46
- 63, // Slash at decimal 47
- 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine
- -9,-9,-9, // Decimal 58 - 60
- -1, // Equals sign at decimal 61
- -9,-9,-9, // Decimal 62 - 64
- 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N'
- 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z'
- -9,-9,-9,-9,-9,-9, // Decimal 91 - 96
- 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm'
- 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z'
- -9,-9,-9,-9 // Decimal 123 - 126
- /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
- };
-
-
-/* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */
-
- /**
- * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548:
- * <a href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>.
- * Notice that the last two bytes become "hyphen" and "underscore" instead of "plus" and "slash."
- */
- private final static byte[] _URL_SAFE_ALPHABET =
- {
- (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
- (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
- (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
- (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
- (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
- (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
- (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
- (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'-', (byte)'_'
- };
-
- /**
- * Used in decoding URL- and Filename-safe dialects of Base64.
- */
- private final static byte[] _URL_SAFE_DECODABET =
- {
- -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
- -5,-5, // Whitespace: Tab and Linefeed
- -9,-9, // Decimal 11 - 12
- -5, // Whitespace: Carriage Return
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26
- -9,-9,-9,-9,-9, // Decimal 27 - 31
- -5, // Whitespace: Space
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42
- -9, // Plus sign at decimal 43
- -9, // Decimal 44
- 62, // Minus sign at decimal 45
- -9, // Decimal 46
- -9, // Slash at decimal 47
- 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine
- -9,-9,-9, // Decimal 58 - 60
- -1, // Equals sign at decimal 61
- -9,-9,-9, // Decimal 62 - 64
- 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N'
- 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z'
- -9,-9,-9,-9, // Decimal 91 - 94
- 63, // Underscore at decimal 95
- -9, // Decimal 96
- 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm'
- 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z'
- -9,-9,-9,-9 // Decimal 123 - 126
- /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
- };
-
-
-
-/* ******** O R D E R E D B A S E 6 4 A L P H A B E T ******** */
-
- /**
- * I don't get the point of this technique, but it is described here:
- * <a href="http://www.faqs.org/qa/rfcc-1940.html">http://www.faqs.org/qa/rfcc-1940.html</a>.
- */
- private final static byte[] _ORDERED_ALPHABET =
- {
- (byte)'-',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4',
- (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9',
- (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
- (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
- (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
- (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
- (byte)'_',
- (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
- (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
- (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z'
- };
-
- /**
- * Used in decoding the "ordered" dialect of Base64.
- */
- private final static byte[] _ORDERED_DECODABET =
- {
- -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
- -5,-5, // Whitespace: Tab and Linefeed
- -9,-9, // Decimal 11 - 12
- -5, // Whitespace: Carriage Return
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26
- -9,-9,-9,-9,-9, // Decimal 27 - 31
- -5, // Whitespace: Space
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42
- -9, // Plus sign at decimal 43
- -9, // Decimal 44
- 0, // Minus sign at decimal 45
- -9, // Decimal 46
- -9, // Slash at decimal 47
- 1,2,3,4,5,6,7,8,9,10, // Numbers zero through nine
- -9,-9,-9, // Decimal 58 - 60
- -1, // Equals sign at decimal 61
- -9,-9,-9, // Decimal 62 - 64
- 11,12,13,14,15,16,17,18,19,20,21,22,23, // Letters 'A' through 'M'
- 24,25,26,27,28,29,30,31,32,33,34,35,36, // Letters 'N' through 'Z'
- -9,-9,-9,-9, // Decimal 91 - 94
- 37, // Underscore at decimal 95
- -9, // Decimal 96
- 38,39,40,41,42,43,44,45,46,47,48,49,50, // Letters 'a' through 'm'
- 51,52,53,54,55,56,57,58,59,60,61,62,63, // Letters 'n' through 'z'
- -9,-9,-9,-9 // Decimal 123 - 126
- /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
- };
-
-
-/* ******** D E T E R M I N E W H I C H A L H A B E T ******** */
-
-
- /**
- * Returns one of the _SOMETHING_ALPHABET byte arrays depending on
- * the options specified.
- * It's possible, though silly, to specify ORDERED and URLSAFE
- * in which case one of them will be picked, though there is
- * no guarantee as to which one will be picked.
- */
- private final static byte[] getAlphabet( int options )
- {
- if( (options & URL_SAFE) == URL_SAFE ) return _URL_SAFE_ALPHABET;
- else if( (options & ORDERED) == ORDERED ) return _ORDERED_ALPHABET;
- else return _STANDARD_ALPHABET;
-
- } // end getAlphabet
-
-
- /**
- * Returns one of the _SOMETHING_DECODABET byte arrays depending on
- * the options specified.
- * It's possible, though silly, to specify ORDERED and URL_SAFE
- * in which case one of them will be picked, though there is
- * no guarantee as to which one will be picked.
- */
- private final static byte[] getDecodabet( int options )
- {
- if( (options & URL_SAFE) == URL_SAFE ) return _URL_SAFE_DECODABET;
- else if( (options & ORDERED) == ORDERED ) return _ORDERED_DECODABET;
- else return _STANDARD_DECODABET;
-
- } // end getAlphabet
-
-
-
- /** Defeats instantiation. */
- private Base64(){}
-
- /**
- * Prints command line usage.
- *
- * @param msg A message to include with usage info.
- */
- private final static void usage( String msg )
- {
- System.err.println( msg );
- System.err.println( "Usage: java Base64 -e|-d inputfile outputfile" );
- } // end usage
-
-
-/* ******** E N C O D I N G M E T H O D S ******** */
-
-
- /**
- * Encodes up to the first three bytes of array <var>threeBytes</var>
- * and returns a four-byte array in Base64 notation.
- * The actual number of significant bytes in your array is
- * given by <var>numSigBytes</var>.
- * The array <var>threeBytes</var> needs only be as big as
- * <var>numSigBytes</var>.
- * Code can reuse a byte array by passing a four-byte array as <var>b4</var>.
- *
- * @param b4 A reusable byte array to reduce array instantiation
- * @param threeBytes the array to convert
- * @param numSigBytes the number of significant bytes in your array
- * @return four byte array in Base64 notation.
- * @since 1.5.1
- */
- private static byte[] encode3to4( byte[] b4, byte[] threeBytes, int numSigBytes, int options )
- {
- encode3to4( threeBytes, 0, numSigBytes, b4, 0, options );
- return b4;
- } // end encode3to4
-
-
- /**
- * <p>Encodes up to three bytes of the array <var>source</var>
- * and writes the resulting four Base64 bytes to <var>destination</var>.
- * The source and destination arrays can be manipulated
- * anywhere along their length by specifying
- * <var>srcOffset</var> and <var>destOffset</var>.
- * This method does not check to make sure your arrays
- * are large enough to accomodate <var>srcOffset</var> + 3 for
- * the <var>source</var> array or <var>destOffset</var> + 4 for
- * the <var>destination</var> array.
- * The actual number of significant bytes in your array is
- * given by <var>numSigBytes</var>.</p>
- * <p>This is the lowest level of the encoding methods with
- * all possible parameters.</p>
- *
- * @param source the array to convert
- * @param srcOffset the index where conversion begins
- * @param numSigBytes the number of significant bytes in your array
- * @param destination the array to hold the conversion
- * @param destOffset the index where output will be put
- * @return the <var>destination</var> array
- * @since 1.3
- */
- private static byte[] encode3to4(
- byte[] source, int srcOffset, int numSigBytes,
- byte[] destination, int destOffset, int options )
- {
- byte[] ALPHABET = getAlphabet( options );
-
- // 1 2 3
- // 01234567890123456789012345678901 Bit position
- // --------000000001111111122222222 Array position from threeBytes
- // --------| || || || | Six bit groups to index ALPHABET
- // >>18 >>12 >> 6 >> 0 Right shift necessary
- // 0x3f 0x3f 0x3f Additional AND
-
- // Create buffer with zero-padding if there are only one or two
- // significant bytes passed in the array.
- // We have to shift left 24 in order to flush out the 1's that appear
- // when Java treats a value as negative that is cast from a byte to an int.
- int inBuff = ( numSigBytes > 0 ? ((source[ srcOffset ] << 24) >>> 8) : 0 )
- | ( numSigBytes > 1 ? ((source[ srcOffset + 1 ] << 24) >>> 16) : 0 )
- | ( numSigBytes > 2 ? ((source[ srcOffset + 2 ] << 24) >>> 24) : 0 );
-
- switch( numSigBytes )
- {
- case 3:
- destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ];
- destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
- destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ];
- destination[ destOffset + 3 ] = ALPHABET[ (inBuff ) & 0x3f ];
- return destination;
-
- case 2:
- destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ];
- destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
- destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ];
- destination[ destOffset + 3 ] = EQUALS_SIGN;
- return destination;
-
- case 1:
- destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ];
- destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
- destination[ destOffset + 2 ] = EQUALS_SIGN;
- destination[ destOffset + 3 ] = EQUALS_SIGN;
- return destination;
-
- default:
- return destination;
- } // end switch
- } // end encode3to4
-
-
-
- /**
- * Serializes an object and returns the Base64-encoded
- * version of that serialized object. If the object
- * cannot be serialized or there is another error,
- * the method will return <tt>null</tt>.
- * The object is not GZip-compressed before being encoded.
- *
- * @param serializableObject The object to encode
- * @return The Base64-encoded object
- * @since 1.4
- */
- public static String encodeObject( java.io.Serializable serializableObject )
- {
- return encodeObject( serializableObject, NO_OPTIONS );
- } // end encodeObject
-
-
-
- /**
- * Serializes an object and returns the Base64-encoded
- * version of that serialized object. If the object
- * cannot be serialized or there is another error,
- * the method will return <tt>null</tt>.
- * <p>
- * Valid options:<pre>
- * GZIP: gzip-compresses object before encoding it.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * <i>Note: Technically, this makes your encoding non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>encodeObject( myObj, Base64.GZIP )</code> or
- * <p>
- * Example: <code>encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
- *
- * @param serializableObject The object to encode
- * @param options Specified options
- * @return The Base64-encoded object
- * @see Base64#GZIP
- * @see Base64#DONT_BREAK_LINES
- * @since 2.0
- */
- public static String encodeObject( java.io.Serializable serializableObject, int options )
- {
- // Streams
- java.io.ByteArrayOutputStream baos = null;
- java.io.OutputStream b64os = null;
- java.io.ObjectOutputStream oos = null;
- java.util.zip.GZIPOutputStream gzos = null;
-
- // Isolate options
- int gzip = (options & GZIP);
- int dontBreakLines = (options & DONT_BREAK_LINES);
-
- try
- {
- // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
- baos = new java.io.ByteArrayOutputStream();
- b64os = new Base64.OutputStream( baos, ENCODE | options );
-
- // GZip?
- if( gzip == GZIP )
- {
- gzos = new java.util.zip.GZIPOutputStream( b64os );
- oos = new java.io.ObjectOutputStream( gzos );
- } // end if: gzip
- else
- oos = new java.io.ObjectOutputStream( b64os );
-
- oos.writeObject( serializableObject );
- } // end try
- catch( java.io.IOException e )
- {
- e.printStackTrace();
- return null;
- } // end catch
- finally
- {
- try{ oos.close(); } catch( Exception e ){}
- try{ gzos.close(); } catch( Exception e ){}
- try{ b64os.close(); } catch( Exception e ){}
- try{ baos.close(); } catch( Exception e ){}
- } // end finally
-
- // Return value according to relevant encoding.
- try
- {
- return new String( baos.toByteArray(), PREFERRED_ENCODING );
- } // end try
- catch (java.io.UnsupportedEncodingException uue)
- {
- return new String( baos.toByteArray() );
- } // end catch
-
- } // end encode
-
-
-
- /**
- * Encodes a byte array into Base64 notation.
- * Does not GZip-compress data.
- *
- * @param source The data to convert
- * @since 1.4
- */
- public static String encodeBytes( byte[] source )
- {
- return encodeBytes( source, 0, source.length, NO_OPTIONS );
- } // end encodeBytes
-
-
-
- /**
- * Encodes a byte array into Base64 notation.
- * <p>
- * Valid options:<pre>
- * GZIP: gzip-compresses object before encoding it.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * <i>Note: Technically, this makes your encoding non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
- * <p>
- * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
- *
- *
- * @param source The data to convert
- * @param options Specified options
- * @see Base64#GZIP
- * @see Base64#DONT_BREAK_LINES
- * @since 2.0
- */
- public static String encodeBytes( byte[] source, int options )
- {
- return encodeBytes( source, 0, source.length, options );
- } // end encodeBytes
-
-
- /**
- * Encodes a byte array into Base64 notation.
- * Does not GZip-compress data.
- *
- * @param source The data to convert
- * @param off Offset in array where conversion should begin
- * @param len Length of data to convert
- * @since 1.4
- */
- public static String encodeBytes( byte[] source, int off, int len )
- {
- return encodeBytes( source, off, len, NO_OPTIONS );
- } // end encodeBytes
-
-
-
- /**
- * Encodes a byte array into Base64 notation.
- * <p>
- * Valid options:<pre>
- * GZIP: gzip-compresses object before encoding it.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * <i>Note: Technically, this makes your encoding non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
- * <p>
- * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
- *
- *
- * @param source The data to convert
- * @param off Offset in array where conversion should begin
- * @param len Length of data to convert
- * @param options Specified options; alphabet type is pulled from this (standard, url-safe, ordered)
- * @see Base64#GZIP
- * @see Base64#DONT_BREAK_LINES
- * @since 2.0
- */
- public static String encodeBytes( byte[] source, int off, int len, int options )
- {
- // Isolate options
- int dontBreakLines = ( options & DONT_BREAK_LINES );
- int gzip = ( options & GZIP );
-
- // Compress?
- if( gzip == GZIP )
- {
- java.io.ByteArrayOutputStream baos = null;
- java.util.zip.GZIPOutputStream gzos = null;
- Base64.OutputStream b64os = null;
-
-
- try
- {
- // GZip -> Base64 -> ByteArray
- baos = new java.io.ByteArrayOutputStream();
- b64os = new Base64.OutputStream( baos, ENCODE | options );
- gzos = new java.util.zip.GZIPOutputStream( b64os );
-
- gzos.write( source, off, len );
- gzos.close();
- } // end try
- catch( java.io.IOException e )
- {
- e.printStackTrace();
- return null;
- } // end catch
- finally
- {
- try{ gzos.close(); } catch( Exception e ){}
- try{ b64os.close(); } catch( Exception e ){}
- try{ baos.close(); } catch( Exception e ){}
- } // end finally
-
- // Return value according to relevant encoding.
- try
- {
- return new String( baos.toByteArray(), PREFERRED_ENCODING );
- } // end try
- catch (java.io.UnsupportedEncodingException uue)
- {
- return new String( baos.toByteArray() );
- } // end catch
- } // end if: compress
-
- // Else, don't compress. Better not to use streams at all then.
- else
- {
- // Convert option to boolean in way that code likes it.
- boolean breakLines = dontBreakLines == 0;
-
- int len43 = len * 4 / 3;
- byte[] outBuff = new byte[ ( len43 ) // Main 4:3
- + ( (len % 3) > 0 ? 4 : 0 ) // Account for padding
- + (breakLines ? ( len43 / MAX_LINE_LENGTH ) : 0) ]; // New lines
- int d = 0;
- int e = 0;
- int len2 = len - 2;
- int lineLength = 0;
- for( ; d < len2; d+=3, e+=4 )
- {
- encode3to4( source, d+off, 3, outBuff, e, options );
-
- lineLength += 4;
- if( breakLines && lineLength == MAX_LINE_LENGTH )
- {
- outBuff[e+4] = NEW_LINE;
- e++;
- lineLength = 0;
- } // end if: end of line
- } // en dfor: each piece of array
-
- if( d < len )
- {
- encode3to4( source, d+off, len - d, outBuff, e, options );
- e += 4;
- } // end if: some padding needed
-
-
- // Return value according to relevant encoding.
- try
- {
- return new String( outBuff, 0, e, PREFERRED_ENCODING );
- } // end try
- catch (java.io.UnsupportedEncodingException uue)
- {
- return new String( outBuff, 0, e );
- } // end catch
-
- } // end else: don't compress
-
- } // end encodeBytes
-
-
-
-
-
-/* ******** D E C O D I N G M E T H O D S ******** */
-
-
- /**
- * Decodes four bytes from array <var>source</var>
- * and writes the resulting bytes (up to three of them)
- * to <var>destination</var>.
- * The source and destination arrays can be manipulated
- * anywhere along their length by specifying
- * <var>srcOffset</var> and <var>destOffset</var>.
- * This method does not check to make sure your arrays
- * are large enough to accomodate <var>srcOffset</var> + 4 for
- * the <var>source</var> array or <var>destOffset</var> + 3 for
- * the <var>destination</var> array.
- * This method returns the actual number of bytes that
- * were converted from the Base64 encoding.
- * <p>This is the lowest level of the decoding methods with
- * all possible parameters.</p>
- *
- *
- * @param source the array to convert
- * @param srcOffset the index where conversion begins
- * @param destination the array to hold the conversion
- * @param destOffset the index where output will be put
- * @param options alphabet type is pulled from this (standard, url-safe, ordered)
- * @return the number of decoded bytes converted
- * @since 1.3
- */
- private static int decode4to3( byte[] source, int srcOffset, byte[] destination, int destOffset, int options )
- {
- byte[] DECODABET = getDecodabet( options );
-
- // Example: Dk==
- if( source[ srcOffset + 2] == EQUALS_SIGN )
- {
- // Two ways to do the same thing. Don't know which way I like best.
- //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
- // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 );
- int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 )
- | ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF ) << 12 );
-
- destination[ destOffset ] = (byte)( outBuff >>> 16 );
- return 1;
- }
-
- // Example: DkL=
- else if( source[ srcOffset + 3 ] == EQUALS_SIGN )
- {
- // Two ways to do the same thing. Don't know which way I like best.
- //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
- // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
- // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 );
- int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 )
- | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 )
- | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6 );
-
- destination[ destOffset ] = (byte)( outBuff >>> 16 );
- destination[ destOffset + 1 ] = (byte)( outBuff >>> 8 );
- return 2;
- }
-
- // Example: DkLE
- else
- {
- try{
- // Two ways to do the same thing. Don't know which way I like best.
- //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
- // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
- // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 )
- // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 );
- int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 )
- | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 )
- | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6)
- | ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF ) );
-
-
- destination[ destOffset ] = (byte)( outBuff >> 16 );
- destination[ destOffset + 1 ] = (byte)( outBuff >> 8 );
- destination[ destOffset + 2 ] = (byte)( outBuff );
-
- return 3;
- }catch( Exception e){
- System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[ source[ srcOffset ] ] ) );
- System.out.println(""+source[srcOffset+1]+ ": " + ( DECODABET[ source[ srcOffset + 1 ] ] ) );
- System.out.println(""+source[srcOffset+2]+ ": " + ( DECODABET[ source[ srcOffset + 2 ] ] ) );
- System.out.println(""+source[srcOffset+3]+ ": " + ( DECODABET[ source[ srcOffset + 3 ] ] ) );
- return -1;
- } // end catch
- }
- } // end decodeToBytes
-
-
-
-
- /**
- * Very low-level access to decoding ASCII characters in
- * the form of a byte array. Does not support automatically
- * gunzipping or any other "fancy" features.
- *
- * @param source The Base64 encoded data
- * @param off The offset of where to begin decoding
- * @param len The length of characters to decode
- * @return decoded data
- * @since 1.3
- */
- public static byte[] decode( byte[] source, int off, int len, int options )
- {
- byte[] DECODABET = getDecodabet( options );
-
- int len34 = len * 3 / 4;
- byte[] outBuff = new byte[ len34 ]; // Upper limit on size of output
- int outBuffPosn = 0;
-
- byte[] b4 = new byte[4];
- int b4Posn = 0;
- int i = 0;
- byte sbiCrop = 0;
- byte sbiDecode = 0;
- for( i = off; i < off+len; i++ )
- {
- sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits
- sbiDecode = DECODABET[ sbiCrop ];
-
- if( sbiDecode >= WHITE_SPACE_ENC ) // White space, Equals sign or better
- {
- if( sbiDecode >= EQUALS_SIGN_ENC )
- {
- b4[ b4Posn++ ] = sbiCrop;
- if( b4Posn > 3 )
- {
- outBuffPosn += decode4to3( b4, 0, outBuff, outBuffPosn, options );
- b4Posn = 0;
-
- // If that was the equals sign, break out of 'for' loop
- if( sbiCrop == EQUALS_SIGN )
- break;
- } // end if: quartet built
-
- } // end if: equals sign or better
-
- } // end if: white space, equals sign or better
- else
- {
- System.err.println( "Bad Base64 input character at " + i + ": " + source[i] + "(decimal)" );
- return null;
- } // end else:
- } // each input character
-
- byte[] out = new byte[ outBuffPosn ];
- System.arraycopy( outBuff, 0, out, 0, outBuffPosn );
- return out;
- } // end decode
-
-
-
-
- /**
- * Decodes data from Base64 notation, automatically
- * detecting gzip-compressed data and decompressing it.
- *
- * @param s the string to decode
- * @return the decoded data
- * @since 1.4
- */
- public static byte[] decode( String s )
- {
- return decode( s, NO_OPTIONS );
- }
-
-
- /**
- * Decodes data from Base64 notation, automatically
- * detecting gzip-compressed data and decompressing it.
- *
- * @param s the string to decode
- * @param options encode options such as URL_SAFE
- * @return the decoded data
- * @since 1.4
- */
- public static byte[] decode( String s, int options )
- {
- byte[] bytes;
- try
- {
- bytes = s.getBytes( PREFERRED_ENCODING );
- } // end try
- catch( java.io.UnsupportedEncodingException uee )
- {
- bytes = s.getBytes();
- } // end catch
- //</change>
-
- // Decode
- bytes = decode( bytes, 0, bytes.length, options );
-
-
- // Check to see if it's gzip-compressed
- // GZIP Magic Two-Byte Number: 0x8b1f (35615)
- if( bytes != null && bytes.length >= 4 )
- {
-
- int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
- if( java.util.zip.GZIPInputStream.GZIP_MAGIC == head )
- {
- java.io.ByteArrayInputStream bais = null;
- java.util.zip.GZIPInputStream gzis = null;
- java.io.ByteArrayOutputStream baos = null;
- byte[] buffer = new byte[2048];
- int length = 0;
-
- try
- {
- baos = new java.io.ByteArrayOutputStream();
- bais = new java.io.ByteArrayInputStream( bytes );
- gzis = new java.util.zip.GZIPInputStream( bais );
-
- while( ( length = gzis.read( buffer ) ) >= 0 )
- {
- baos.write(buffer,0,length);
- } // end while: reading input
-
- // No error? Get new bytes.
- bytes = baos.toByteArray();
-
- } // end try
- catch( java.io.IOException e )
- {
- // Just return originally-decoded bytes
- } // end catch
- finally
- {
- try{ baos.close(); } catch( Exception e ){}
- try{ gzis.close(); } catch( Exception e ){}
- try{ bais.close(); } catch( Exception e ){}
- } // end finally
-
- } // end if: gzipped
- } // end if: bytes.length >= 2
-
- return bytes;
- } // end decode
-
-
-
-
- /**
- * Attempts to decode Base64 data and deserialize a Java
- * Object within. Returns <tt>null</tt> if there was an error.
- *
- * @param encodedObject The Base64 data to decode
- * @return The decoded and deserialized object
- * @since 1.5
- */
- public static Object decodeToObject( String encodedObject )
- {
- // Decode and gunzip if necessary
- byte[] objBytes = decode( encodedObject );
-
- java.io.ByteArrayInputStream bais = null;
- java.io.ObjectInputStream ois = null;
- Object obj = null;
-
- try
- {
- bais = new java.io.ByteArrayInputStream( objBytes );
- ois = new java.io.ObjectInputStream( bais );
-
- obj = ois.readObject();
- } // end try
- catch( java.io.IOException e )
- {
- e.printStackTrace();
- obj = null;
- } // end catch
- catch( java.lang.ClassNotFoundException e )
- {
- e.printStackTrace();
- obj = null;
- } // end catch
- finally
- {
- try{ bais.close(); } catch( Exception e ){}
- try{ ois.close(); } catch( Exception e ){}
- } // end finally
-
- return obj;
- } // end decodeObject
-
-
-
- /**
- * Convenience method for encoding data to a file.
- *
- * @param dataToEncode byte array of data to encode in base64 form
- * @param filename Filename for saving encoded data
- * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
- *
- * @since 2.1
- */
- public static boolean encodeToFile( byte[] dataToEncode, String filename )
- {
- boolean success = false;
- Base64.OutputStream bos = null;
- try
- {
- bos = new Base64.OutputStream(
- new java.io.FileOutputStream( filename ), Base64.ENCODE );
- bos.write( dataToEncode );
- success = true;
- } // end try
- catch( java.io.IOException e )
- {
-
- success = false;
- } // end catch: IOException
- finally
- {
- try{ bos.close(); } catch( Exception e ){}
- } // end finally
-
- return success;
- } // end encodeToFile
-
-
- /**
- * Convenience method for decoding data to a file.
- *
- * @param dataToDecode Base64-encoded data as a string
- * @param filename Filename for saving decoded data
- * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
- *
- * @since 2.1
- */
- public static boolean decodeToFile( String dataToDecode, String filename )
- {
- boolean success = false;
- Base64.OutputStream bos = null;
- try
- {
- bos = new Base64.OutputStream(
- new java.io.FileOutputStream( filename ), Base64.DECODE );
- bos.write( dataToDecode.getBytes( PREFERRED_ENCODING ) );
- success = true;
- } // end try
- catch( java.io.IOException e )
- {
- success = false;
- } // end catch: IOException
- finally
- {
- try{ bos.close(); } catch( Exception e ){}
- } // end finally
-
- return success;
- } // end decodeToFile
-
-
-
-
- /**
- * Convenience method for reading a base64-encoded
- * file and decoding it.
- *
- * @param filename Filename for reading encoded data
- * @return decoded byte array or null if unsuccessful
- *
- * @since 2.1
- */
- public static byte[] decodeFromFile( String filename )
- {
- byte[] decodedData = null;
- Base64.InputStream bis = null;
- try
- {
- // Set up some useful variables
- java.io.File file = new java.io.File( filename );
- byte[] buffer = null;
- int length = 0;
- int numBytes = 0;
-
- // Check for size of file
- if( file.length() > Integer.MAX_VALUE )
- {
- System.err.println( "File is too big for this convenience method (" + file.length() + " bytes)." );
- return null;
- } // end if: file too big for int index
- buffer = new byte[ (int)file.length() ];
-
- // Open a stream
- bis = new Base64.InputStream(
- new java.io.BufferedInputStream(
- new java.io.FileInputStream( file ) ), Base64.DECODE );
-
- // Read until done
- while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 )
- length += numBytes;
-
- // Save in a variable to return
- decodedData = new byte[ length ];
- System.arraycopy( buffer, 0, decodedData, 0, length );
-
- } // end try
- catch( java.io.IOException e )
- {
- System.err.println( "Error decoding from file " + filename );
- } // end catch: IOException
- finally
- {
- try{ bis.close(); } catch( Exception e) {}
- } // end finally
-
- return decodedData;
- } // end decodeFromFile
-
-
-
- /**
- * Convenience method for reading a binary file
- * and base64-encoding it.
- *
- * @param filename Filename for reading binary data
- * @return base64-encoded string or null if unsuccessful
- *
- * @since 2.1
- */
- public static String encodeFromFile( String filename )
- {
- String encodedData = null;
- Base64.InputStream bis = null;
- try
- {
- // Set up some useful variables
- java.io.File file = new java.io.File( filename );
- byte[] buffer = new byte[ Math.max((int)(file.length() * 1.4),40) ]; // Need max() for math on small files (v2.2.1)
- int length = 0;
- int numBytes = 0;
-
- // Open a stream
- bis = new Base64.InputStream(
- new java.io.BufferedInputStream(
- new java.io.FileInputStream( file ) ), Base64.ENCODE );
-
- // Read until done
- while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 )
- length += numBytes;
-
- // Save in a variable to return
- encodedData = new String( buffer, 0, length, Base64.PREFERRED_ENCODING );
-
- } // end try
- catch( java.io.IOException e )
- {
- System.err.println( "Error encoding from file " + filename );
- } // end catch: IOException
- finally
- {
- try{ bis.close(); } catch( Exception e) {}
- } // end finally
-
- return encodedData;
- } // end encodeFromFile
-
- /**
- * Reads <tt>infile</tt> and encodes it to <tt>outfile</tt>.
- *
- * @param infile Input file
- * @param outfile Output file
- * @since 2.2
- */
- public static void encodeFileToFile( String infile, String outfile )
- {
- String encoded = Base64.encodeFromFile( infile );
- java.io.OutputStream out = null;
- try{
- out = new java.io.BufferedOutputStream(
- new java.io.FileOutputStream( outfile ) );
- out.write( encoded.getBytes("US-ASCII") ); // Strict, 7-bit output.
- } // end try
- catch( java.io.IOException ex ) {
- ex.printStackTrace();
- } // end catch
- finally {
- try { out.close(); }
- catch( Exception ex ){}
- } // end finally
- } // end encodeFileToFile
-
-
- /**
- * Reads <tt>infile</tt> and decodes it to <tt>outfile</tt>.
- *
- * @param infile Input file
- * @param outfile Output file
- * @since 2.2
- */
- public static void decodeFileToFile( String infile, String outfile )
- {
- byte[] decoded = Base64.decodeFromFile( infile );
- java.io.OutputStream out = null;
- try{
- out = new java.io.BufferedOutputStream(
- new java.io.FileOutputStream( outfile ) );
- out.write( decoded );
- } // end try
- catch( java.io.IOException ex ) {
- ex.printStackTrace();
- } // end catch
- finally {
- try { out.close(); }
- catch( Exception ex ){}
- } // end finally
- } // end decodeFileToFile
-
-
- /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */
-
-
-
- /**
- * A {@link Base64.InputStream} will read data from another
- * <tt>java.io.InputStream</tt>, given in the constructor,
- * and encode/decode to/from Base64 notation on the fly.
- *
- * @see Base64
- * @since 1.3
- */
- public static class InputStream extends java.io.FilterInputStream
- {
- private boolean encode; // Encoding or decoding
- private int position; // Current position in the buffer
- private byte[] buffer; // Small buffer holding converted data
- private int bufferLength; // Length of buffer (3 or 4)
- private int numSigBytes; // Number of meaningful bytes in the buffer
- private int lineLength;
- private boolean breakLines; // Break lines at less than 80 characters
- private int options; // Record options used to create the stream.
- private byte[] alphabet; // Local copies to avoid extra method calls
- private byte[] decodabet; // Local copies to avoid extra method calls
-
-
- /**
- * Constructs a {@link Base64.InputStream} in DECODE mode.
- *
- * @param in the <tt>java.io.InputStream</tt> from which to read data.
- * @since 1.3
- */
- public InputStream( java.io.InputStream in )
- {
- this( in, DECODE );
- } // end constructor
-
-
- /**
- * Constructs a {@link Base64.InputStream} in
- * either ENCODE or DECODE mode.
- * <p>
- * Valid options:<pre>
- * ENCODE or DECODE: Encode or Decode as data is read.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * (only meaningful when encoding)
- * <i>Note: Technically, this makes your encoding non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>new Base64.InputStream( in, Base64.DECODE )</code>
- *
- *
- * @param in the <tt>java.io.InputStream</tt> from which to read data.
- * @param options Specified options
- * @see Base64#ENCODE
- * @see Base64#DECODE
- * @see Base64#DONT_BREAK_LINES
- * @since 2.0
- */
- public InputStream( java.io.InputStream in, int options )
- {
- super( in );
- this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
- this.encode = (options & ENCODE) == ENCODE;
- this.bufferLength = encode ? 4 : 3;
- this.buffer = new byte[ bufferLength ];
- this.position = -1;
- this.lineLength = 0;
- this.options = options; // Record for later, mostly to determine which alphabet to use
- this.alphabet = getAlphabet(options);
- this.decodabet = getDecodabet(options);
- } // end constructor
-
- /**
- * Reads enough of the input stream to convert
- * to/from Base64 and returns the next byte.
- *
- * @return next byte
- * @since 1.3
- */
- public int read() throws java.io.IOException
- {
- // Do we need to get data?
- if( position < 0 )
- {
- if( encode )
- {
- byte[] b3 = new byte[3];
- int numBinaryBytes = 0;
- for( int i = 0; i < 3; i++ )
- {
- try
- {
- int b = in.read();
-
- // If end of stream, b is -1.
- if( b >= 0 )
- {
- b3[i] = (byte)b;
- numBinaryBytes++;
- } // end if: not end of stream
-
- } // end try: read
- catch( java.io.IOException e )
- {
- // Only a problem if we got no data at all.
- if( i == 0 )
- throw e;
-
- } // end catch
- } // end for: each needed input byte
-
- if( numBinaryBytes > 0 )
- {
- encode3to4( b3, 0, numBinaryBytes, buffer, 0, options );
- position = 0;
- numSigBytes = 4;
- } // end if: got data
- else
- {
- return -1;
- } // end else
- } // end if: encoding
-
- // Else decoding
- else
- {
- byte[] b4 = new byte[4];
- int i = 0;
- for( i = 0; i < 4; i++ )
- {
- // Read four "meaningful" bytes:
- int b = 0;
- do{ b = in.read(); }
- while( b >= 0 && decodabet[ b & 0x7f ] <= WHITE_SPACE_ENC );
-
- if( b < 0 )
- break; // Reads a -1 if end of stream
-
- b4[i] = (byte)b;
- } // end for: each needed input byte
-
- if( i == 4 )
- {
- numSigBytes = decode4to3( b4, 0, buffer, 0, options );
- position = 0;
- } // end if: got four characters
- else if( i == 0 ){
- return -1;
- } // end else if: also padded correctly
- else
- {
- // Must have broken out from above.
- throw new java.io.IOException( "Improperly padded Base64 input." );
- } // end
-
- } // end else: decode
- } // end else: get data
-
- // Got data?
- if( position >= 0 )
- {
- // End of relevant data?
- if( /*!encode &&*/ position >= numSigBytes )
- return -1;
-
- if( encode && breakLines && lineLength >= MAX_LINE_LENGTH )
- {
- lineLength = 0;
- return '\n';
- } // end if
- else
- {
- lineLength++; // This isn't important when decoding
- // but throwing an extra "if" seems
- // just as wasteful.
-
- int b = buffer[ position++ ];
-
- if( position >= bufferLength )
- position = -1;
-
- return b & 0xFF; // This is how you "cast" a byte that's
- // intended to be unsigned.
- } // end else
- } // end if: position >= 0
-
- // Else error
- else
- {
- // When JDK1.4 is more accepted, use an assertion here.
- throw new java.io.IOException( "Error in Base64 code reading stream." );
- } // end else
- } // end read
-
-
- /**
- * Calls {@link #read()} repeatedly until the end of stream
- * is reached or <var>len</var> bytes are read.
- * Returns number of bytes read into array or -1 if
- * end of stream is encountered.
- *
- * @param dest array to hold values
- * @param off offset for array
- * @param len max number of bytes to read into array
- * @return bytes read into array or -1 if end of stream is encountered.
- * @since 1.3
- */
- public int read( byte[] dest, int off, int len ) throws java.io.IOException
- {
- int i;
- int b;
- for( i = 0; i < len; i++ )
- {
- b = read();
-
- //if( b < 0 && i == 0 )
- // return -1;
-
- if( b >= 0 )
- dest[off + i] = (byte)b;
- else if( i == 0 )
- return -1;
- else
- break; // Out of 'for' loop
- } // end for: each byte read
- return i;
- } // end read
-
- } // end inner class InputStream
-
-
-
-
-
-
- /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */
-
-
-
- /**
- * A {@link Base64.OutputStream} will write data to another
- * <tt>java.io.OutputStream</tt>, given in the constructor,
- * and encode/decode to/from Base64 notation on the fly.
- *
- * @see Base64
- * @since 1.3
- */
- public static class OutputStream extends java.io.FilterOutputStream
- {
- private boolean encode;
- private int position;
- private byte[] buffer;
- private int bufferLength;
- private int lineLength;
- private boolean breakLines;
- private byte[] b4; // Scratch used in a few places
- private boolean suspendEncoding;
- private int options; // Record for later
- private byte[] alphabet; // Local copies to avoid extra method calls
- private byte[] decodabet; // Local copies to avoid extra method calls
-
- /**
- * Constructs a {@link Base64.OutputStream} in ENCODE mode.
- *
- * @param out the <tt>java.io.OutputStream</tt> to which data will be written.
- * @since 1.3
- */
- public OutputStream( java.io.OutputStream out )
- {
- this( out, ENCODE );
- } // end constructor
-
-
- /**
- * Constructs a {@link Base64.OutputStream} in
- * either ENCODE or DECODE mode.
- * <p>
- * Valid options:<pre>
- * ENCODE or DECODE: Encode or Decode as data is read.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * (only meaningful when encoding)
- * <i>Note: Technically, this makes your encoding non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>new Base64.OutputStream( out, Base64.ENCODE )</code>
- *
- * @param out the <tt>java.io.OutputStream</tt> to which data will be written.
- * @param options Specified options.
- * @see Base64#ENCODE
- * @see Base64#DECODE
- * @see Base64#DONT_BREAK_LINES
- * @since 1.3
- */
- public OutputStream( java.io.OutputStream out, int options )
- {
- super( out );
- this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
- this.encode = (options & ENCODE) == ENCODE;
- this.bufferLength = encode ? 3 : 4;
- this.buffer = new byte[ bufferLength ];
- this.position = 0;
- this.lineLength = 0;
- this.suspendEncoding = false;
- this.b4 = new byte[4];
- this.options = options;
- this.alphabet = getAlphabet(options);
- this.decodabet = getDecodabet(options);
- } // end constructor
-
-
- /**
- * Writes the byte to the output stream after
- * converting to/from Base64 notation.
- * When encoding, bytes are buffered three
- * at a time before the output stream actually
- * gets a write() call.
- * When decoding, bytes are buffered four
- * at a time.
- *
- * @param theByte the byte to write
- * @since 1.3
- */
- public void write(int theByte) throws java.io.IOException
- {
- // Encoding suspended?
- if( suspendEncoding )
- {
- super.out.write( theByte );
- return;
- } // end if: supsended
-
- // Encode?
- if( encode )
- {
- buffer[ position++ ] = (byte)theByte;
- if( position >= bufferLength ) // Enough to encode.
- {
- out.write( encode3to4( b4, buffer, bufferLength, options ) );
-
- lineLength += 4;
- if( breakLines && lineLength >= MAX_LINE_LENGTH )
- {
- out.write( NEW_LINE );
- lineLength = 0;
- } // end if: end of line
-
- position = 0;
- } // end if: enough to output
- } // end if: encoding
-
- // Else, Decoding
- else
- {
- // Meaningful Base64 character?
- if( decodabet[ theByte & 0x7f ] > WHITE_SPACE_ENC )
- {
- buffer[ position++ ] = (byte)theByte;
- if( position >= bufferLength ) // Enough to output.
- {
- int len = Base64.decode4to3( buffer, 0, b4, 0, options );
- out.write( b4, 0, len );
- //out.write( Base64.decode4to3( buffer ) );
- position = 0;
- } // end if: enough to output
- } // end if: meaningful base64 character
- else if( decodabet[ theByte & 0x7f ] != WHITE_SPACE_ENC )
- {
- throw new java.io.IOException( "Invalid character in Base64 data." );
- } // end else: not white space either
- } // end else: decoding
- } // end write
-
-
-
- /**
- * Calls {@link #write(int)} repeatedly until <var>len</var>
- * bytes are written.
- *
- * @param theBytes array from which to read bytes
- * @param off offset for array
- * @param len max number of bytes to read into array
- * @since 1.3
- */
- public void write( byte[] theBytes, int off, int len ) throws java.io.IOException
- {
- // Encoding suspended?
- if( suspendEncoding )
- {
- super.out.write( theBytes, off, len );
- return;
- } // end if: supsended
-
- for( int i = 0; i < len; i++ )
- {
- write( theBytes[ off + i ] );
- } // end for: each byte written
-
- } // end write
-
-
-
- /**
- * Method added by PHIL. [Thanks, PHIL. -Rob]
- * This pads the buffer without closing the stream.
- */
- public void flushBase64() throws java.io.IOException
- {
- if( position > 0 )
- {
- if( encode )
- {
- out.write( encode3to4( b4, buffer, position, options ) );
- position = 0;
- } // end if: encoding
- else
- {
- throw new java.io.IOException( "Base64 input not properly padded." );
- } // end else: decoding
- } // end if: buffer partially full
-
- } // end flush
-
-
- /**
- * Flushes and closes (I think, in the superclass) the stream.
- *
- * @since 1.3
- */
- public void close() throws java.io.IOException
- {
- // 1. Ensure that pending characters are written
- flushBase64();
-
- // 2. Actually close the stream
- // Base class both flushes and closes.
- super.close();
-
- buffer = null;
- out = null;
- } // end close
-
-
-
- /**
- * Suspends encoding of the stream.
- * May be helpful if you need to embed a piece of
- * base640-encoded data in a stream.
- *
- * @since 1.5.1
- */
- public void suspendEncoding() throws java.io.IOException
- {
- flushBase64();
- this.suspendEncoding = true;
- } // end suspendEncoding
-
-
- /**
- * Resumes encoding of the stream.
- * May be helpful if you need to embed a piece of
- * base640-encoded data in a stream.
- *
- * @since 1.5.1
- */
- public void resumeEncoding()
- {
- this.suspendEncoding = false;
- } // end resumeEncoding
-
-
-
- } // end inner class OutputStream
-
-
-} // end class Base64
-
+ * This code was obtained from <a href="http://iharder.net/base64">http://iharder.net/base64</a></p>
+ *
+ *
+ * @author Robert Harder
+ * @author rob@iharder.net
+ * @version 2.2.1
+ */
+public class Base64
+{
+
+/* ******** P U B L I C F I E L D S ******** */
+
+
+ /** No options specified. Value is zero. */
+ public final static int NO_OPTIONS = 0;
+
+ /** Specify encoding. */
+ public final static int ENCODE = 1;
+
+
+ /** Specify decoding. */
+ public final static int DECODE = 0;
+
+
+ /** Specify that data should be gzip-compressed. */
+ public final static int GZIP = 2;
+
+
+ /** Don't break lines when encoding (violates strict Base64 specification) */
+ public final static int DONT_BREAK_LINES = 8;
+
+ /**
+ * Encode using Base64-like encoding that is URL- and Filename-safe as described
+ * in Section 4 of RFC3548:
+ * <a href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>.
+ * It is important to note that data encoded this way is <em>not</em> officially valid Base64,
+ * or at the very least should not be called Base64 without also specifying that is
+ * was encoded using the URL- and Filename-safe dialect.
+ */
+ public final static int URL_SAFE = 16;
+
+
+ /**
+ * Encode using the special "ordered" dialect of Base64 described here:
+ * <a href="http://www.faqs.org/qa/rfcc-1940.html">http://www.faqs.org/qa/rfcc-1940.html</a>.
+ */
+ public final static int ORDERED = 32;
+
+
+/* ******** P R I V A T E F I E L D S ******** */
+
+
+ /** Maximum line length (76) of Base64 output. */
+ private final static int MAX_LINE_LENGTH = 76;
+
+
+ /** The equals sign (=) as a byte. */
+ private final static byte EQUALS_SIGN = (byte)'=';
+
+
+ /** The new line character (\n) as a byte. */
+ private final static byte NEW_LINE = (byte)'\n';
+
+
+ /** Preferred encoding. */
+ private final static String PREFERRED_ENCODING = "UTF-8";
+
+
+ // I think I end up not using the BAD_ENCODING indicator.
+ //private final static byte BAD_ENCODING = -9; // Indicates error in encoding
+ private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding
+ private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding
+
+
+/* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */
+
+ /** The 64 valid Base64 values. */
+ //private final static byte[] ALPHABET;
+ /* Host platform me be something funny like EBCDIC, so we hardcode these values. */
+ private final static byte[] _STANDARD_ALPHABET =
+ {
+ (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
+ (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
+ (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
+ (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
+ (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
+ (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
+ (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
+ (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
+ (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/'
+ };
+
+
+ /**
+ * Translates a Base64 value to either its 6-bit reconstruction value
+ * or a negative number indicating some other meaning.
+ **/
+ private final static byte[] _STANDARD_DECODABET =
+ {
+ -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
+ -5,-5, // Whitespace: Tab and Linefeed
+ -9,-9, // Decimal 11 - 12
+ -5, // Whitespace: Carriage Return
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26
+ -9,-9,-9,-9,-9, // Decimal 27 - 31
+ -5, // Whitespace: Space
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42
+ 62, // Plus sign at decimal 43
+ -9,-9,-9, // Decimal 44 - 46
+ 63, // Slash at decimal 47
+ 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine
+ -9,-9,-9, // Decimal 58 - 60
+ -1, // Equals sign at decimal 61
+ -9,-9,-9, // Decimal 62 - 64
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N'
+ 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z'
+ -9,-9,-9,-9,-9,-9, // Decimal 91 - 96
+ 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm'
+ 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z'
+ -9,-9,-9,-9 // Decimal 123 - 126
+ /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
+ };
+
+
+/* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */
+
+ /**
+ * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548:
+ * <a href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>.
+ * Notice that the last two bytes become "hyphen" and "underscore" instead of "plus" and "slash."
+ */
+ private final static byte[] _URL_SAFE_ALPHABET =
+ {
+ (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
+ (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
+ (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
+ (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
+ (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
+ (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
+ (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
+ (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
+ (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'-', (byte)'_'
+ };
+
+ /**
+ * Used in decoding URL- and Filename-safe dialects of Base64.
+ */
+ private final static byte[] _URL_SAFE_DECODABET =
+ {
+ -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
+ -5,-5, // Whitespace: Tab and Linefeed
+ -9,-9, // Decimal 11 - 12
+ -5, // Whitespace: Carriage Return
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26
+ -9,-9,-9,-9,-9, // Decimal 27 - 31
+ -5, // Whitespace: Space
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42
+ -9, // Plus sign at decimal 43
+ -9, // Decimal 44
+ 62, // Minus sign at decimal 45
+ -9, // Decimal 46
+ -9, // Slash at decimal 47
+ 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine
+ -9,-9,-9, // Decimal 58 - 60
+ -1, // Equals sign at decimal 61
+ -9,-9,-9, // Decimal 62 - 64
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N'
+ 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z'
+ -9,-9,-9,-9, // Decimal 91 - 94
+ 63, // Underscore at decimal 95
+ -9, // Decimal 96
+ 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm'
+ 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z'
+ -9,-9,-9,-9 // Decimal 123 - 126
+ /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
+ };
+
+
+
+/* ******** O R D E R E D B A S E 6 4 A L P H A B E T ******** */
+
+ /**
+ * I don't get the point of this technique, but it is described here:
+ * <a href="http://www.faqs.org/qa/rfcc-1940.html">http://www.faqs.org/qa/rfcc-1940.html</a>.
+ */
+ private final static byte[] _ORDERED_ALPHABET =
+ {
+ (byte)'-',
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4',
+ (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9',
+ (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
+ (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
+ (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
+ (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
+ (byte)'_',
+ (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
+ (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
+ (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
+ (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z'
+ };
+
+ /**
+ * Used in decoding the "ordered" dialect of Base64.
+ */
+ private final static byte[] _ORDERED_DECODABET =
+ {
+ -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
+ -5,-5, // Whitespace: Tab and Linefeed
+ -9,-9, // Decimal 11 - 12
+ -5, // Whitespace: Carriage Return
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26
+ -9,-9,-9,-9,-9, // Decimal 27 - 31
+ -5, // Whitespace: Space
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42
+ -9, // Plus sign at decimal 43
+ -9, // Decimal 44
+ 0, // Minus sign at decimal 45
+ -9, // Decimal 46
+ -9, // Slash at decimal 47
+ 1,2,3,4,5,6,7,8,9,10, // Numbers zero through nine
+ -9,-9,-9, // Decimal 58 - 60
+ -1, // Equals sign at decimal 61
+ -9,-9,-9, // Decimal 62 - 64
+ 11,12,13,14,15,16,17,18,19,20,21,22,23, // Letters 'A' through 'M'
+ 24,25,26,27,28,29,30,31,32,33,34,35,36, // Letters 'N' through 'Z'
+ -9,-9,-9,-9, // Decimal 91 - 94
+ 37, // Underscore at decimal 95
+ -9, // Decimal 96
+ 38,39,40,41,42,43,44,45,46,47,48,49,50, // Letters 'a' through 'm'
+ 51,52,53,54,55,56,57,58,59,60,61,62,63, // Letters 'n' through 'z'
+ -9,-9,-9,-9 // Decimal 123 - 126
+ /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
+ };
+
+
+/* ******** D E T E R M I N E W H I C H A L H A B E T ******** */
+
+
+ /**
+ * Returns one of the _SOMETHING_ALPHABET byte arrays depending on
+ * the options specified.
+ * It's possible, though silly, to specify ORDERED and URLSAFE
+ * in which case one of them will be picked, though there is
+ * no guarantee as to which one will be picked.
+ */
+ private final static byte[] getAlphabet( int options )
+ {
+ if( (options & URL_SAFE) == URL_SAFE ) return _URL_SAFE_ALPHABET;
+ else if( (options & ORDERED) == ORDERED ) return _ORDERED_ALPHABET;
+ else return _STANDARD_ALPHABET;
+
+ } // end getAlphabet
+
+
+ /**
+ * Returns one of the _SOMETHING_DECODABET byte arrays depending on
+ * the options specified.
+ * It's possible, though silly, to specify ORDERED and URL_SAFE
+ * in which case one of them will be picked, though there is
+ * no guarantee as to which one will be picked.
+ */
+ private final static byte[] getDecodabet( int options )
+ {
+ if( (options & URL_SAFE) == URL_SAFE ) return _URL_SAFE_DECODABET;
+ else if( (options & ORDERED) == ORDERED ) return _ORDERED_DECODABET;
+ else return _STANDARD_DECODABET;
+
+ } // end getAlphabet
+
+
+
+ /** Defeats instantiation. */
+ private Base64(){}
+
+ /**
+ * Prints command line usage.
+ *
+ * @param msg A message to include with usage info.
+ */
+ private final static void usage( String msg )
+ {
+ System.err.println( msg );
+ System.err.println( "Usage: java Base64 -e|-d inputfile outputfile" );
+ } // end usage
+
+
+/* ******** E N C O D I N G M E T H O D S ******** */
+
+
+ /**
+ * Encodes up to the first three bytes of array <var>threeBytes</var>
+ * and returns a four-byte array in Base64 notation.
+ * The actual number of significant bytes in your array is
+ * given by <var>numSigBytes</var>.
+ * The array <var>threeBytes</var> needs only be as big as
+ * <var>numSigBytes</var>.
+ * Code can reuse a byte array by passing a four-byte array as <var>b4</var>.
+ *
+ * @param b4 A reusable byte array to reduce array instantiation
+ * @param threeBytes the array to convert
+ * @param numSigBytes the number of significant bytes in your array
+ * @return four byte array in Base64 notation.
+ * @since 1.5.1
+ */
+ private static byte[] encode3to4( byte[] b4, byte[] threeBytes, int numSigBytes, int options )
+ {
+ encode3to4( threeBytes, 0, numSigBytes, b4, 0, options );
+ return b4;
+ } // end encode3to4
+
+
+ /**
+ * <p>Encodes up to three bytes of the array <var>source</var>
+ * and writes the resulting four Base64 bytes to <var>destination</var>.
+ * The source and destination arrays can be manipulated
+ * anywhere along their length by specifying
+ * <var>srcOffset</var> and <var>destOffset</var>.
+ * This method does not check to make sure your arrays
+ * are large enough to accomodate <var>srcOffset</var> + 3 for
+ * the <var>source</var> array or <var>destOffset</var> + 4 for
+ * the <var>destination</var> array.
+ * The actual number of significant bytes in your array is
+ * given by <var>numSigBytes</var>.</p>
+ * <p>This is the lowest level of the encoding methods with
+ * all possible parameters.</p>
+ *
+ * @param source the array to convert
+ * @param srcOffset the index where conversion begins
+ * @param numSigBytes the number of significant bytes in your array
+ * @param destination the array to hold the conversion
+ * @param destOffset the index where output will be put
+ * @return the <var>destination</var> array
+ * @since 1.3
+ */
+ private static byte[] encode3to4(
+ byte[] source, int srcOffset, int numSigBytes,
+ byte[] destination, int destOffset, int options )
+ {
+ byte[] ALPHABET = getAlphabet( options );
+
+ // 1 2 3
+ // 01234567890123456789012345678901 Bit position
+ // --------000000001111111122222222 Array position from threeBytes
+ // --------| || || || | Six bit groups to index ALPHABET
+ // >>18 >>12 >> 6 >> 0 Right shift necessary
+ // 0x3f 0x3f 0x3f Additional AND
+
+ // Create buffer with zero-padding if there are only one or two
+ // significant bytes passed in the array.
+ // We have to shift left 24 in order to flush out the 1's that appear
+ // when Java treats a value as negative that is cast from a byte to an int.
+ int inBuff = ( numSigBytes > 0 ? ((source[ srcOffset ] << 24) >>> 8) : 0 )
+ | ( numSigBytes > 1 ? ((source[ srcOffset + 1 ] << 24) >>> 16) : 0 )
+ | ( numSigBytes > 2 ? ((source[ srcOffset + 2 ] << 24) >>> 24) : 0 );
+
+ switch( numSigBytes )
+ {
+ case 3:
+ destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ];
+ destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
+ destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ];
+ destination[ destOffset + 3 ] = ALPHABET[ (inBuff ) & 0x3f ];
+ return destination;
+
+ case 2:
+ destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ];
+ destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
+ destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ];
+ destination[ destOffset + 3 ] = EQUALS_SIGN;
+ return destination;
+
+ case 1:
+ destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ];
+ destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
+ destination[ destOffset + 2 ] = EQUALS_SIGN;
+ destination[ destOffset + 3 ] = EQUALS_SIGN;
+ return destination;
+
+ default:
+ return destination;
+ } // end switch
+ } // end encode3to4
+
+
+
+ /**
+ * Serializes an object and returns the Base64-encoded
+ * version of that serialized object. If the object
+ * cannot be serialized or there is another error,
+ * the method will return <tt>null</tt>.
+ * The object is not GZip-compressed before being encoded.
+ *
+ * @param serializableObject The object to encode
+ * @return The Base64-encoded object
+ * @since 1.4
+ */
+ public static String encodeObject( java.io.Serializable serializableObject )
+ {
+ return encodeObject( serializableObject, NO_OPTIONS );
+ } // end encodeObject
+
+
+
+ /**
+ * Serializes an object and returns the Base64-encoded
+ * version of that serialized object. If the object
+ * cannot be serialized or there is another error,
+ * the method will return <tt>null</tt>.
+ * <p>
+ * Valid options:<pre>
+ * GZIP: gzip-compresses object before encoding it.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>encodeObject( myObj, Base64.GZIP )</code> or
+ * <p>
+ * Example: <code>encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+ *
+ * @param serializableObject The object to encode
+ * @param options Specified options
+ * @return The Base64-encoded object
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeObject( java.io.Serializable serializableObject, int options )
+ {
+ // Streams
+ java.io.ByteArrayOutputStream baos = null;
+ java.io.OutputStream b64os = null;
+ java.io.ObjectOutputStream oos = null;
+ java.util.zip.GZIPOutputStream gzos = null;
+
+ // Isolate options
+ int gzip = (options & GZIP);
+ int dontBreakLines = (options & DONT_BREAK_LINES);
+
+ try
+ {
+ // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
+ baos = new java.io.ByteArrayOutputStream();
+ b64os = new Base64.OutputStream( baos, ENCODE | options );
+
+ // GZip?
+ if( gzip == GZIP )
+ {
+ gzos = new java.util.zip.GZIPOutputStream( b64os );
+ oos = new java.io.ObjectOutputStream( gzos );
+ } // end if: gzip
+ else
+ oos = new java.io.ObjectOutputStream( b64os );
+
+ oos.writeObject( serializableObject );
+ } // end try
+ catch( java.io.IOException e )
+ {
+ e.printStackTrace();
+ return null;
+ } // end catch
+ finally
+ {
+ try{ oos.close(); } catch( Exception e ){}
+ try{ gzos.close(); } catch( Exception e ){}
+ try{ b64os.close(); } catch( Exception e ){}
+ try{ baos.close(); } catch( Exception e ){}
+ } // end finally
+
+ // Return value according to relevant encoding.
+ try
+ {
+ return new String( baos.toByteArray(), PREFERRED_ENCODING );
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue)
+ {
+ return new String( baos.toByteArray() );
+ } // end catch
+
+ } // end encode
+
+
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * Does not GZip-compress data.
+ *
+ * @param source The data to convert
+ * @since 1.4
+ */
+ public static String encodeBytes( byte[] source )
+ {
+ return encodeBytes( source, 0, source.length, NO_OPTIONS );
+ } // end encodeBytes
+
+
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * <p>
+ * Valid options:<pre>
+ * GZIP: gzip-compresses object before encoding it.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+ *
+ *
+ * @param source The data to convert
+ * @param options Specified options
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeBytes( byte[] source, int options )
+ {
+ return encodeBytes( source, 0, source.length, options );
+ } // end encodeBytes
+
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * Does not GZip-compress data.
+ *
+ * @param source The data to convert
+ * @param off Offset in array where conversion should begin
+ * @param len Length of data to convert
+ * @since 1.4
+ */
+ public static String encodeBytes( byte[] source, int off, int len )
+ {
+ return encodeBytes( source, off, len, NO_OPTIONS );
+ } // end encodeBytes
+
+
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * <p>
+ * Valid options:<pre>
+ * GZIP: gzip-compresses object before encoding it.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
+ *
+ *
+ * @param source The data to convert
+ * @param off Offset in array where conversion should begin
+ * @param len Length of data to convert
+ * @param options Specified options; alphabet type is pulled from this (standard, url-safe, ordered)
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeBytes( byte[] source, int off, int len, int options )
+ {
+ // Isolate options
+ int dontBreakLines = ( options & DONT_BREAK_LINES );
+ int gzip = ( options & GZIP );
+
+ // Compress?
+ if( gzip == GZIP )
+ {
+ java.io.ByteArrayOutputStream baos = null;
+ java.util.zip.GZIPOutputStream gzos = null;
+ Base64.OutputStream b64os = null;
+
+
+ try
+ {
+ // GZip -> Base64 -> ByteArray
+ baos = new java.io.ByteArrayOutputStream();
+ b64os = new Base64.OutputStream( baos, ENCODE | options );
+ gzos = new java.util.zip.GZIPOutputStream( b64os );
+
+ gzos.write( source, off, len );
+ gzos.close();
+ } // end try
+ catch( java.io.IOException e )
+ {
+ e.printStackTrace();
+ return null;
+ } // end catch
+ finally
+ {
+ try{ gzos.close(); } catch( Exception e ){}
+ try{ b64os.close(); } catch( Exception e ){}
+ try{ baos.close(); } catch( Exception e ){}
+ } // end finally
+
+ // Return value according to relevant encoding.
+ try
+ {
+ return new String( baos.toByteArray(), PREFERRED_ENCODING );
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue)
+ {
+ return new String( baos.toByteArray() );
+ } // end catch
+ } // end if: compress
+
+ // Else, don't compress. Better not to use streams at all then.
+ else
+ {
+ // Convert option to boolean in way that code likes it.
+ boolean breakLines = dontBreakLines == 0;
+
+ int len43 = len * 4 / 3;
+ byte[] outBuff = new byte[ ( len43 ) // Main 4:3
+ + ( (len % 3) > 0 ? 4 : 0 ) // Account for padding
+ + (breakLines ? ( len43 / MAX_LINE_LENGTH ) : 0) ]; // New lines
+ int d = 0;
+ int e = 0;
+ int len2 = len - 2;
+ int lineLength = 0;
+ for( ; d < len2; d+=3, e+=4 )
+ {
+ encode3to4( source, d+off, 3, outBuff, e, options );
+
+ lineLength += 4;
+ if( breakLines && lineLength == MAX_LINE_LENGTH )
+ {
+ outBuff[e+4] = NEW_LINE;
+ e++;
+ lineLength = 0;
+ } // end if: end of line
+ } // en dfor: each piece of array
+
+ if( d < len )
+ {
+ encode3to4( source, d+off, len - d, outBuff, e, options );
+ e += 4;
+ } // end if: some padding needed
+
+
+ // Return value according to relevant encoding.
+ try
+ {
+ return new String( outBuff, 0, e, PREFERRED_ENCODING );
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue)
+ {
+ return new String( outBuff, 0, e );
+ } // end catch
+
+ } // end else: don't compress
+
+ } // end encodeBytes
+
+
+
+
+
+/* ******** D E C O D I N G M E T H O D S ******** */
+
+
+ /**
+ * Decodes four bytes from array <var>source</var>
+ * and writes the resulting bytes (up to three of them)
+ * to <var>destination</var>.
+ * The source and destination arrays can be manipulated
+ * anywhere along their length by specifying
+ * <var>srcOffset</var> and <var>destOffset</var>.
+ * This method does not check to make sure your arrays
+ * are large enough to accomodate <var>srcOffset</var> + 4 for
+ * the <var>source</var> array or <var>destOffset</var> + 3 for
+ * the <var>destination</var> array.
+ * This method returns the actual number of bytes that
+ * were converted from the Base64 encoding.
+ * <p>This is the lowest level of the decoding methods with
+ * all possible parameters.</p>
+ *
+ *
+ * @param source the array to convert
+ * @param srcOffset the index where conversion begins
+ * @param destination the array to hold the conversion
+ * @param destOffset the index where output will be put
+ * @param options alphabet type is pulled from this (standard, url-safe, ordered)
+ * @return the number of decoded bytes converted
+ * @since 1.3
+ */
+ private static int decode4to3( byte[] source, int srcOffset, byte[] destination, int destOffset, int options )
+ {
+ byte[] DECODABET = getDecodabet( options );
+
+ // Example: Dk==
+ if( source[ srcOffset + 2] == EQUALS_SIGN )
+ {
+ // Two ways to do the same thing. Don't know which way I like best.
+ //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
+ // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 );
+ int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 )
+ | ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF ) << 12 );
+
+ destination[ destOffset ] = (byte)( outBuff >>> 16 );
+ return 1;
+ }
+
+ // Example: DkL=
+ else if( source[ srcOffset + 3 ] == EQUALS_SIGN )
+ {
+ // Two ways to do the same thing. Don't know which way I like best.
+ //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
+ // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
+ // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 );
+ int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 )
+ | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 )
+ | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6 );
+
+ destination[ destOffset ] = (byte)( outBuff >>> 16 );
+ destination[ destOffset + 1 ] = (byte)( outBuff >>> 8 );
+ return 2;
+ }
+
+ // Example: DkLE
+ else
+ {
+ try{
+ // Two ways to do the same thing. Don't know which way I like best.
+ //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 )
+ // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
+ // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 )
+ // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 );
+ int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 )
+ | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 )
+ | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6)
+ | ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF ) );
+
+
+ destination[ destOffset ] = (byte)( outBuff >> 16 );
+ destination[ destOffset + 1 ] = (byte)( outBuff >> 8 );
+ destination[ destOffset + 2 ] = (byte)( outBuff );
+
+ return 3;
+ }catch( Exception e){
+ System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[ source[ srcOffset ] ] ) );
+ System.out.println(""+source[srcOffset+1]+ ": " + ( DECODABET[ source[ srcOffset + 1 ] ] ) );
+ System.out.println(""+source[srcOffset+2]+ ": " + ( DECODABET[ source[ srcOffset + 2 ] ] ) );
+ System.out.println(""+source[srcOffset+3]+ ": " + ( DECODABET[ source[ srcOffset + 3 ] ] ) );
+ return -1;
+ } // end catch
+ }
+ } // end decodeToBytes
+
+
+
+
+ /**
+ * Very low-level access to decoding ASCII characters in
+ * the form of a byte array. Does not support automatically
+ * gunzipping or any other "fancy" features.
+ *
+ * @param source The Base64 encoded data
+ * @param off The offset of where to begin decoding
+ * @param len The length of characters to decode
+ * @return decoded data
+ * @since 1.3
+ */
+ public static byte[] decode( byte[] source, int off, int len, int options )
+ {
+ byte[] DECODABET = getDecodabet( options );
+
+ int len34 = len * 3 / 4;
+ byte[] outBuff = new byte[ len34 ]; // Upper limit on size of output
+ int outBuffPosn = 0;
+
+ byte[] b4 = new byte[4];
+ int b4Posn = 0;
+ int i = 0;
+ byte sbiCrop = 0;
+ byte sbiDecode = 0;
+ for( i = off; i < off+len; i++ )
+ {
+ sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits
+ sbiDecode = DECODABET[ sbiCrop ];
+
+ if( sbiDecode >= WHITE_SPACE_ENC ) // White space, Equals sign or better
+ {
+ if( sbiDecode >= EQUALS_SIGN_ENC )
+ {
+ b4[ b4Posn++ ] = sbiCrop;
+ if( b4Posn > 3 )
+ {
+ outBuffPosn += decode4to3( b4, 0, outBuff, outBuffPosn, options );
+ b4Posn = 0;
+
+ // If that was the equals sign, break out of 'for' loop
+ if( sbiCrop == EQUALS_SIGN )
+ break;
+ } // end if: quartet built
+
+ } // end if: equals sign or better
+
+ } // end if: white space, equals sign or better
+ else
+ {
+ System.err.println( "Bad Base64 input character at " + i + ": " + source[i] + "(decimal)" );
+ return null;
+ } // end else:
+ } // each input character
+
+ byte[] out = new byte[ outBuffPosn ];
+ System.arraycopy( outBuff, 0, out, 0, outBuffPosn );
+ return out;
+ } // end decode
+
+
+
+
+ /**
+ * Decodes data from Base64 notation, automatically
+ * detecting gzip-compressed data and decompressing it.
+ *
+ * @param s the string to decode
+ * @return the decoded data
+ * @since 1.4
+ */
+ public static byte[] decode( String s )
+ {
+ return decode( s, NO_OPTIONS );
+ }
+
+
+ /**
+ * Decodes data from Base64 notation, automatically
+ * detecting gzip-compressed data and decompressing it.
+ *
+ * @param s the string to decode
+ * @param options encode options such as URL_SAFE
+ * @return the decoded data
+ * @since 1.4
+ */
+ public static byte[] decode( String s, int options )
+ {
+ byte[] bytes;
+ try
+ {
+ bytes = s.getBytes( PREFERRED_ENCODING );
+ } // end try
+ catch( java.io.UnsupportedEncodingException uee )
+ {
+ bytes = s.getBytes();
+ } // end catch
+ //</change>
+
+ // Decode
+ bytes = decode( bytes, 0, bytes.length, options );
+
+
+ // Check to see if it's gzip-compressed
+ // GZIP Magic Two-Byte Number: 0x8b1f (35615)
+ if( bytes != null && bytes.length >= 4 )
+ {
+
+ int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
+ if( java.util.zip.GZIPInputStream.GZIP_MAGIC == head )
+ {
+ java.io.ByteArrayInputStream bais = null;
+ java.util.zip.GZIPInputStream gzis = null;
+ java.io.ByteArrayOutputStream baos = null;
+ byte[] buffer = new byte[2048];
+ int length = 0;
+
+ try
+ {
+ baos = new java.io.ByteArrayOutputStream();
+ bais = new java.io.ByteArrayInputStream( bytes );
+ gzis = new java.util.zip.GZIPInputStream( bais );
+
+ while( ( length = gzis.read( buffer ) ) >= 0 )
+ {
+ baos.write(buffer,0,length);
+ } // end while: reading input
+
+ // No error? Get new bytes.
+ bytes = baos.toByteArray();
+
+ } // end try
+ catch( java.io.IOException e )
+ {
+ // Just return originally-decoded bytes
+ } // end catch
+ finally
+ {
+ try{ baos.close(); } catch( Exception e ){}
+ try{ gzis.close(); } catch( Exception e ){}
+ try{ bais.close(); } catch( Exception e ){}
+ } // end finally
+
+ } // end if: gzipped
+ } // end if: bytes.length >= 2
+
+ return bytes;
+ } // end decode
+
+
+
+
+ /**
+ * Attempts to decode Base64 data and deserialize a Java
+ * Object within. Returns <tt>null</tt> if there was an error.
+ *
+ * @param encodedObject The Base64 data to decode
+ * @return The decoded and deserialized object
+ * @since 1.5
+ */
+ public static Object decodeToObject( String encodedObject )
+ {
+ // Decode and gunzip if necessary
+ byte[] objBytes = decode( encodedObject );
+
+ java.io.ByteArrayInputStream bais = null;
+ java.io.ObjectInputStream ois = null;
+ Object obj = null;
+
+ try
+ {
+ bais = new java.io.ByteArrayInputStream( objBytes );
+ ois = new java.io.ObjectInputStream( bais );
+
+ obj = ois.readObject();
+ } // end try
+ catch( java.io.IOException e )
+ {
+ e.printStackTrace();
+ obj = null;
+ } // end catch
+ catch( java.lang.ClassNotFoundException e )
+ {
+ e.printStackTrace();
+ obj = null;
+ } // end catch
+ finally
+ {
+ try{ bais.close(); } catch( Exception e ){}
+ try{ ois.close(); } catch( Exception e ){}
+ } // end finally
+
+ return obj;
+ } // end decodeObject
+
+
+
+ /**
+ * Convenience method for encoding data to a file.
+ *
+ * @param dataToEncode byte array of data to encode in base64 form
+ * @param filename Filename for saving encoded data
+ * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
+ *
+ * @since 2.1
+ */
+ public static boolean encodeToFile( byte[] dataToEncode, String filename )
+ {
+ boolean success = false;
+ Base64.OutputStream bos = null;
+ try
+ {
+ bos = new Base64.OutputStream(
+ new java.io.FileOutputStream( filename ), Base64.ENCODE );
+ bos.write( dataToEncode );
+ success = true;
+ } // end try
+ catch( java.io.IOException e )
+ {
+
+ success = false;
+ } // end catch: IOException
+ finally
+ {
+ try{ bos.close(); } catch( Exception e ){}
+ } // end finally
+
+ return success;
+ } // end encodeToFile
+
+
+ /**
+ * Convenience method for decoding data to a file.
+ *
+ * @param dataToDecode Base64-encoded data as a string
+ * @param filename Filename for saving decoded data
+ * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
+ *
+ * @since 2.1
+ */
+ public static boolean decodeToFile( String dataToDecode, String filename )
+ {
+ boolean success = false;
+ Base64.OutputStream bos = null;
+ try
+ {
+ bos = new Base64.OutputStream(
+ new java.io.FileOutputStream( filename ), Base64.DECODE );
+ bos.write( dataToDecode.getBytes( PREFERRED_ENCODING ) );
+ success = true;
+ } // end try
+ catch( java.io.IOException e )
+ {
+ success = false;
+ } // end catch: IOException
+ finally
+ {
+ try{ bos.close(); } catch( Exception e ){}
+ } // end finally
+
+ return success;
+ } // end decodeToFile
+
+
+
+
+ /**
+ * Convenience method for reading a base64-encoded
+ * file and decoding it.
+ *
+ * @param filename Filename for reading encoded data
+ * @return decoded byte array or null if unsuccessful
+ *
+ * @since 2.1
+ */
+ public static byte[] decodeFromFile( String filename )
+ {
+ byte[] decodedData = null;
+ Base64.InputStream bis = null;
+ try
+ {
+ // Set up some useful variables
+ java.io.File file = new java.io.File( filename );
+ byte[] buffer = null;
+ int length = 0;
+ int numBytes = 0;
+
+ // Check for size of file
+ if( file.length() > Integer.MAX_VALUE )
+ {
+ System.err.println( "File is too big for this convenience method (" + file.length() + " bytes)." );
+ return null;
+ } // end if: file too big for int index
+ buffer = new byte[ (int)file.length() ];
+
+ // Open a stream
+ bis = new Base64.InputStream(
+ new java.io.BufferedInputStream(
+ new java.io.FileInputStream( file ) ), Base64.DECODE );
+
+ // Read until done
+ while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 )
+ length += numBytes;
+
+ // Save in a variable to return
+ decodedData = new byte[ length ];
+ System.arraycopy( buffer, 0, decodedData, 0, length );
+
+ } // end try
+ catch( java.io.IOException e )
+ {
+ System.err.println( "Error decoding from file " + filename );
+ } // end catch: IOException
+ finally
+ {
+ try{ bis.close(); } catch( Exception e) {}
+ } // end finally
+
+ return decodedData;
+ } // end decodeFromFile
+
+
+
+ /**
+ * Convenience method for reading a binary file
+ * and base64-encoding it.
+ *
+ * @param filename Filename for reading binary data
+ * @return base64-encoded string or null if unsuccessful
+ *
+ * @since 2.1
+ */
+ public static String encodeFromFile( String filename )
+ {
+ String encodedData = null;
+ Base64.InputStream bis = null;
+ try
+ {
+ // Set up some useful variables
+ java.io.File file = new java.io.File( filename );
+ byte[] buffer = new byte[ Math.max((int)(file.length() * 1.4),40) ]; // Need max() for math on small files (v2.2.1)
+ int length = 0;
+ int numBytes = 0;
+
+ // Open a stream
+ bis = new Base64.InputStream(
+ new java.io.BufferedInputStream(
+ new java.io.FileInputStream( file ) ), Base64.ENCODE );
+
+ // Read until done
+ while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 )
+ length += numBytes;
+
+ // Save in a variable to return
+ encodedData = new String( buffer, 0, length, Base64.PREFERRED_ENCODING );
+
+ } // end try
+ catch( java.io.IOException e )
+ {
+ System.err.println( "Error encoding from file " + filename );
+ } // end catch: IOException
+ finally
+ {
+ try{ bis.close(); } catch( Exception e) {}
+ } // end finally
+
+ return encodedData;
+ } // end encodeFromFile
+
+ /**
+ * Reads <tt>infile</tt> and encodes it to <tt>outfile</tt>.
+ *
+ * @param infile Input file
+ * @param outfile Output file
+ * @since 2.2
+ */
+ public static void encodeFileToFile( String infile, String outfile )
+ {
+ String encoded = Base64.encodeFromFile( infile );
+ java.io.OutputStream out = null;
+ try{
+ out = new java.io.BufferedOutputStream(
+ new java.io.FileOutputStream( outfile ) );
+ out.write( encoded.getBytes("US-ASCII") ); // Strict, 7-bit output.
+ } // end try
+ catch( java.io.IOException ex ) {
+ ex.printStackTrace();
+ } // end catch
+ finally {
+ try { out.close(); }
+ catch( Exception ex ){}
+ } // end finally
+ } // end encodeFileToFile
+
+
+ /**
+ * Reads <tt>infile</tt> and decodes it to <tt>outfile</tt>.
+ *
+ * @param infile Input file
+ * @param outfile Output file
+ * @since 2.2
+ */
+ public static void decodeFileToFile( String infile, String outfile )
+ {
+ byte[] decoded = Base64.decodeFromFile( infile );
+ java.io.OutputStream out = null;
+ try{
+ out = new java.io.BufferedOutputStream(
+ new java.io.FileOutputStream( outfile ) );
+ out.write( decoded );
+ } // end try
+ catch( java.io.IOException ex ) {
+ ex.printStackTrace();
+ } // end catch
+ finally {
+ try { out.close(); }
+ catch( Exception ex ){}
+ } // end finally
+ } // end decodeFileToFile
+
+
+ /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */
+
+
+
+ /**
+ * A {@link Base64.InputStream} will read data from another
+ * <tt>java.io.InputStream</tt>, given in the constructor,
+ * and encode/decode to/from Base64 notation on the fly.
+ *
+ * @see Base64
+ * @since 1.3
+ */
+ public static class InputStream extends java.io.FilterInputStream
+ {
+ private boolean encode; // Encoding or decoding
+ private int position; // Current position in the buffer
+ private byte[] buffer; // Small buffer holding converted data
+ private int bufferLength; // Length of buffer (3 or 4)
+ private int numSigBytes; // Number of meaningful bytes in the buffer
+ private int lineLength;
+ private boolean breakLines; // Break lines at less than 80 characters
+ private int options; // Record options used to create the stream.
+ private byte[] alphabet; // Local copies to avoid extra method calls
+ private byte[] decodabet; // Local copies to avoid extra method calls
+
+
+ /**
+ * Constructs a {@link Base64.InputStream} in DECODE mode.
+ *
+ * @param in the <tt>java.io.InputStream</tt> from which to read data.
+ * @since 1.3
+ */
+ public InputStream( java.io.InputStream in )
+ {
+ this( in, DECODE );
+ } // end constructor
+
+
+ /**
+ * Constructs a {@link Base64.InputStream} in
+ * either ENCODE or DECODE mode.
+ * <p>
+ * Valid options:<pre>
+ * ENCODE or DECODE: Encode or Decode as data is read.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * (only meaningful when encoding)
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>new Base64.InputStream( in, Base64.DECODE )</code>
+ *
+ *
+ * @param in the <tt>java.io.InputStream</tt> from which to read data.
+ * @param options Specified options
+ * @see Base64#ENCODE
+ * @see Base64#DECODE
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public InputStream( java.io.InputStream in, int options )
+ {
+ super( in );
+ this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
+ this.encode = (options & ENCODE) == ENCODE;
+ this.bufferLength = encode ? 4 : 3;
+ this.buffer = new byte[ bufferLength ];
+ this.position = -1;
+ this.lineLength = 0;
+ this.options = options; // Record for later, mostly to determine which alphabet to use
+ this.alphabet = getAlphabet(options);
+ this.decodabet = getDecodabet(options);
+ } // end constructor
+
+ /**
+ * Reads enough of the input stream to convert
+ * to/from Base64 and returns the next byte.
+ *
+ * @return next byte
+ * @since 1.3
+ */
+ public int read() throws java.io.IOException
+ {
+ // Do we need to get data?
+ if( position < 0 )
+ {
+ if( encode )
+ {
+ byte[] b3 = new byte[3];
+ int numBinaryBytes = 0;
+ for( int i = 0; i < 3; i++ )
+ {
+ try
+ {
+ int b = in.read();
+
+ // If end of stream, b is -1.
+ if( b >= 0 )
+ {
+ b3[i] = (byte)b;
+ numBinaryBytes++;
+ } // end if: not end of stream
+
+ } // end try: read
+ catch( java.io.IOException e )
+ {
+ // Only a problem if we got no data at all.
+ if( i == 0 )
+ throw e;
+
+ } // end catch
+ } // end for: each needed input byte
+
+ if( numBinaryBytes > 0 )
+ {
+ encode3to4( b3, 0, numBinaryBytes, buffer, 0, options );
+ position = 0;
+ numSigBytes = 4;
+ } // end if: got data
+ else
+ {
+ return -1;
+ } // end else
+ } // end if: encoding
+
+ // Else decoding
+ else
+ {
+ byte[] b4 = new byte[4];
+ int i = 0;
+ for( i = 0; i < 4; i++ )
+ {
+ // Read four "meaningful" bytes:
+ int b = 0;
+ do{ b = in.read(); }
+ while( b >= 0 && decodabet[ b & 0x7f ] <= WHITE_SPACE_ENC );
+
+ if( b < 0 )
+ break; // Reads a -1 if end of stream
+
+ b4[i] = (byte)b;
+ } // end for: each needed input byte
+
+ if( i == 4 )
+ {
+ numSigBytes = decode4to3( b4, 0, buffer, 0, options );
+ position = 0;
+ } // end if: got four characters
+ else if( i == 0 ){
+ return -1;
+ } // end else if: also padded correctly
+ else
+ {
+ // Must have broken out from above.
+ throw new java.io.IOException( "Improperly padded Base64 input." );
+ } // end
+
+ } // end else: decode
+ } // end else: get data
+
+ // Got data?
+ if( position >= 0 )
+ {
+ // End of relevant data?
+ if( /*!encode &&*/ position >= numSigBytes )
+ return -1;
+
+ if( encode && breakLines && lineLength >= MAX_LINE_LENGTH )
+ {
+ lineLength = 0;
+ return '\n';
+ } // end if
+ else
+ {
+ lineLength++; // This isn't important when decoding
+ // but throwing an extra "if" seems
+ // just as wasteful.
+
+ int b = buffer[ position++ ];
+
+ if( position >= bufferLength )
+ position = -1;
+
+ return b & 0xFF; // This is how you "cast" a byte that's
+ // intended to be unsigned.
+ } // end else
+ } // end if: position >= 0
+
+ // Else error
+ else
+ {
+ // When JDK1.4 is more accepted, use an assertion here.
+ throw new java.io.IOException( "Error in Base64 code reading stream." );
+ } // end else
+ } // end read
+
+
+ /**
+ * Calls {@link #read()} repeatedly until the end of stream
+ * is reached or <var>len</var> bytes are read.
+ * Returns number of bytes read into array or -1 if
+ * end of stream is encountered.
+ *
+ * @param dest array to hold values
+ * @param off offset for array
+ * @param len max number of bytes to read into array
+ * @return bytes read into array or -1 if end of stream is encountered.
+ * @since 1.3
+ */
+ public int read( byte[] dest, int off, int len ) throws java.io.IOException
+ {
+ int i;
+ int b;
+ for( i = 0; i < len; i++ )
+ {
+ b = read();
+
+ //if( b < 0 && i == 0 )
+ // return -1;
+
+ if( b >= 0 )
+ dest[off + i] = (byte)b;
+ else if( i == 0 )
+ return -1;
+ else
+ break; // Out of 'for' loop
+ } // end for: each byte read
+ return i;
+ } // end read
+
+ } // end inner class InputStream
+
+
+
+
+
+
+ /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */
+
+
+
+ /**
+ * A {@link Base64.OutputStream} will write data to another
+ * <tt>java.io.OutputStream</tt>, given in the constructor,
+ * and encode/decode to/from Base64 notation on the fly.
+ *
+ * @see Base64
+ * @since 1.3
+ */
+ public static class OutputStream extends java.io.FilterOutputStream
+ {
+ private boolean encode;
+ private int position;
+ private byte[] buffer;
+ private int bufferLength;
+ private int lineLength;
+ private boolean breakLines;
+ private byte[] b4; // Scratch used in a few places
+ private boolean suspendEncoding;
+ private int options; // Record for later
+ private byte[] alphabet; // Local copies to avoid extra method calls
+ private byte[] decodabet; // Local copies to avoid extra method calls
+
+ /**
+ * Constructs a {@link Base64.OutputStream} in ENCODE mode.
+ *
+ * @param out the <tt>java.io.OutputStream</tt> to which data will be written.
+ * @since 1.3
+ */
+ public OutputStream( java.io.OutputStream out )
+ {
+ this( out, ENCODE );
+ } // end constructor
+
+
+ /**
+ * Constructs a {@link Base64.OutputStream} in
+ * either ENCODE or DECODE mode.
+ * <p>
+ * Valid options:<pre>
+ * ENCODE or DECODE: Encode or Decode as data is read.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * (only meaningful when encoding)
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>new Base64.OutputStream( out, Base64.ENCODE )</code>
+ *
+ * @param out the <tt>java.io.OutputStream</tt> to which data will be written.
+ * @param options Specified options.
+ * @see Base64#ENCODE
+ * @see Base64#DECODE
+ * @see Base64#DONT_BREAK_LINES
+ * @since 1.3
+ */
+ public OutputStream( java.io.OutputStream out, int options )
+ {
+ super( out );
+ this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
+ this.encode = (options & ENCODE) == ENCODE;
+ this.bufferLength = encode ? 3 : 4;
+ this.buffer = new byte[ bufferLength ];
+ this.position = 0;
+ this.lineLength = 0;
+ this.suspendEncoding = false;
+ this.b4 = new byte[4];
+ this.options = options;
+ this.alphabet = getAlphabet(options);
+ this.decodabet = getDecodabet(options);
+ } // end constructor
+
+
+ /**
+ * Writes the byte to the output stream after
+ * converting to/from Base64 notation.
+ * When encoding, bytes are buffered three
+ * at a time before the output stream actually
+ * gets a write() call.
+ * When decoding, bytes are buffered four
+ * at a time.
+ *
+ * @param theByte the byte to write
+ * @since 1.3
+ */
+ public void write(int theByte) throws java.io.IOException
+ {
+ // Encoding suspended?
+ if( suspendEncoding )
+ {
+ super.out.write( theByte );
+ return;
+ } // end if: supsended
+
+ // Encode?
+ if( encode )
+ {
+ buffer[ position++ ] = (byte)theByte;
+ if( position >= bufferLength ) // Enough to encode.
+ {
+ out.write( encode3to4( b4, buffer, bufferLength, options ) );
+
+ lineLength += 4;
+ if( breakLines && lineLength >= MAX_LINE_LENGTH )
+ {
+ out.write( NEW_LINE );
+ lineLength = 0;
+ } // end if: end of line
+
+ position = 0;
+ } // end if: enough to output
+ } // end if: encoding
+
+ // Else, Decoding
+ else
+ {
+ // Meaningful Base64 character?
+ if( decodabet[ theByte & 0x7f ] > WHITE_SPACE_ENC )
+ {
+ buffer[ position++ ] = (byte)theByte;
+ if( position >= bufferLength ) // Enough to output.
+ {
+ int len = Base64.decode4to3( buffer, 0, b4, 0, options );
+ out.write( b4, 0, len );
+ //out.write( Base64.decode4to3( buffer ) );
+ position = 0;
+ } // end if: enough to output
+ } // end if: meaningful base64 character
+ else if( decodabet[ theByte & 0x7f ] != WHITE_SPACE_ENC )
+ {
+ throw new java.io.IOException( "Invalid character in Base64 data." );
+ } // end else: not white space either
+ } // end else: decoding
+ } // end write
+
+
+
+ /**
+ * Calls {@link #write(int)} repeatedly until <var>len</var>
+ * bytes are written.
+ *
+ * @param theBytes array from which to read bytes
+ * @param off offset for array
+ * @param len max number of bytes to read into array
+ * @since 1.3
+ */
+ public void write( byte[] theBytes, int off, int len ) throws java.io.IOException
+ {
+ // Encoding suspended?
+ if( suspendEncoding )
+ {
+ super.out.write( theBytes, off, len );
+ return;
+ } // end if: supsended
+
+ for( int i = 0; i < len; i++ )
+ {
+ write( theBytes[ off + i ] );
+ } // end for: each byte written
+
+ } // end write
+
+
+
+ /**
+ * Method added by PHIL. [Thanks, PHIL. -Rob]
+ * This pads the buffer without closing the stream.
+ */
+ public void flushBase64() throws java.io.IOException
+ {
+ if( position > 0 )
+ {
+ if( encode )
+ {
+ out.write( encode3to4( b4, buffer, position, options ) );
+ position = 0;
+ } // end if: encoding
+ else
+ {
+ throw new java.io.IOException( "Base64 input not properly padded." );
+ } // end else: decoding
+ } // end if: buffer partially full
+
+ } // end flush
+
+
+ /**
+ * Flushes and closes (I think, in the superclass) the stream.
+ *
+ * @since 1.3
+ */
+ public void close() throws java.io.IOException
+ {
+ // 1. Ensure that pending characters are written
+ flushBase64();
+
+ // 2. Actually close the stream
+ // Base class both flushes and closes.
+ super.close();
+
+ buffer = null;
+ out = null;
+ } // end close
+
+
+
+ /**
+ * Suspends encoding of the stream.
+ * May be helpful if you need to embed a piece of
+ * base640-encoded data in a stream.
+ *
+ * @since 1.5.1
+ */
+ public void suspendEncoding() throws java.io.IOException
+ {
+ flushBase64();
+ this.suspendEncoding = true;
+ } // end suspendEncoding
+
+
+ /**
+ * Resumes encoding of the stream.
+ * May be helpful if you need to embed a piece of
+ * base640-encoded data in a stream.
+ *
+ * @since 1.5.1
+ */
+ public void resumeEncoding()
+ {
+ this.suspendEncoding = false;
+ } // end resumeEncoding
+
+
+
+ } // end inner class OutputStream
+
+
+} // end class Base64
+
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/util/SyncPacketSend.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/util/SyncPacketSend.java
index 6506cbd88..58cf1f85f 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/util/SyncPacketSend.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smack/util/SyncPacketSend.java
@@ -1,64 +1,64 @@
-/**
- * All rights reserved. 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 org.jivesoftware.smack.util;
-
-import org.jivesoftware.smack.PacketCollector;
-import org.jivesoftware.smack.SmackConfiguration;
-import org.jivesoftware.smack.Connection;
-import org.jivesoftware.smack.SmackError;
-import org.jivesoftware.smack.XMPPException;
-import org.jivesoftware.smack.filter.PacketFilter;
-import org.jivesoftware.smack.filter.PacketIDFilter;
-import org.jivesoftware.smack.packet.Packet;
-
-/**
- * Utility class for doing synchronous calls to the server. Provides several
- * methods for sending a packet to the server and waiting for the reply.
- *
- * @author Robin Collier
- */
-final public class SyncPacketSend
-{
- private SyncPacketSend()
- { }
-
- static public Packet getReply(Connection connection, Packet packet, long timeout)
- throws XMPPException
- {
- PacketFilter responseFilter = new PacketIDFilter(packet.getPacketID());
- PacketCollector response = connection.createPacketCollector(responseFilter);
-
- connection.sendPacket(packet);
-
- // Wait up to a certain number of seconds for a reply.
- Packet result = response.nextResult(timeout);
-
- // Stop queuing results
- response.cancel();
-
- if (result == null) {
- throw new XMPPException(SmackError.NO_RESPONSE_FROM_SERVER);
- }
- else if (result.getError() != null) {
- throw new XMPPException(result.getError());
- }
- return result;
- }
-
- static public Packet getReply(Connection connection, Packet packet)
- throws XMPPException
- {
- return getReply(connection, packet, SmackConfiguration.getPacketReplyTimeout());
- }
-}
+/**
+ * All rights reserved. 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 org.jivesoftware.smack.util;
+
+import org.jivesoftware.smack.PacketCollector;
+import org.jivesoftware.smack.SmackConfiguration;
+import org.jivesoftware.smack.Connection;
+import org.jivesoftware.smack.SmackError;
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smack.filter.PacketFilter;
+import org.jivesoftware.smack.filter.PacketIDFilter;
+import org.jivesoftware.smack.packet.Packet;
+
+/**
+ * Utility class for doing synchronous calls to the server. Provides several
+ * methods for sending a packet to the server and waiting for the reply.
+ *
+ * @author Robin Collier
+ */
+final public class SyncPacketSend
+{
+ private SyncPacketSend()
+ { }
+
+ static public Packet getReply(Connection connection, Packet packet, long timeout)
+ throws XMPPException
+ {
+ PacketFilter responseFilter = new PacketIDFilter(packet.getPacketID());
+ PacketCollector response = connection.createPacketCollector(responseFilter);
+
+ connection.sendPacket(packet);
+
+ // Wait up to a certain number of seconds for a reply.
+ Packet result = response.nextResult(timeout);
+
+ // Stop queuing results
+ response.cancel();
+
+ if (result == null) {
+ throw new XMPPException(SmackError.NO_RESPONSE_FROM_SERVER);
+ }
+ else if (result.getError() != null) {
+ throw new XMPPException(result.getError());
+ }
+ return result;
+ }
+
+ static public Packet getReply(Connection connection, Packet packet)
+ throws XMPPException
+ {
+ return getReply(connection, packet, SmackConfiguration.getPacketReplyTimeout());
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/LastActivityManager.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/LastActivityManager.java
index a9d1f12b8..7729bc07a 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/LastActivityManager.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/LastActivityManager.java
@@ -1,230 +1,230 @@
-/**
- * $RCSfile$
- * $Revision$
- * $Date$
- *
- * Copyright 2003-2006 Jive Software.
- *
- * All rights reserved. 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 org.jivesoftware.smackx;
-
-import org.jivesoftware.smack.*;
-import org.jivesoftware.smack.filter.AndFilter;
-import org.jivesoftware.smack.filter.IQTypeFilter;
-import org.jivesoftware.smack.filter.PacketIDFilter;
-import org.jivesoftware.smack.filter.PacketTypeFilter;
-import org.jivesoftware.smack.packet.IQ;
-import org.jivesoftware.smack.packet.Message;
-import org.jivesoftware.smack.packet.Packet;
-import org.jivesoftware.smack.packet.Presence;
-import org.jivesoftware.smackx.packet.DiscoverInfo;
-import org.jivesoftware.smackx.packet.LastActivity;
-
-/**
- * A last activity manager for handling information about the last activity
- * associated with a Jabber ID. A manager handles incoming LastActivity requests
- * of existing Connections. It also allows to request last activity information
- * of other users.
- * <p>
- *
- * LastActivity (XEP-0012) based on the sending JID's type allows for retrieval
- * of:
- * <ol>
- * <li>How long a particular user has been idle
- * <li>How long a particular user has been logged-out and the message the
- * specified when doing so.
- * <li>How long a host has been up.
- * </ol>
- * <p/>
- *
- * For example to get the idle time of a user logged in a resource, simple send
- * the LastActivity packet to them, as in the following code:
- * <p>
- *
- * <pre>
- * Connection con = new XMPPConnection(&quot;jabber.org&quot;);
- * con.login(&quot;john&quot;, &quot;doe&quot;);
- * LastActivity activity = LastActivity.getLastActivity(con, &quot;xray@jabber.org/Smack&quot;);
- * </pre>
- *
- * To get the lapsed time since the last user logout is the same as above but
- * with out the resource:
- *
- * <pre>
- * LastActivity activity = LastActivity.getLastActivity(con, &quot;xray@jabber.org&quot;);
- * </pre>
- *
- * To get the uptime of a host, you simple send the LastActivity packet to it,
- * as in the following code example:
- * <p>
- *
- * <pre>
- * LastActivity activity = LastActivity.getLastActivity(con, &quot;jabber.org&quot;);
- * </pre>
- *
- * @author Gabriel Guardincerri
- * @see <a href="http://xmpp.org/extensions/xep-0012.html">XEP-0012: Last
- * Activity</a>
- */
-
-public class LastActivityManager {
-
- private long lastMessageSent;
-
- private Connection connection;
-
- // Enable the LastActivity support on every established connection
- static {
- Connection.addConnectionCreationListener(new ConnectionCreationListener() {
- public void connectionCreated(Connection connection) {
- new LastActivityManager(connection);
- }
- });
- }
-
- /**
- * Creates a last activity manager to response last activity requests.
- *
- * @param connection
- * The Connection that the last activity requests will use.
- */
- private LastActivityManager(Connection connection) {
- this.connection = connection;
-
- // Listen to all the sent messages to reset the idle time on each one
- connection.addPacketSendingListener(new PacketListener() {
- public void processPacket(Packet packet) {
- Presence presence = (Presence) packet;
- Presence.Mode mode = presence.getMode();
- if (mode == null) return;
- switch (mode) {
- case available:
- case chat:
- // We assume that only a switch to available and chat indicates user activity
- // since other mode changes could be also a result of some sort of automatism
- resetIdleTime();
- }
- }
- }, new PacketTypeFilter(Presence.class));
-
- connection.addPacketListener(new PacketListener() {
- @Override
- public void processPacket(Packet packet) {
- Message message = (Message) packet;
- // if it's not an error message, reset the idle time
- if (message.getType() == Message.Type.error) return;
- resetIdleTime();
- }
- }, new PacketTypeFilter(Message.class));
-
- // Register a listener for a last activity query
- connection.addPacketListener(new PacketListener() {
-
- public void processPacket(Packet packet) {
- LastActivity message = new LastActivity();
- message.setType(IQ.Type.RESULT);
- message.setTo(packet.getFrom());
- message.setFrom(packet.getTo());
- message.setPacketID(packet.getPacketID());
- message.setLastActivity(getIdleTime());
-
- LastActivityManager.this.connection.sendPacket(message);
- }
-
- }, new AndFilter(new IQTypeFilter(IQ.Type.GET), new PacketTypeFilter(LastActivity.class)));
- ServiceDiscoveryManager.getInstanceFor(connection).addFeature(LastActivity.NAMESPACE);
- resetIdleTime();
- }
-
- /**
- * Resets the idle time to 0, this should be invoked when a new message is
- * sent.
- */
- private void resetIdleTime() {
- long now = System.currentTimeMillis();
- synchronized (this) {
- lastMessageSent = now;
- }
- }
-
- /**
- * The idle time is the lapsed time between the last message sent and now.
- *
- * @return the lapsed time between the last message sent and now.
- */
- private long getIdleTime() {
- long lms;
- long now = System.currentTimeMillis();
- synchronized (this) {
- lms = lastMessageSent;
- }
- return ((now - lms) / 1000);
- }
-
- /**
- * Returns the last activity of a particular jid. If the jid is a full JID
- * (i.e., a JID of the form of 'user@host/resource') then the last activity
- * is the idle time of that connected resource. On the other hand, when the
- * jid is a bare JID (e.g. 'user@host') then the last activity is the lapsed
- * time since the last logout or 0 if the user is currently logged in.
- * Moreover, when the jid is a server or component (e.g., a JID of the form
- * 'host') the last activity is the uptime.
- *
- * @param con
- * the current Connection.
- * @param jid
- * the JID of the user.
- * @return the LastActivity packet of the jid.
- * @throws XMPPException
- * thrown if a server error has occured.
- */
- public static LastActivity getLastActivity(Connection con, String jid) throws XMPPException {
- LastActivity activity = new LastActivity();
- activity.setTo(jid);
-
- PacketCollector collector = con.createPacketCollector(new PacketIDFilter(activity.getPacketID()));
- con.sendPacket(activity);
-
- LastActivity response = (LastActivity) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
-
- // Cancel the collector.
- collector.cancel();
- if (response == null) {
- throw new XMPPException("No response from server on status set.");
- }
- if (response.getError() != null) {
- throw new XMPPException(response.getError());
- }
- return response;
- }
-
- /**
- * Returns true if Last Activity (XEP-0012) is supported by a given JID
- *
- * @param connection the connection to be used
- * @param jid a JID to be tested for Last Activity support
- * @return true if Last Activity is supported, otherwise false
- */
- public static boolean isLastActivitySupported(Connection connection, String jid) {
- try {
- DiscoverInfo result =
- ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(jid);
- return result.containsFeature(LastActivity.NAMESPACE);
- }
- catch (XMPPException e) {
- return false;
- }
- }
-}
+/**
+ * $RCSfile$
+ * $Revision$
+ * $Date$
+ *
+ * Copyright 2003-2006 Jive Software.
+ *
+ * All rights reserved. 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 org.jivesoftware.smackx;
+
+import org.jivesoftware.smack.*;
+import org.jivesoftware.smack.filter.AndFilter;
+import org.jivesoftware.smack.filter.IQTypeFilter;
+import org.jivesoftware.smack.filter.PacketIDFilter;
+import org.jivesoftware.smack.filter.PacketTypeFilter;
+import org.jivesoftware.smack.packet.IQ;
+import org.jivesoftware.smack.packet.Message;
+import org.jivesoftware.smack.packet.Packet;
+import org.jivesoftware.smack.packet.Presence;
+import org.jivesoftware.smackx.packet.DiscoverInfo;
+import org.jivesoftware.smackx.packet.LastActivity;
+
+/**
+ * A last activity manager for handling information about the last activity
+ * associated with a Jabber ID. A manager handles incoming LastActivity requests
+ * of existing Connections. It also allows to request last activity information
+ * of other users.
+ * <p>
+ *
+ * LastActivity (XEP-0012) based on the sending JID's type allows for retrieval
+ * of:
+ * <ol>
+ * <li>How long a particular user has been idle
+ * <li>How long a particular user has been logged-out and the message the
+ * specified when doing so.
+ * <li>How long a host has been up.
+ * </ol>
+ * <p/>
+ *
+ * For example to get the idle time of a user logged in a resource, simple send
+ * the LastActivity packet to them, as in the following code:
+ * <p>
+ *
+ * <pre>
+ * Connection con = new XMPPConnection(&quot;jabber.org&quot;);
+ * con.login(&quot;john&quot;, &quot;doe&quot;);
+ * LastActivity activity = LastActivity.getLastActivity(con, &quot;xray@jabber.org/Smack&quot;);
+ * </pre>
+ *
+ * To get the lapsed time since the last user logout is the same as above but
+ * with out the resource:
+ *
+ * <pre>
+ * LastActivity activity = LastActivity.getLastActivity(con, &quot;xray@jabber.org&quot;);
+ * </pre>
+ *
+ * To get the uptime of a host, you simple send the LastActivity packet to it,
+ * as in the following code example:
+ * <p>
+ *
+ * <pre>
+ * LastActivity activity = LastActivity.getLastActivity(con, &quot;jabber.org&quot;);
+ * </pre>
+ *
+ * @author Gabriel Guardincerri
+ * @see <a href="http://xmpp.org/extensions/xep-0012.html">XEP-0012: Last
+ * Activity</a>
+ */
+
+public class LastActivityManager {
+
+ private long lastMessageSent;
+
+ private Connection connection;
+
+ // Enable the LastActivity support on every established connection
+ static {
+ Connection.addConnectionCreationListener(new ConnectionCreationListener() {
+ public void connectionCreated(Connection connection) {
+ new LastActivityManager(connection);
+ }
+ });
+ }
+
+ /**
+ * Creates a last activity manager to response last activity requests.
+ *
+ * @param connection
+ * The Connection that the last activity requests will use.
+ */
+ private LastActivityManager(Connection connection) {
+ this.connection = connection;
+
+ // Listen to all the sent messages to reset the idle time on each one
+ connection.addPacketSendingListener(new PacketListener() {
+ public void processPacket(Packet packet) {
+ Presence presence = (Presence) packet;
+ Presence.Mode mode = presence.getMode();
+ if (mode == null) return;
+ switch (mode) {
+ case available:
+ case chat:
+ // We assume that only a switch to available and chat indicates user activity
+ // since other mode changes could be also a result of some sort of automatism
+ resetIdleTime();
+ }
+ }
+ }, new PacketTypeFilter(Presence.class));
+
+ connection.addPacketListener(new PacketListener() {
+ @Override
+ public void processPacket(Packet packet) {
+ Message message = (Message) packet;
+ // if it's not an error message, reset the idle time
+ if (message.getType() == Message.Type.error) return;
+ resetIdleTime();
+ }
+ }, new PacketTypeFilter(Message.class));
+
+ // Register a listener for a last activity query
+ connection.addPacketListener(new PacketListener() {
+
+ public void processPacket(Packet packet) {
+ LastActivity message = new LastActivity();
+ message.setType(IQ.Type.RESULT);
+ message.setTo(packet.getFrom());
+ message.setFrom(packet.getTo());
+ message.setPacketID(packet.getPacketID());
+ message.setLastActivity(getIdleTime());
+
+ LastActivityManager.this.connection.sendPacket(message);
+ }
+
+ }, new AndFilter(new IQTypeFilter(IQ.Type.GET), new PacketTypeFilter(LastActivity.class)));
+ ServiceDiscoveryManager.getInstanceFor(connection).addFeature(LastActivity.NAMESPACE);
+ resetIdleTime();
+ }
+
+ /**
+ * Resets the idle time to 0, this should be invoked when a new message is
+ * sent.
+ */
+ private void resetIdleTime() {
+ long now = System.currentTimeMillis();
+ synchronized (this) {
+ lastMessageSent = now;
+ }
+ }
+
+ /**
+ * The idle time is the lapsed time between the last message sent and now.
+ *
+ * @return the lapsed time between the last message sent and now.
+ */
+ private long getIdleTime() {
+ long lms;
+ long now = System.currentTimeMillis();
+ synchronized (this) {
+ lms = lastMessageSent;
+ }
+ return ((now - lms) / 1000);
+ }
+
+ /**
+ * Returns the last activity of a particular jid. If the jid is a full JID
+ * (i.e., a JID of the form of 'user@host/resource') then the last activity
+ * is the idle time of that connected resource. On the other hand, when the
+ * jid is a bare JID (e.g. 'user@host') then the last activity is the lapsed
+ * time since the last logout or 0 if the user is currently logged in.
+ * Moreover, when the jid is a server or component (e.g., a JID of the form
+ * 'host') the last activity is the uptime.
+ *
+ * @param con
+ * the current Connection.
+ * @param jid
+ * the JID of the user.
+ * @return the LastActivity packet of the jid.
+ * @throws XMPPException
+ * thrown if a server error has occured.
+ */
+ public static LastActivity getLastActivity(Connection con, String jid) throws XMPPException {
+ LastActivity activity = new LastActivity();
+ activity.setTo(jid);
+
+ PacketCollector collector = con.createPacketCollector(new PacketIDFilter(activity.getPacketID()));
+ con.sendPacket(activity);
+
+ LastActivity response = (LastActivity) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
+
+ // Cancel the collector.
+ collector.cancel();
+ if (response == null) {
+ throw new XMPPException("No response from server on status set.");
+ }
+ if (response.getError() != null) {
+ throw new XMPPException(response.getError());
+ }
+ return response;
+ }
+
+ /**
+ * Returns true if Last Activity (XEP-0012) is supported by a given JID
+ *
+ * @param connection the connection to be used
+ * @param jid a JID to be tested for Last Activity support
+ * @return true if Last Activity is supported, otherwise false
+ */
+ public static boolean isLastActivitySupported(Connection connection, String jid) {
+ try {
+ DiscoverInfo result =
+ ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(jid);
+ return result.containsFeature(LastActivity.NAMESPACE);
+ }
+ catch (XMPPException e) {
+ return false;
+ }
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/SharedGroupManager.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/SharedGroupManager.java
index 76cd527c5..44ab67070 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/SharedGroupManager.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/SharedGroupManager.java
@@ -17,56 +17,56 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jivesoftware.smackx;
-
-import org.jivesoftware.smack.Connection;
-import org.jivesoftware.smack.PacketCollector;
-import org.jivesoftware.smack.SmackConfiguration;
-import org.jivesoftware.smack.XMPPException;
-import org.jivesoftware.smack.filter.PacketIDFilter;
-import org.jivesoftware.smack.packet.IQ;
-import org.jivesoftware.smackx.packet.SharedGroupsInfo;
-
-import java.util.List;
-
-/**
- * A SharedGroupManager provides services for discovering the shared groups where a user belongs.<p>
- *
- * Important note: This functionality is not part of the XMPP spec and it will only work
- * with Wildfire.
- *
- * @author Gaston Dombiak
- */
-public class SharedGroupManager {
-
- /**
- * Returns the collection that will contain the name of the shared groups where the user
- * logged in with the specified session belongs.
- *
- * @param connection connection to use to get the user's shared groups.
- * @return collection with the shared groups' name of the logged user.
- */
- public static List<String> getSharedGroups(Connection connection) throws XMPPException {
- // Discover the shared groups of the logged user
- SharedGroupsInfo info = new SharedGroupsInfo();
- info.setType(IQ.Type.GET);
-
- // Create a packet collector to listen for a response.
- PacketCollector collector =
- connection.createPacketCollector(new PacketIDFilter(info.getPacketID()));
-
- connection.sendPacket(info);
-
- // Wait up to 5 seconds for a result.
- IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
- // Stop queuing results
- collector.cancel();
- if (result == null) {
- throw new XMPPException("No response from the server.");
- }
- if (result.getType() == IQ.Type.ERROR) {
- throw new XMPPException(result.getError());
- }
- return ((SharedGroupsInfo) result).getGroups();
- }
-}
+package org.jivesoftware.smackx;
+
+import org.jivesoftware.smack.Connection;
+import org.jivesoftware.smack.PacketCollector;
+import org.jivesoftware.smack.SmackConfiguration;
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smack.filter.PacketIDFilter;
+import org.jivesoftware.smack.packet.IQ;
+import org.jivesoftware.smackx.packet.SharedGroupsInfo;
+
+import java.util.List;
+
+/**
+ * A SharedGroupManager provides services for discovering the shared groups where a user belongs.<p>
+ *
+ * Important note: This functionality is not part of the XMPP spec and it will only work
+ * with Wildfire.
+ *
+ * @author Gaston Dombiak
+ */
+public class SharedGroupManager {
+
+ /**
+ * Returns the collection that will contain the name of the shared groups where the user
+ * logged in with the specified session belongs.
+ *
+ * @param connection connection to use to get the user's shared groups.
+ * @return collection with the shared groups' name of the logged user.
+ */
+ public static List<String> getSharedGroups(Connection connection) throws XMPPException {
+ // Discover the shared groups of the logged user
+ SharedGroupsInfo info = new SharedGroupsInfo();
+ info.setType(IQ.Type.GET);
+
+ // Create a packet collector to listen for a response.
+ PacketCollector collector =
+ connection.createPacketCollector(new PacketIDFilter(info.getPacketID()));
+
+ connection.sendPacket(info);
+
+ // Wait up to 5 seconds for a result.
+ IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
+ // Stop queuing results
+ collector.cancel();
+ if (result == null) {
+ throw new XMPPException("No response from the server.");
+ }
+ if (result.getType() == IQ.Type.ERROR) {
+ throw new XMPPException(result.getError());
+ }
+ return ((SharedGroupsInfo) result).getGroups();
+ }
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamListener.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamListener.java
index be78255d5..87ab2f5ee 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamListener.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamListener.java
@@ -1,47 +1,47 @@
-/**
- * All rights reserved. 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 org.jivesoftware.smackx.bytestreams;
-
-import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamListener;
-import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager;
-import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamListener;
-import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamManager;
-
-/**
- * BytestreamListener are notified if a remote user wants to initiate a bytestream. Implement this
- * interface to handle incoming bytestream requests.
- * <p>
- * BytestreamListener can be registered at the {@link Socks5BytestreamManager} or the
- * {@link InBandBytestreamManager}.
- * <p>
- * There are two ways to add this listener. See
- * {@link BytestreamManager#addIncomingBytestreamListener(BytestreamListener)} and
- * {@link BytestreamManager#addIncomingBytestreamListener(BytestreamListener, String)} for further
- * details.
- * <p>
- * {@link Socks5BytestreamListener} or {@link InBandBytestreamListener} provide a more specific
- * interface of the BytestreamListener.
- *
- * @author Henning Staib
- */
-public interface BytestreamListener {
-
- /**
- * This listener is notified if a bytestream request from another user has been received.
- *
- * @param request the incoming bytestream request
- */
- public void incomingBytestreamRequest(BytestreamRequest request);
-
-}
+/**
+ * All rights reserved. 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 org.jivesoftware.smackx.bytestreams;
+
+import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamListener;
+import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager;
+import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamListener;
+import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamManager;
+
+/**
+ * BytestreamListener are notified if a remote user wants to initiate a bytestream. Implement this
+ * interface to handle incoming bytestream requests.
+ * <p>
+ * BytestreamListener can be registered at the {@link Socks5BytestreamManager} or the
+ * {@link InBandBytestreamManager}.
+ * <p>
+ * There are two ways to add this listener. See
+ * {@link BytestreamManager#addIncomingBytestreamListener(BytestreamListener)} and
+ * {@link BytestreamManager#addIncomingBytestreamListener(BytestreamListener, String)} for further
+ * details.
+ * <p>
+ * {@link Socks5BytestreamListener} or {@link InBandBytestreamListener} provide a more specific
+ * interface of the BytestreamListener.
+ *
+ * @author Henning Staib
+ */
+public interface BytestreamListener {
+
+ /**
+ * This listener is notified if a bytestream request from another user has been received.
+ *
+ * @param request the incoming bytestream request
+ */
+ public void incomingBytestreamRequest(BytestreamRequest request);
+
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamManager.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamManager.java
index ca6bbc602..232af2a2a 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamManager.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamManager.java
@@ -1,114 +1,114 @@
-/**
- * All rights reserved. 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 org.jivesoftware.smackx.bytestreams;
-
-import java.io.IOException;
-
-import org.jivesoftware.smack.XMPPException;
-import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager;
-import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamManager;
-
-/**
- * BytestreamManager provides a generic interface for bytestream managers.
- * <p>
- * There are two implementations of the interface. See {@link Socks5BytestreamManager} and
- * {@link InBandBytestreamManager}.
- *
- * @author Henning Staib
- */
-public interface BytestreamManager {
-
- /**
- * Adds {@link BytestreamListener} that is called for every incoming bytestream request unless
- * there is a user specific {@link BytestreamListener} registered.
- * <p>
- * See {@link Socks5BytestreamManager#addIncomingBytestreamListener(BytestreamListener)} and
- * {@link InBandBytestreamManager#addIncomingBytestreamListener(BytestreamListener)} for further
- * details.
- *
- * @param listener the listener to register
- */
- public void addIncomingBytestreamListener(BytestreamListener listener);
-
- /**
- * Removes the given listener from the list of listeners for all incoming bytestream requests.
- *
- * @param listener the listener to remove
- */
- public void removeIncomingBytestreamListener(BytestreamListener listener);
-
- /**
- * Adds {@link BytestreamListener} that is called for every incoming bytestream request unless
- * there is a user specific {@link BytestreamListener} registered.
- * <p>
- * Use this method if you are awaiting an incoming bytestream request from a specific user.
- * <p>
- * See {@link Socks5BytestreamManager#addIncomingBytestreamListener(BytestreamListener, String)}
- * and {@link InBandBytestreamManager#addIncomingBytestreamListener(BytestreamListener, String)}
- * for further details.
- *
- * @param listener the listener to register
- * @param initiatorJID the JID of the user that wants to establish a bytestream
- */
- public void addIncomingBytestreamListener(BytestreamListener listener, String initiatorJID);
-
- /**
- * Removes the listener for the given user.
- *
- * @param initiatorJID the JID of the user the listener should be removed
- */
- public void removeIncomingBytestreamListener(String initiatorJID);
-
- /**
- * Establishes a bytestream with the given user and returns the session to send/receive data
- * to/from the user.
- * <p>
- * Use this method to establish bytestreams to users accepting all incoming bytestream requests
- * since this method doesn't provide a way to tell the user something about the data to be sent.
- * <p>
- * To establish a bytestream after negotiation the kind of data to be sent (e.g. file transfer)
- * use {@link #establishSession(String, String)}.
- * <p>
- * See {@link Socks5BytestreamManager#establishSession(String)} and
- * {@link InBandBytestreamManager#establishSession(String)} for further details.
- *
- * @param targetJID the JID of the user a bytestream should be established
- * @return the session to send/receive data to/from the user
- * @throws XMPPException if an error occurred while establishing the session
- * @throws IOException if an IO error occurred while establishing the session
- * @throws InterruptedException if the thread was interrupted while waiting in a blocking
- * operation
- */
- public BytestreamSession establishSession(String targetJID) throws XMPPException, IOException,
- InterruptedException;
-
- /**
- * Establishes a bytestream with the given user and returns the session to send/receive data
- * to/from the user.
- * <p>
- * See {@link Socks5BytestreamManager#establishSession(String)} and
- * {@link InBandBytestreamManager#establishSession(String)} for further details.
- *
- * @param targetJID the JID of the user a bytestream should be established
- * @param sessionID the session ID for the bytestream request
- * @return the session to send/receive data to/from the user
- * @throws XMPPException if an error occurred while establishing the session
- * @throws IOException if an IO error occurred while establishing the session
- * @throws InterruptedException if the thread was interrupted while waiting in a blocking
- * operation
- */
- public BytestreamSession establishSession(String targetJID, String sessionID)
- throws XMPPException, IOException, InterruptedException;
-
-}
+/**
+ * All rights reserved. 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 org.jivesoftware.smackx.bytestreams;
+
+import java.io.IOException;
+
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager;
+import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamManager;
+
+/**
+ * BytestreamManager provides a generic interface for bytestream managers.
+ * <p>
+ * There are two implementations of the interface. See {@link Socks5BytestreamManager} and
+ * {@link InBandBytestreamManager}.
+ *
+ * @author Henning Staib
+ */
+public interface BytestreamManager {
+
+ /**
+ * Adds {@link BytestreamListener} that is called for every incoming bytestream request unless
+ * there is a user specific {@link BytestreamListener} registered.
+ * <p>
+ * See {@link Socks5BytestreamManager#addIncomingBytestreamListener(BytestreamListener)} and
+ * {@link InBandBytestreamManager#addIncomingBytestreamListener(BytestreamListener)} for further
+ * details.
+ *
+ * @param listener the listener to register
+ */
+ public void addIncomingBytestreamListener(BytestreamListener listener);
+
+ /**
+ * Removes the given listener from the list of listeners for all incoming bytestream requests.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeIncomingBytestreamListener(BytestreamListener listener);
+
+ /**
+ * Adds {@link BytestreamListener} that is called for every incoming bytestream request unless
+ * there is a user specific {@link BytestreamListener} registered.
+ * <p>
+ * Use this method if you are awaiting an incoming bytestream request from a specific user.
+ * <p>
+ * See {@link Socks5BytestreamManager#addIncomingBytestreamListener(BytestreamListener, String)}
+ * and {@link InBandBytestreamManager#addIncomingBytestreamListener(BytestreamListener, String)}
+ * for further details.
+ *
+ * @param listener the listener to register
+ * @param initiatorJID the JID of the user that wants to establish a bytestream
+ */
+ public void addIncomingBytestreamListener(BytestreamListener listener, String initiatorJID);
+
+ /**
+ * Removes the listener for the given user.
+ *
+ * @param initiatorJID the JID of the user the listener should be removed
+ */
+ public void removeIncomingBytestreamListener(String initiatorJID);
+
+ /**
+ * Establishes a bytestream with the given user and returns the session to send/receive data
+ * to/from the user.
+ * <p>
+ * Use this method to establish bytestreams to users accepting all incoming bytestream requests
+ * since this method doesn't provide a way to tell the user something about the data to be sent.
+ * <p>
+ * To establish a bytestream after negotiation the kind of data to be sent (e.g. file transfer)
+ * use {@link #establishSession(String, String)}.
+ * <p>
+ * See {@link Socks5BytestreamManager#establishSession(String)} and
+ * {@link InBandBytestreamManager#establishSession(String)} for further details.
+ *
+ * @param targetJID the JID of the user a bytestream should be established
+ * @return the session to send/receive data to/from the user
+ * @throws XMPPException if an error occurred while establishing the session
+ * @throws IOException if an IO error occurred while establishing the session
+ * @throws InterruptedException if the thread was interrupted while waiting in a blocking
+ * operation
+ */
+ public BytestreamSession establishSession(String targetJID) throws XMPPException, IOException,
+ InterruptedException;
+
+ /**
+ * Establishes a bytestream with the given user and returns the session to send/receive data
+ * to/from the user.
+ * <p>
+ * See {@link Socks5BytestreamManager#establishSession(String)} and
+ * {@link InBandBytestreamManager#establishSession(String)} for further details.
+ *
+ * @param targetJID the JID of the user a bytestream should be established
+ * @param sessionID the session ID for the bytestream request
+ * @return the session to send/receive data to/from the user
+ * @throws XMPPException if an error occurred while establishing the session
+ * @throws IOException if an IO error occurred while establishing the session
+ * @throws InterruptedException if the thread was interrupted while waiting in a blocking
+ * operation
+ */
+ public BytestreamSession establishSession(String targetJID, String sessionID)
+ throws XMPPException, IOException, InterruptedException;
+
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamRequest.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamRequest.java
index e368bad99..e16474b0f 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamRequest.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamRequest.java
@@ -1,59 +1,59 @@
-/**
- * All rights reserved. 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 org.jivesoftware.smackx.bytestreams;
-
-import org.jivesoftware.smack.XMPPException;
-import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamRequest;
-import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamRequest;
-
-/**
- * BytestreamRequest provides an interface to handle incoming bytestream requests.
- * <p>
- * There are two implementations of the interface. See {@link Socks5BytestreamRequest} and
- * {@link InBandBytestreamRequest}.
- *
- * @author Henning Staib
- */
-public interface BytestreamRequest {
-
- /**
- * Returns the sender of the bytestream open request.
- *
- * @return the sender of the bytestream open request
- */
- public String getFrom();
-
- /**
- * Returns the session ID of the bytestream open request.
- *
- * @return the session ID of the bytestream open request
- */
- public String getSessionID();
-
- /**
- * Accepts the bytestream open request and returns the session to send/receive data.
- *
- * @return the session to send/receive data
- * @throws XMPPException if an error occurred while accepting the bytestream request
- * @throws InterruptedException if the thread was interrupted while waiting in a blocking
- * operation
- */
- public BytestreamSession accept() throws XMPPException, InterruptedException;
-
- /**
- * Rejects the bytestream request by sending a reject error to the initiator.
- */
- public void reject();
-
-}
+/**
+ * All rights reserved. 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 org.jivesoftware.smackx.bytestreams;
+
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamRequest;
+import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamRequest;
+
+/**
+ * BytestreamRequest provides an interface to handle incoming bytestream requests.
+ * <p>
+ * There are two implementations of the interface. See {@link Socks5BytestreamRequest} and
+ * {@link InBandBytestreamRequest}.
+ *
+ * @author Henning Staib
+ */
+public interface BytestreamRequest {
+
+ /**
+ * Returns the sender of the bytestream open request.
+ *
+ * @return the sender of the bytestream open request
+ */
+ public String getFrom();
+
+ /**
+ * Returns the session ID of the bytestream open request.
+ *
+ * @return the session ID of the bytestream open request
+ */
+ public String getSessionID();
+
+ /**
+ * Accepts the bytestream open request and returns the session to send/receive data.
+ *
+ * @return the session to send/receive data
+ * @throws XMPPException if an error occurred while accepting the bytestream request
+ * @throws InterruptedException if the thread was interrupted while waiting in a blocking
+ * operation
+ */
+ public BytestreamSession accept() throws XMPPException, InterruptedException;
+
+ /**
+ * Rejects the bytestream request by sending a reject error to the initiator.
+ */
+ public void reject();
+
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamSession.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamSession.java
index 7aafc3513..3041d77c7 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamSession.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/BytestreamSession.java
@@ -1,81 +1,81 @@
-/**
- * All rights reserved. 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 org.jivesoftware.smackx.bytestreams;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamSession;
-import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamSession;
-
-/**
- * BytestreamSession provides an interface for established bytestream sessions.
- * <p>
- * There are two implementations of the interface. See {@link Socks5BytestreamSession} and
- * {@link InBandBytestreamSession}.
- *
- * @author Henning Staib
- */
-public interface BytestreamSession {
-
- /**
- * Returns the InputStream associated with this session to send data.
- *
- * @return the InputStream associated with this session to send data
- * @throws IOException if an error occurs while retrieving the input stream
- */
- public InputStream getInputStream() throws IOException;
-
- /**
- * Returns the OutputStream associated with this session to receive data.
- *
- * @return the OutputStream associated with this session to receive data
- * @throws IOException if an error occurs while retrieving the output stream
- */
- public OutputStream getOutputStream() throws IOException;
-
- /**
- * Closes the bytestream session.
- * <p>
- * Closing the session will also close the input stream and the output stream associated to this
- * session.
- *
- * @throws IOException if an error occurs while closing the session
- */
- public void close() throws IOException;
-
- /**
- * Returns the timeout for read operations of the input stream associated with this session. 0
- * returns implies that the option is disabled (i.e., timeout of infinity). Default is 0.
- *
- * @return the timeout for read operations
- * @throws IOException if there is an error in the underlying protocol
- */
- public int getReadTimeout() throws IOException;
-
- /**
- * Sets the specified timeout, in milliseconds. With this option set to a non-zero timeout, a
- * read() call on the input stream associated with this session will block for only this amount
- * of time. If the timeout expires, a java.net.SocketTimeoutException is raised, though the
- * session is still valid. The option must be enabled prior to entering the blocking operation
- * to have effect. The timeout must be > 0. A timeout of zero is interpreted as an infinite
- * timeout. Default is 0.
- *
- * @param timeout the specified timeout, in milliseconds
- * @throws IOException if there is an error in the underlying protocol
- */
- public void setReadTimeout(int timeout) throws IOException;
-
-}
+/**
+ * All rights reserved. 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 org.jivesoftware.smackx.bytestreams;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamSession;
+import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamSession;
+
+/**
+ * BytestreamSession provides an interface for established bytestream sessions.
+ * <p>
+ * There are two implementations of the interface. See {@link Socks5BytestreamSession} and
+ * {@link InBandBytestreamSession}.
+ *
+ * @author Henning Staib
+ */
+public interface BytestreamSession {
+
+ /**
+ * Returns the InputStream associated with this session to send data.
+ *
+ * @return the InputStream associated with this session to send data
+ * @throws IOException if an error occurs while retrieving the input stream
+ */
+ public InputStream getInputStream() throws IOException;
+
+ /**
+ * Returns the OutputStream associated with this session to receive data.
+ *
+ * @return the OutputStream associated with this session to receive data
+ * @throws IOException if an error occurs while retrieving the output stream
+ */
+ public OutputStream getOutputStream() throws IOException;
+
+ /**
+ * Closes the bytestream session.
+ * <p>
+ * Closing the session will also close the input stream and the output stream associated to this
+ * session.
+ *
+ * @throws IOException if an error occurs while closing the session
+ */
+ public void close() throws IOException;
+
+ /**
+ * Returns the timeout for read operations of the input stream associated with this session. 0
+ * returns implies that the option is disabled (i.e., timeout of infinity). Default is 0.
+ *
+ * @return the timeout for read operations
+ * @throws IOException if there is an error in the underlying protocol
+ */
+ public int getReadTimeout() throws IOException;
+
+ /**
+ * Sets the specified timeout, in milliseconds. With this option set to a non-zero timeout, a
+ * read() call on the input stream associated with this session will block for only this amount
+ * of time. If the timeout expires, a java.net.SocketTimeoutException is raised, though the
+ * session is still valid. The option must be enabled prior to entering the blocking operation
+ * to have effect. The timeout must be > 0. A timeout of zero is interpreted as an infinite
+ * timeout. Default is 0.
+ *
+ * @param timeout the specified timeout, in milliseconds
+ * @throws IOException if there is an error in the underlying protocol
+ */
+ public void setReadTimeout(int timeout) throws IOException;
+
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/CloseListener.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/CloseListener.java
index 7690e9537..83ca51c51 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/CloseListener.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/CloseListener.java
@@ -1,75 +1,75 @@
-/**
- * All rights reserved. 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 org.jivesoftware.smackx.bytestreams.ibb;
-
-import org.jivesoftware.smack.PacketListener;
-import org.jivesoftware.smack.filter.AndFilter;
-import org.jivesoftware.smack.filter.IQTypeFilter;
-import org.jivesoftware.smack.filter.PacketFilter;
-import org.jivesoftware.smack.filter.PacketTypeFilter;
-import org.jivesoftware.smack.packet.IQ;
-import org.jivesoftware.smack.packet.Packet;
-import org.jivesoftware.smackx.bytestreams.ibb.packet.Close;
-
-/**
- * CloseListener handles all In-Band Bytestream close requests.
- * <p>
- * If a close request is received it looks if a stored In-Band Bytestream
- * session exists and closes it. If no session with the given session ID exists
- * an &lt;item-not-found/&gt; error is returned to the sender.
- *
- * @author Henning Staib
- */
-class CloseListener implements PacketListener {
-
- /* manager containing the listeners and the XMPP connection */
- private final InBandBytestreamManager manager;
-
- /* packet filter for all In-Band Bytestream close requests */
- private final PacketFilter closeFilter = new AndFilter(new PacketTypeFilter(
- Close.class), new IQTypeFilter(IQ.Type.SET));
-
- /**
- * Constructor.
- *
- * @param manager the In-Band Bytestream manager
- */
- protected CloseListener(InBandBytestreamManager manager) {
- this.manager = manager;
- }
-
- public void processPacket(Packet packet) {
- Close closeRequest = (Close) packet;
- InBandBytestreamSession ibbSession = this.manager.getSessions().get(
- closeRequest.getSessionID());
- if (ibbSession == null) {
- this.manager.replyItemNotFoundPacket(closeRequest);
- }
- else {
- ibbSession.closeByPeer(closeRequest);
- this.manager.getSessions().remove(closeRequest.getSessionID());
- }
-
- }
-
- /**
- * Returns the packet filter for In-Band Bytestream close requests.
- *
- * @return the packet filter for In-Band Bytestream close requests
- */
- protected PacketFilter getFilter() {
- return this.closeFilter;
- }
-
-}
+/**
+ * All rights reserved. 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 org.jivesoftware.smackx.bytestreams.ibb;
+
+import org.jivesoftware.smack.PacketListener;
+import org.jivesoftware.smack.filter.AndFilter;
+import org.jivesoftware.smack.filter.IQTypeFilter;
+import org.jivesoftware.smack.filter.PacketFilter;
+import org.jivesoftware.smack.filter.PacketTypeFilter;
+import org.jivesoftware.smack.packet.IQ;
+import org.jivesoftware.smack.packet.Packet;
+import org.jivesoftware.smackx.bytestreams.ibb.packet.Close;
+
+/**
+ * CloseListener handles all In-Band Bytestream close requests.
+ * <p>
+ * If a close request is received it looks if a stored In-Band Bytestream
+ * session exists and closes it. If no session with the given session ID exists
+ * an &lt;item-not-found/&gt; error is returned to the sender.
+ *
+ * @author Henning Staib
+ */
+class CloseListener implements PacketListener {
+
+ /* manager containing the listeners and the XMPP connection */
+ private final InBandBytestreamManager manager;
+
+ /* packet filter for all In-Band Bytestream close requests */
+ private final PacketFilter closeFilter = new AndFilter(new PacketTypeFilter(
+ Close.class), new IQTypeFilter(IQ.Type.SET));
+
+ /**
+ * Constructor.
+ *
+ * @param manager the In-Band Bytestream manager
+ */
+ protected CloseListener(InBandBytestreamManager manager) {
+ this.manager = manager;
+ }
+
+ public void processPacket(Packet packet) {
+ Close closeRequest = (Close) packet;
+ InBandBytestreamSession ibbSession = this.manager.getSessions().get(
+ closeRequest.getSessionID());
+ if (ibbSession == null) {
+ this.manager.replyItemNotFoundPacket(closeRequest);
+ }
+ else {
+ ibbSession.closeByPeer(closeRequest);
+ this.manager.getSessions().remove(closeRequest.getSessionID());
+ }
+
+ }
+
+ /**
+ * Returns the packet filter for In-Band Bytestream close requests.
+ *
+ * @return the packet filter for In-Band Bytestream close requests
+ */
+ protected PacketFilter getFilter() {
+ return this.closeFilter;
+ }
+
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/DataListener.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/DataListener.java
index 166c14647..6ef759c5d 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/DataListener.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/DataListener.java
@@ -1,73 +1,73 @@
-/**
- * All rights reserved. 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 org.jivesoftware.smackx.bytestreams.ibb;
-
-import org.jivesoftware.smack.PacketListener;
-import org.jivesoftware.smack.filter.AndFilter;
-import org.jivesoftware.smack.filter.PacketFilter;
-import org.jivesoftware.smack.filter.PacketTypeFilter;
-import org.jivesoftware.smack.packet.Packet;
-import org.jivesoftware.smackx.bytestreams.ibb.packet.Data;
-
-/**
- * DataListener handles all In-Band Bytestream IQ stanzas containing a data
- * packet extension that don't belong to an existing session.
- * <p>
- * If a data packet is received it looks if a stored In-Band Bytestream session
- * exists. If no session with the given session ID exists an
- * &lt;item-not-found/&gt; error is returned to the sender.
- * <p>
- * Data packets belonging to a running In-Band Bytestream session are processed
- * by more specific listeners registered when an {@link InBandBytestreamSession}
- * is created.
- *
- * @author Henning Staib
- */
-class DataListener implements PacketListener {
-
- /* manager containing the listeners and the XMPP connection */
- private final InBandBytestreamManager manager;
-
- /* packet filter for all In-Band Bytestream data packets */
- private final PacketFilter dataFilter = new AndFilter(
- new PacketTypeFilter(Data.class));
-
- /**
- * Constructor.
- *
- * @param manager the In-Band Bytestream manager
- */
- public DataListener(InBandBytestreamManager manager) {
- this.manager = manager;
- }
-
- public void processPacket(Packet packet) {
- Data data = (Data) packet;
- InBandBytestreamSession ibbSession = this.manager.getSessions().get(
- data.getDataPacketExtension().getSessionID());
- if (ibbSession == null) {
- this.manager.replyItemNotFoundPacket(data);
- }
- }
-
- /**
- * Returns the packet filter for In-Band Bytestream data packets.
- *
- * @return the packet filter for In-Band Bytestream data packets
- */
- protected PacketFilter getFilter() {
- return this.dataFilter;
- }
-
-}
+/**
+ * All rights reserved. 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 org.jivesoftware.smackx.bytestreams.ibb;
+
+import org.jivesoftware.smack.PacketListener;
+import org.jivesoftware.smack.filter.AndFilter;
+import org.jivesoftware.smack.filter.PacketFilter;
+import org.jivesoftware.smack.filter.PacketTypeFilter;
+import org.jivesoftware.smack.packet.Packet;
+import org.jivesoftware.smackx.bytestreams.ibb.packet.Data;
+
+/**
+ * DataListener handles all In-Band Bytestream IQ stanzas containing a data
+ * packet extension that don't belong to an existing session.
+ * <p>
+ * If a data packet is received it looks if a stored In-Band Bytestream session
+ * exists. If no session with the given session ID exists an
+ * &lt;item-not-found/&gt; error is returned to the sender.
+ * <p>
+ * Data packets belonging to a running In-Band Bytestream session are processed
+ * by more specific listeners registered when an {@link InBandBytestreamSession}
+ * is created.
+ *
+ * @author Henning Staib
+ */
+class DataListener implements PacketListener {
+
+ /* manager containing the listeners and the XMPP connection */
+ private final InBandBytestreamManager manager;
+
+ /* packet filter for all In-Band Bytestream data packets */
+ private final PacketFilter dataFilter = new AndFilter(
+ new PacketTypeFilter(Data.class));
+
+ /**
+ * Constructor.
+ *
+ * @param manager the In-Band Bytestream manager
+ */
+ public DataListener(InBandBytestreamManager manager) {
+ this.manager = manager;
+ }
+
+ public void processPacket(Packet packet) {
+ Data data = (Data) packet;
+ InBandBytestreamSession ibbSession = this.manager.getSessions().get(
+ data.getDataPacketExtension().getSessionID());
+ if (ibbSession == null) {
+ this.manager.replyItemNotFoundPacket(data);
+ }
+ }
+
+ /**
+ * Returns the packet filter for In-Band Bytestream data packets.
+ *
+ * @return the packet filter for In-Band Bytestream data packets
+ */
+ protected PacketFilter getFilter() {
+ return this.dataFilter;
+ }
+
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamListener.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamListener.java
index 68791a6f3..6c84013c2 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamListener.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamListener.java
@@ -1,46 +1,46 @@
-/**
- * All rights reserved. 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 org.jivesoftware.smackx.bytestreams.ibb;
-
-import org.jivesoftware.smackx.bytestreams.BytestreamListener;
-import org.jivesoftware.smackx.bytestreams.BytestreamRequest;
-
-/**
- * InBandBytestreamListener are informed if a remote user wants to initiate an In-Band Bytestream.
- * Implement this interface to handle incoming In-Band Bytestream requests.
- * <p>
- * There are two ways to add this listener. See
- * {@link InBandBytestreamManager#addIncomingBytestreamListener(BytestreamListener)} and
- * {@link InBandBytestreamManager#addIncomingBytestreamListener(BytestreamListener, String)} for
- * further details.
- *
- * @author Henning Staib
- */
-public abstract class InBandBytestreamListener implements BytestreamListener {
-
-
-
- public void incomingBytestreamRequest(BytestreamRequest request) {
- incomingBytestreamRequest((InBandBytestreamRequest) request);
- }
-
- /**
- * This listener is notified if an In-Band Bytestream request from another user has been
- * received.
- *
- * @param request the incoming In-Band Bytestream request
- */
- public abstract void incomingBytestreamRequest(InBandBytestreamRequest request);
-
-}
+/**
+ * All rights reserved. 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 org.jivesoftware.smackx.bytestreams.ibb;
+
+import org.jivesoftware.smackx.bytestreams.BytestreamListener;
+import org.jivesoftware.smackx.bytestreams.BytestreamRequest;
+
+/**
+ * InBandBytestreamListener are informed if a remote user wants to initiate an In-Band Bytestream.
+ * Implement this interface to handle incoming In-Band Bytestream requests.
+ * <p>
+ * There are two ways to add this listener. See
+ * {@link InBandBytestreamManager#addIncomingBytestreamListener(BytestreamListener)} and
+ * {@link InBandBytestreamManager#addIncomingBytestreamListener(BytestreamListener, String)} for
+ * further details.
+ *
+ * @author Henning Staib
+ */
+public abstract class InBandBytestreamListener implements BytestreamListener {
+
+
+
+ public void incomingBytestreamRequest(BytestreamRequest request) {
+ incomingBytestreamRequest((InBandBytestreamRequest) request);
+ }
+
+ /**
+ * This listener is notified if an In-Band Bytestream request from another user has been
+ * received.
+ *
+ * @param request the incoming In-Band Bytestream request
+ */
+ public abstract void incomingBytestreamRequest(InBandBytestreamRequest request);
+
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamManager.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamManager.java
index ef5253154..a4f3592e1 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamManager.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamManager.java
@@ -1,546 +1,546 @@
-/**
- * All rights reserved. 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 org.jivesoftware.smackx.bytestreams.ibb;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.jivesoftware.smack.AbstractConnectionListener;
-import org.jivesoftware.smack.Connection;
-import org.jivesoftware.smack.ConnectionCreationListener;
-import org.jivesoftware.smack.XMPPException;
-import org.jivesoftware.smack.packet.IQ;
-import org.jivesoftware.smack.packet.XMPPError;
-import org.jivesoftware.smack.util.SyncPacketSend;
-import org.jivesoftware.smackx.bytestreams.BytestreamListener;
-import org.jivesoftware.smackx.bytestreams.BytestreamManager;
-import org.jivesoftware.smackx.bytestreams.ibb.packet.Open;
-import org.jivesoftware.smackx.filetransfer.FileTransferManager;
-
-/**
- * The InBandBytestreamManager class handles establishing In-Band Bytestreams as specified in the <a
- * href="http://xmpp.org/extensions/xep-0047.html">XEP-0047</a>.
- * <p>
- * The In-Band Bytestreams (IBB) enables two entities to establish a virtual bytestream over which
- * they can exchange Base64-encoded chunks of data over XMPP itself. It is the fall-back mechanism
- * in case the Socks5 bytestream method of transferring data is not available.
- * <p>
- * There are two ways to send data over an In-Band Bytestream. It could either use IQ stanzas to
- * send data packets or message stanzas. If IQ stanzas are used every data packet is acknowledged by
- * the receiver. This is the recommended way to avoid possible rate-limiting penalties. Message
- * stanzas are not acknowledged because most XMPP server implementation don't support stanza
- * flow-control method like <a href="http://xmpp.org/extensions/xep-0079.html">Advanced Message
- * Processing</a>. To set the stanza that should be used invoke {@link #setStanza(StanzaType)}.
- * <p>
- * To establish an In-Band Bytestream invoke the {@link #establishSession(String)} method. This will
- * negotiate an in-band bytestream with the given target JID and return a session.
- * <p>
- * If a session ID for the In-Band Bytestream was already negotiated (e.g. while negotiating a file
- * transfer) invoke {@link #establishSession(String, String)}.
- * <p>
- * To handle incoming In-Band Bytestream requests add an {@link InBandBytestreamListener} to the
- * manager. There are two ways to add this listener. If you want to be informed about incoming
- * In-Band Bytestreams from a specific user add the listener by invoking
- * {@link #addIncomingBytestreamListener(BytestreamListener, String)}. If the listener should
- * respond to all In-Band Bytestream requests invoke
- * {@link #addIncomingBytestreamListener(BytestreamListener)}.
- * <p>
- * Note that the registered {@link InBandBytestreamListener} will NOT be notified on incoming
- * In-Band bytestream requests sent in the context of <a
- * href="http://xmpp.org/extensions/xep-0096.html">XEP-0096</a> file transfer. (See
- * {@link FileTransferManager})
- * <p>
- * If no {@link InBandBytestreamListener}s are registered, all incoming In-Band bytestream requests
- * will be rejected by returning a &lt;not-acceptable/&gt; error to the initiator.
- *
- * @author Henning Staib
- */
-public class InBandBytestreamManager implements BytestreamManager {
-
- /**
- * Stanzas that can be used to encapsulate In-Band Bytestream data packets.
- */
- public enum StanzaType {
-
- /**
- * IQ stanza.
- */
- IQ,
-
- /**
- * Message stanza.
- */
- MESSAGE
- }
-
- /*
- * create a new InBandBytestreamManager and register its shutdown listener on every established
- * connection
- */
- static {
- Connection.addConnectionCreationListener(new ConnectionCreationListener() {
- public void connectionCreated(Connection connection) {
- final InBandBytestreamManager manager;
- manager = InBandBytestreamManager.getByteStreamManager(connection);
-
- // register shutdown listener
- connection.addConnectionListener(new AbstractConnectionListener() {
-
- public void connectionClosed() {
- manager.disableService();
- }
-
- });
-
- }
- });
- }
-
- /**
- * The XMPP namespace of the In-Band Bytestream
- */
- public static final String NAMESPACE = "http://jabber.org/protocol/ibb";
-
- /**
- * Maximum block size that is allowed for In-Band Bytestreams
- */
- public static final int MAXIMUM_BLOCK_SIZE = 65535;
-
- /* prefix used to generate session IDs */
- private static final String SESSION_ID_PREFIX = "jibb_";
-
- /* random generator to create session IDs */
- private final static Random randomGenerator = new Random();
-
- /* stores one InBandBytestreamManager for each XMPP connection */
- private final static Map<Connection, InBandBytestreamManager> managers = new HashMap<Connection, InBandBytestreamManager>();
-
- /* XMPP connection */
- private final Connection connection;
-
- /*
- * assigns a user to a listener that is informed if an In-Band Bytestream request for this user
- * is received
- */
- private final Map<String, BytestreamListener> userListeners = new ConcurrentHashMap<String, BytestreamListener>();
-
- /*
- * list of listeners that respond to all In-Band Bytestream requests if there are no user
- * specific listeners for that request
- */
- private final List<BytestreamListener> allRequestListeners = Collections.synchronizedList(new LinkedList<BytestreamListener>());
-
- /* listener that handles all incoming In-Band Bytestream requests */
- private final InitiationListener initiationListener;
-
- /* listener that handles all incoming In-Band Bytestream IQ data packets */
- private final DataListener dataListener;
-
- /* listener that handles all incoming In-Band Bytestream close requests */
- private final CloseListener closeListener;
-
- /* assigns a session ID to the In-Band Bytestream session */
- private final Map<String, InBandBytestreamSession> sessions = new ConcurrentHashMap<String, InBandBytestreamSession>();
-
- /* block size used for new In-Band Bytestreams */
- private int defaultBlockSize = 4096;
-
- /* maximum block size allowed for this connection */
- private int maximumBlockSize = MAXIMUM_BLOCK_SIZE;
-
- /* the stanza used to send data packets */
- private StanzaType stanza = StanzaType.IQ;
-
- /*
- * list containing session IDs of In-Band Bytestream open packets that should be ignored by the
- * InitiationListener
- */
- private List<String> ignoredBytestreamRequests = Collections.synchronizedList(new LinkedList<String>());
-
- /**
- * Returns the InBandBytestreamManager to handle In-Band Bytestreams for a given
- * {@link Connection}.
- *
- * @param connection the XMPP connection
- * @return the InBandBytestreamManager for the given XMPP connection
- */
- public static synchronized InBandBytestreamManager getByteStreamManager(Connection connection) {
- if (connection == null)
- return null;
- InBandBytestreamManager manager = managers.get(connection);
- if (manager == null) {
- manager = new InBandBytestreamManager(connection);
- managers.put(connection, manager);
- }
- return manager;
- }
-
- /**
- * Constructor.
- *
- * @param connection the XMPP connection
- */
- private InBandBytestreamManager(Connection connection) {
- this.connection = connection;
-
- // register bytestream open packet listener
- this.initiationListener = new InitiationListener(this);
- this.connection.addPacketListener(this.initiationListener,
- this.initiationListener.getFilter());
-
- // register bytestream data packet listener
- this.dataListener = new DataListener(this);
- this.connection.addPacketListener(this.dataListener, this.dataListener.getFilter());
-
- // register bytestream close packet listener
- this.closeListener = new CloseListener(this);
- this.connection.addPacketListener(this.closeListener, this.closeListener.getFilter());
-
- }
-
- /**
- * Adds InBandBytestreamListener that is called for every incoming in-band bytestream request
- * unless there is a user specific InBandBytestreamListener registered.
- * <p>
- * If no listeners are registered all In-Band Bytestream request are rejected with a
- * &lt;not-acceptable/&gt; error.
- * <p>
- * Note that the registered {@link InBandBytestreamListener} will NOT be notified on incoming
- * Socks5 bytestream requests sent in the context of <a
- * href="http://xmpp.org/extensions/xep-0096.html">XEP-0096</a> file transfer. (See
- * {@link FileTransferManager})
- *
- * @param listener the listener to register
- */
- public void addIncomingBytestreamListener(BytestreamListener listener) {
- this.allRequestListeners.add(listener);
- }
-
- /**
- * Removes the given listener from the list of listeners for all incoming In-Band Bytestream
- * requests.
- *
- * @param listener the listener to remove
- */
- public void removeIncomingBytestreamListener(BytestreamListener listener) {
- this.allRequestListeners.remove(listener);
- }
-
- /**
- * Adds InBandBytestreamListener that is called for every incoming in-band bytestream request
- * from the given user.
- * <p>
- * Use this method if you are awaiting an incoming Socks5 bytestream request from a specific
- * user.
- * <p>
- * If no listeners are registered all In-Band Bytestream request are rejected with a
- * &lt;not-acceptable/&gt; error.
- * <p>
- * Note that the registered {@link InBandBytestreamListener} will NOT be notified on incoming
- * Socks5 bytestream requests sent in the context of <a
- * href="http://xmpp.org/extensions/xep-0096.html">XEP-0096</a> file transfer. (See
- * {@link FileTransferManager})
- *
- * @param listener the listener to register
- * @param initiatorJID the JID of the user that wants to establish an In-Band Bytestream
- */
- public void addIncomingBytestreamListener(BytestreamListener listener, String initiatorJID) {
- this.userListeners.put(initiatorJID, listener);
- }
-
- /**
- * Removes the listener for the given user.
- *
- * @param initiatorJID the JID of the user the listener should be removed
- */
- public void removeIncomingBytestreamListener(String initiatorJID) {
- this.userListeners.remove(initiatorJID);
- }
-
- /**
- * Use this method to ignore the next incoming In-Band Bytestream request containing the given
- * session ID. No listeners will be notified for this request and and no error will be returned
- * to the initiator.
- * <p>
- * This method should be used if you are awaiting an In-Band Bytestream request as a reply to
- * another packet (e.g. file transfer).
- *
- * @param sessionID to be ignored
- */
- public void ignoreBytestreamRequestOnce(String sessionID) {
- this.ignoredBytestreamRequests.add(sessionID);
- }
-
- /**
- * Returns the default block size that is used for all outgoing in-band bytestreams for this
- * connection.
- * <p>
- * The recommended default block size is 4096 bytes. See <a
- * href="http://xmpp.org/extensions/xep-0047.html#usage">XEP-0047</a> Section 5.
- *
- * @return the default block size
- */
- public int getDefaultBlockSize() {
- return defaultBlockSize;
- }
-
- /**
- * Sets the default block size that is used for all outgoing in-band bytestreams for this
- * connection.
- * <p>
- * The default block size must be between 1 and 65535 bytes. The recommended default block size
- * is 4096 bytes. See <a href="http://xmpp.org/extensions/xep-0047.html#usage">XEP-0047</a>
- * Section 5.
- *
- * @param defaultBlockSize the default block size to set
- */
- public void setDefaultBlockSize(int defaultBlockSize) {
- if (defaultBlockSize <= 0 || defaultBlockSize > MAXIMUM_BLOCK_SIZE) {
- throw new IllegalArgumentException("Default block size must be between 1 and "
- + MAXIMUM_BLOCK_SIZE);
- }
- this.defaultBlockSize = defaultBlockSize;
- }
-
- /**
- * Returns the maximum block size that is allowed for In-Band Bytestreams for this connection.
- * <p>
- * Incoming In-Band Bytestream open request will be rejected with an
- * &lt;resource-constraint/&gt; error if the block size is greater then the maximum allowed
- * block size.
- * <p>
- * The default maximum block size is 65535 bytes.
- *
- * @return the maximum block size
- */
- public int getMaximumBlockSize() {
- return maximumBlockSize;
- }
-
- /**
- * Sets the maximum block size that is allowed for In-Band Bytestreams for this connection.
- * <p>
- * The maximum block size must be between 1 and 65535 bytes.
- * <p>
- * Incoming In-Band Bytestream open request will be rejected with an
- * &lt;resource-constraint/&gt; error if the block size is greater then the maximum allowed
- * block size.
- *
- * @param maximumBlockSize the maximum block size to set
- */
- public void setMaximumBlockSize(int maximumBlockSize) {
- if (maximumBlockSize <= 0 || maximumBlockSize > MAXIMUM_BLOCK_SIZE) {
- throw new IllegalArgumentException("Maximum block size must be between 1 and "
- + MAXIMUM_BLOCK_SIZE);
- }
- this.maximumBlockSize = maximumBlockSize;
- }
-
- /**
- * Returns the stanza used to send data packets.
- * <p>
- * Default is {@link StanzaType#IQ}. See <a
- * href="http://xmpp.org/extensions/xep-0047.html#message">XEP-0047</a> Section 4.
- *
- * @return the stanza used to send data packets
- */
- public StanzaType getStanza() {
- return stanza;
- }
-
- /**
- * Sets the stanza used to send data packets.
- * <p>
- * The use of {@link StanzaType#IQ} is recommended. See <a
- * href="http://xmpp.org/extensions/xep-0047.html#message">XEP-0047</a> Section 4.
- *
- * @param stanza the stanza to set
- */
- public void setStanza(StanzaType stanza) {
- this.stanza = stanza;
- }
-
- /**
- * Establishes an In-Band Bytestream with the given user and returns the session to send/receive
- * data to/from the user.
- * <p>
- * Use this method to establish In-Band Bytestreams to users accepting all incoming In-Band
- * Bytestream requests since this method doesn't provide a way to tell the user something about
- * the data to be sent.
- * <p>
- * To establish an In-Band Bytestream after negotiation the kind of data to be sent (e.g. file
- * transfer) use {@link #establishSession(String, String)}.
- *
- * @param targetJID the JID of the user an In-Band Bytestream should be established
- * @return the session to send/receive data to/from the user
- * @throws XMPPException if the user doesn't support or accept in-band bytestreams, or if the
- * user prefers smaller block sizes
- */
- public InBandBytestreamSession establishSession(String targetJID) throws XMPPException {
- String sessionID = getNextSessionID();
- return establishSession(targetJID, sessionID);
- }
-
- /**
- * Establishes an In-Band Bytestream with the given user using the given session ID and returns
- * the session to send/receive data to/from the user.
- *
- * @param targetJID the JID of the user an In-Band Bytestream should be established
- * @param sessionID the session ID for the In-Band Bytestream request
- * @return the session to send/receive data to/from the user
- * @throws XMPPException if the user doesn't support or accept in-band bytestreams, or if the
- * user prefers smaller block sizes
- */
- public InBandBytestreamSession establishSession(String targetJID, String sessionID)
- throws XMPPException {
- Open byteStreamRequest = new Open(sessionID, this.defaultBlockSize, this.stanza);
- byteStreamRequest.setTo(targetJID);
-
- // sending packet will throw exception on timeout or error reply
- SyncPacketSend.getReply(this.connection, byteStreamRequest);
-
- InBandBytestreamSession inBandBytestreamSession = new InBandBytestreamSession(
- this.connection, byteStreamRequest, targetJID);
- this.sessions.put(sessionID, inBandBytestreamSession);
-
- return inBandBytestreamSession;
- }
-
- /**
- * Responses to the given IQ packet's sender with an XMPP error that an In-Band Bytestream is
- * not accepted.
- *
- * @param request IQ packet that should be answered with a not-acceptable error
- */
- protected void replyRejectPacket(IQ request) {
- XMPPError xmppError = new XMPPError(XMPPError.Condition.no_acceptable);
- IQ error = IQ.createErrorResponse(request, xmppError);
- this.connection.sendPacket(error);
- }
-
- /**
- * Responses to the given IQ packet's sender with an XMPP error that an In-Band Bytestream open
- * request is rejected because its block size is greater than the maximum allowed block size.
- *
- * @param request IQ packet that should be answered with a resource-constraint error
- */
- protected void replyResourceConstraintPacket(IQ request) {
- XMPPError xmppError = new XMPPError(XMPPError.Condition.resource_constraint);
- IQ error = IQ.createErrorResponse(request, xmppError);
- this.connection.sendPacket(error);
- }
-
- /**
- * Responses to the given IQ packet's sender with an XMPP error that an In-Band Bytestream
- * session could not be found.
- *
- * @param request IQ packet that should be answered with a item-not-found error
- */
- protected void replyItemNotFoundPacket(IQ request) {
- XMPPError xmppError = new XMPPError(XMPPError.Condition.item_not_found);
- IQ error = IQ.createErrorResponse(request, xmppError);
- this.connection.sendPacket(error);
- }
-
- /**
- * Returns a new unique session ID.
- *
- * @return a new unique session ID
- */
- private String getNextSessionID() {
- StringBuilder buffer = new StringBuilder();
- buffer.append(SESSION_ID_PREFIX);
- buffer.append(Math.abs(randomGenerator.nextLong()));
- return buffer.toString();
- }
-
- /**
- * Returns the XMPP connection.
- *
- * @return the XMPP connection
- */
- protected Connection getConnection() {
- return this.connection;
- }
-
- /**
- * Returns the {@link InBandBytestreamListener} that should be informed if a In-Band Bytestream
- * request from the given initiator JID is received.
- *
- * @param initiator the initiator's JID
- * @return the listener
- */
- protected BytestreamListener getUserListener(String initiator) {
- return this.userListeners.get(initiator);
- }
-
- /**
- * Returns a list of {@link InBandBytestreamListener} that are informed if there are no
- * listeners for a specific initiator.
- *
- * @return list of listeners
- */
- protected List<BytestreamListener> getAllRequestListeners() {
- return this.allRequestListeners;
- }
-
- /**
- * Returns the sessions map.
- *
- * @return the sessions map
- */
- protected Map<String, InBandBytestreamSession> getSessions() {
- return sessions;
- }
-
- /**
- * Returns the list of session IDs that should be ignored by the InitialtionListener
- *
- * @return list of session IDs
- */
- protected List<String> getIgnoredBytestreamRequests() {
- return ignoredBytestreamRequests;
- }
-
- /**
- * Disables the InBandBytestreamManager by removing its packet listeners and resetting its
- * internal status.
- */
- private void disableService() {
-
- // remove manager from static managers map
- managers.remove(connection);
-
- // remove all listeners registered by this manager
- this.connection.removePacketListener(this.initiationListener);
- this.connection.removePacketListener(this.dataListener);
- this.connection.removePacketListener(this.closeListener);
-
- // shutdown threads
- this.initiationListener.shutdown();
-
- // reset internal status
- this.userListeners.clear();
- this.allRequestListeners.clear();
- this.sessions.clear();
- this.ignoredBytestreamRequests.clear();
-
- }
-
-}
+/**
+ * All rights reserved. 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 org.jivesoftware.smackx.bytestreams.ibb;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.jivesoftware.smack.AbstractConnectionListener;
+import org.jivesoftware.smack.Connection;
+import org.jivesoftware.smack.ConnectionCreationListener;
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smack.packet.IQ;
+import org.jivesoftware.smack.packet.XMPPError;
+import org.jivesoftware.smack.util.SyncPacketSend;
+import org.jivesoftware.smackx.bytestreams.BytestreamListener;
+import org.jivesoftware.smackx.bytestreams.BytestreamManager;
+import org.jivesoftware.smackx.bytestreams.ibb.packet.Open;
+import org.jivesoftware.smackx.filetransfer.FileTransferManager;
+
+/**
+ * The InBandBytestreamManager class handles establishing In-Band Bytestreams as specified in the <a
+ * href="http://xmpp.org/extensions/xep-0047.html">XEP-0047</a>.
+ * <p>
+ * The In-Band Bytestreams (IBB) enables two entities to establish a virtual bytestream over which
+ * they can exchange Base64-encoded chunks of data over XMPP itself. It is the fall-back mechanism
+ * in case the Socks5 bytestream method of transferring data is not available.
+ * <p>
+ * There are two ways to send data over an In-Band Bytestream. It could either use IQ stanzas to
+ * send data packets or message stanzas. If IQ stanzas are used every data packet is acknowledged by
+ * the receiver. This is the recommended way to avoid possible rate-limiting penalties. Message
+ * stanzas are not acknowledged because most XMPP server implementation don't support stanza
+ * flow-control method like <a href="http://xmpp.org/extensions/xep-0079.html">Advanced Message
+ * Processing</a>. To set the stanza that should be used invoke {@link #setStanza(StanzaType)}.
+ * <p>
+ * To establish an In-Band Bytestream invoke the {@link #establishSession(String)} method. This will
+ * negotiate an in-band bytestream with the given target JID and return a session.
+ * <p>
+ * If a session ID for the In-Band Bytestream was already negotiated (e.g. while negotiating a file
+ * transfer) invoke {@link #establishSession(String, String)}.
+ * <p>
+ * To handle incoming In-Band Bytestream requests add an {@link InBandBytestreamListener} to the
+ * manager. There are two ways to add this listener. If you want to be informed about incoming
+ * In-Band Bytestreams from a specific user add the listener by invoking
+ * {@link #addIncomingBytestreamListener(BytestreamListener, String)}. If the listener should
+ * respond to all In-Band Bytestream requests invoke
+ * {@link #addIncomingBytestreamListener(BytestreamListener)}.
+ * <p>
+ * Note that the registered {@link InBandBytestreamListener} will NOT be notified on incoming
+ * In-Band bytestream requests sent in the context of <a
+ * href="http://xmpp.org/extensions/xep-0096.html">XEP-0096</a> file transfer. (See
+ * {@link FileTransferManager})
+ * <p>
+ * If no {@link InBandBytestreamListener}s are registered, all incoming In-Band bytestream requests
+ * will be rejected by returning a &lt;not-acceptable/&gt; error to the initiator.
+ *
+ * @author Henning Staib
+ */
+public class InBandBytestreamManager implements BytestreamManager {
+
+ /**
+ * Stanzas that can be used to encapsulate In-Band Bytestream data packets.
+ */
+ public enum StanzaType {
+
+ /**
+ * IQ stanza.
+ */
+ IQ,
+
+ /**
+ * Message stanza.
+ */
+ MESSAGE
+ }
+
+ /*
+ * create a new InBandBytestreamManager and register its shutdown listener on every established
+ * connection
+ */
+ static {
+ Connection.addConnectionCreationListener(new ConnectionCreationListener() {
+ public void connectionCreated(Connection connection) {
+ final InBandBytestreamManager manager;
+ manager = InBandBytestreamManager.getByteStreamManager(connection);
+
+ // register shutdown listener
+ connection.addConnectionListener(new AbstractConnectionListener() {
+
+ public void connectionClosed() {
+ manager.disableService();
+ }
+
+ });
+
+ }
+ });
+ }
+
+ /**
+ * The XMPP namespace of the In-Band Bytestream
+ */
+ public static final String NAMESPACE = "http://jabber.org/protocol/ibb";
+
+ /**
+ * Maximum block size that is allowed for In-Band Bytestreams
+ */
+ public static final int MAXIMUM_BLOCK_SIZE = 65535;
+
+ /* prefix used to generate session IDs */
+ private static final String SESSION_ID_PREFIX = "jibb_";
+
+ /* random generator to create session IDs */
+ private final static Random randomGenerator = new Random();
+
+ /* stores one InBandBytestreamManager for each XMPP connection */
+ private final static Map<Connection, InBandBytestreamManager> managers = new HashMap<Connection, InBandBytestreamManager>();
+
+ /* XMPP connection */
+ private final Connection connection;
+
+ /*
+ * assigns a user to a listener that is informed if an In-Band Bytestream request for this user
+ * is received
+ */
+ private final Map<String, BytestreamListener> userListeners = new ConcurrentHashMap<String, BytestreamListener>();
+
+ /*
+ * list of listeners that respond to all In-Band Bytestream requests if there are no user
+ * specific listeners for that request
+ */
+ private final List<BytestreamListener> allRequestListeners = Collections.synchronizedList(new LinkedList<BytestreamListener>());
+
+ /* listener that handles all incoming In-Band Bytestream requests */
+ private final InitiationListener initiationListener;
+
+ /* listener that handles all incoming In-Band Bytestream IQ data packets */
+ private final DataListener dataListener;
+
+ /* listener that handles all incoming In-Band Bytestream close requests */
+ private final CloseListener closeListener;
+
+ /* assigns a session ID to the In-Band Bytestream session */
+ private final Map<String, InBandBytestreamSession> sessions = new ConcurrentHashMap<String, InBandBytestreamSession>();
+
+ /* block size used for new In-Band Bytestreams */
+ private int defaultBlockSize = 4096;
+
+ /* maximum block size allowed for this connection */
+ private int maximumBlockSize = MAXIMUM_BLOCK_SIZE;
+
+ /* the stanza used to send data packets */
+ private StanzaType stanza = StanzaType.IQ;
+
+ /*
+ * list containing session IDs of In-Band Bytestream open packets that should be ignored by the
+ * InitiationListener
+ */
+ private List<String> ignoredBytestreamRequests = Collections.synchronizedList(new LinkedList<String>());
+
+ /**
+ * Returns the InBandBytestreamManager to handle In-Band Bytestreams for a given
+ * {@link Connection}.
+ *
+ * @param connection the XMPP connection
+ * @return the InBandBytestreamManager for the given XMPP connection
+ */
+ public static synchronized InBandBytestreamManager getByteStreamManager(Connection connection) {
+ if (connection == null)
+ return null;
+ InBandBytestreamManager manager = managers.get(connection);
+ if (manager == null) {
+ manager = new InBandBytestreamManager(connection);
+ managers.put(connection, manager);
+ }
+ return manager;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param connection the XMPP connection
+ */
+ private InBandBytestreamManager(Connection connection) {
+ this.connection = connection;
+
+ // register bytestream open packet listener
+ this.initiationListener = new InitiationListener(this);
+ this.connection.addPacketListener(this.initiationListener,
+ this.initiationListener.getFilter());
+
+ // register bytestream data packet listener
+ this.dataListener = new DataListener(this);
+ this.connection.addPacketListener(this.dataListener, this.dataListener.getFilter());
+
+ // register bytestream close packet listener
+ this.closeListener = new CloseListener(this);
+ this.connection.addPacketListener(this.closeListener, this.closeListener.getFilter());
+
+ }
+
+ /**
+ * Adds InBandBytestreamListener that is called for every incoming in-band bytestream request
+ * unless there is a user specific InBandBytestreamListener registered.
+ * <p>
+ * If no listeners are registered all In-Band Bytestream request are rejected with a
+ * &lt;not-acceptable/&gt; error.
+ * <p>
+ * Note that the registered {@link InBandBytestreamListener} will NOT be notified on incoming
+ * Socks5 bytestream requests sent in the context of <a
+ * href="http://xmpp.org/extensions/xep-0096.html">XEP-0096</a> file transfer. (See
+ * {@link FileTransferManager})
+ *
+ * @param listener the listener to register
+ */
+ public void addIncomingBytestreamListener(BytestreamListener listener) {
+ this.allRequestListeners.add(listener);
+ }
+
+ /**
+ * Removes the given listener from the list of listeners for all incoming In-Band Bytestream
+ * requests.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeIncomingBytestreamListener(BytestreamListener listener) {
+ this.allRequestListeners.remove(listener);
+ }
+
+ /**
+ * Adds InBandBytestreamListener that is called for every incoming in-band bytestream request
+ * from the given user.
+ * <p>
+ * Use this method if you are awaiting an incoming Socks5 bytestream request from a specific
+ * user.
+ * <p>
+ * If no listeners are registered all In-Band Bytestream request are rejected with a
+ * &lt;not-acceptable/&gt; error.
+ * <p>
+ * Note that the registered {@link InBandBytestreamListener} will NOT be notified on incoming
+ * Socks5 bytestream requests sent in the context of <a
+ * href="http://xmpp.org/extensions/xep-0096.html">XEP-0096</a> file transfer. (See
+ * {@link FileTransferManager})
+ *
+ * @param listener the listener to register
+ * @param initiatorJID the JID of the user that wants to establish an In-Band Bytestream
+ */
+ public void addIncomingBytestreamListener(BytestreamListener listener, String initiatorJID) {
+ this.userListeners.put(initiatorJID, listener);
+ }
+
+ /**
+ * Removes the listener for the given user.
+ *
+ * @param initiatorJID the JID of the user the listener should be removed
+ */
+ public void removeIncomingBytestreamListener(String initiatorJID) {
+ this.userListeners.remove(initiatorJID);
+ }
+
+ /**
+ * Use this method to ignore the next incoming In-Band Bytestream request containing the given
+ * session ID. No listeners will be notified for this request and and no error will be returned
+ * to the initiator.
+ * <p>
+ * This method should be used if you are awaiting an In-Band Bytestream request as a reply to
+ * another packet (e.g. file transfer).
+ *
+ * @param sessionID to be ignored
+ */
+ public void ignoreBytestreamRequestOnce(String sessionID) {
+ this.ignoredBytestreamRequests.add(sessionID);
+ }
+
+ /**
+ * Returns the default block size that is used for all outgoing in-band bytestreams for this
+ * connection.
+ * <p>
+ * The recommended default block size is 4096 bytes. See <a
+ * href="http://xmpp.org/extensions/xep-0047.html#usage">XEP-0047</a> Section 5.
+ *
+ * @return the default block size
+ */
+ public int getDefaultBlockSize() {
+ return defaultBlockSize;
+ }
+
+ /**
+ * Sets the default block size that is used for all outgoing in-band bytestreams for this
+ * connection.
+ * <p>
+ * The default block size must be between 1 and 65535 bytes. The recommended default block size
+ * is 4096 bytes. See <a href="http://xmpp.org/extensions/xep-0047.html#usage">XEP-0047</a>
+ * Section 5.
+ *
+ * @param defaultBlockSize the default block size to set
+ */
+ public void setDefaultBlockSize(int defaultBlockSize) {
+ if (defaultBlockSize <= 0 || defaultBlockSize > MAXIMUM_BLOCK_SIZE) {
+ throw new IllegalArgumentException("Default block size must be between 1 and "
+ + MAXIMUM_BLOCK_SIZE);
+ }
+ this.defaultBlockSize = defaultBlockSize;
+ }
+
+ /**
+ * Returns the maximum block size that is allowed for In-Band Bytestreams for this connection.
+ * <p>
+ * Incoming In-Band Bytestream open request will be rejected with an
+ * &lt;resource-constraint/&gt; error if the block size is greater then the maximum allowed
+ * block size.
+ * <p>
+ * The default maximum block size is 65535 bytes.
+ *
+ * @return the maximum block size
+ */
+ public int getMaximumBlockSize() {
+ return maximumBlockSize;
+ }
+
+ /**
+ * Sets the maximum block size that is allowed for In-Band Bytestreams for this connection.
+ * <p>
+ * The maximum block size must be between 1 and 65535 bytes.
+ * <p>
+ * Incoming In-Band Bytestream open request will be rejected with an
+ * &lt;resource-constraint/&gt; error if the block size is greater then the maximum allowed
+ * block size.
+ *
+ * @param maximumBlockSize the maximum block size to set
+ */
+ public void setMaximumBlockSize(int maximumBlockSize) {
+ if (maximumBlockSize <= 0 || maximumBlockSize > MAXIMUM_BLOCK_SIZE) {
+ throw new IllegalArgumentException("Maximum block size must be between 1 and "
+ + MAXIMUM_BLOCK_SIZE);
+ }
+ this.maximumBlockSize = maximumBlockSize;
+ }
+
+ /**
+ * Returns the stanza used to send data packets.
+ * <p>
+ * Default is {@link StanzaType#IQ}. See <a
+ * href="http://xmpp.org/extensions/xep-0047.html#message">XEP-0047</a> Section 4.
+ *
+ * @return the stanza used to send data packets
+ */
+ public StanzaType getStanza() {
+ return stanza;
+ }
+
+ /**
+ * Sets the stanza used to send data packets.
+ * <p>
+ * The use of {@link StanzaType#IQ} is recommended. See <a
+ * href="http://xmpp.org/extensions/xep-0047.html#message">XEP-0047</a> Section 4.
+ *
+ * @param stanza the stanza to set
+ */
+ public void setStanza(StanzaType stanza) {
+ this.stanza = stanza;
+ }
+
+ /**
+ * Establishes an In-Band Bytestream with the given user and returns the session to send/receive
+ * data to/from the user.
+ * <p>
+ * Use this method to establish In-Band Bytestreams to users accepting all incoming In-Band
+ * Bytestream requests since this method doesn't provide a way to tell the user something about
+ * the data to be sent.
+ * <p>
+ * To establish an In-Band Bytestream after negotiation the kind of data to be sent (e.g. file
+ * transfer) use {@link #establishSession(String, String)}.
+ *
+ * @param targetJID the JID of the user an In-Band Bytestream should be established
+ * @return the session to send/receive data to/from the user
+ * @throws XMPPException if the user doesn't support or accept in-band bytestreams, or if the
+ * user prefers smaller block sizes
+ */
+ public InBandBytestreamSession establishSession(String targetJID) throws XMPPException {
+ String sessionID = getNextSessionID();
+ return establishSession(targetJID, sessionID);
+ }
+
+ /**
+ * Establishes an In-Band Bytestream with the given user using the given session ID and returns
+ * the session to send/receive data to/from the user.
+ *
+ * @param targetJID the JID of the user an In-Band Bytestream should be established
+ * @param sessionID the session ID for the In-Band Bytestream request
+ * @return the session to send/receive data to/from the user
+ * @throws XMPPException if the user doesn't support or accept in-band bytestreams, or if the
+ * user prefers smaller block sizes
+ */
+ public InBandBytestreamSession establishSession(String targetJID, String sessionID)
+ throws XMPPException {
+ Open byteStreamRequest = new Open(sessionID, this.defaultBlockSize, this.stanza);
+ byteStreamRequest.setTo(targetJID);
+
+ // sending packet will throw exception on timeout or error reply
+ SyncPacketSend.getReply(this.connection, byteStreamRequest);
+
+ InBandBytestreamSession inBandBytestreamSession = new InBandBytestreamSession(
+ this.connection, byteStreamRequest, targetJID);
+ this.sessions.put(sessionID, inBandBytestreamSession);
+
+ return inBandBytestreamSession;
+ }
+
+ /**
+ * Responses to the given IQ packet's sender with an XMPP error that an In-Band Bytestream is
+ * not accepted.
+ *
+ * @param request IQ packet that should be answered with a not-acceptable error
+ */
+ protected void replyRejectPacket(IQ request) {
+ XMPPError xmppError = new XMPPError(XMPPError.Condition.no_acceptable);
+ IQ error = IQ.createErrorResponse(request, xmppError);
+ this.connection.sendPacket(error);
+ }
+
+ /**
+ * Responses to the given IQ packet's sender with an XMPP error that an In-Band Bytestream open
+ * request is rejected because its block size is greater than the maximum allowed block size.
+ *
+ * @param request IQ packet that should be answered with a resource-constraint error
+ */
+ protected void replyResourceConstraintPacket(IQ request) {
+ XMPPError xmppError = new XMPPError(XMPPError.Condition.resource_constraint);
+ IQ error = IQ.createErrorResponse(request, xmppError);
+ this.connection.sendPacket(error);
+ }
+
+ /**
+ * Responses to the given IQ packet's sender with an XMPP error that an In-Band Bytestream
+ * session could not be found.
+ *
+ * @param request IQ packet that should be answered with a item-not-found error
+ */
+ protected void replyItemNotFoundPacket(IQ request) {
+ XMPPError xmppError = new XMPPError(XMPPError.Condition.item_not_found);
+ IQ error = IQ.createErrorResponse(request, xmppError);
+ this.connection.sendPacket(error);
+ }
+
+ /**
+ * Returns a new unique session ID.
+ *
+ * @return a new unique session ID
+ */
+ private String getNextSessionID() {
+ StringBuilder buffer = new StringBuilder();
+ buffer.append(SESSION_ID_PREFIX);
+ buffer.append(Math.abs(randomGenerator.nextLong()));
+ return buffer.toString();
+ }
+
+ /**
+ * Returns the XMPP connection.
+ *
+ * @return the XMPP connection
+ */
+ protected Connection getConnection() {
+ return this.connection;
+ }
+
+ /**
+ * Returns the {@link InBandBytestreamListener} that should be informed if a In-Band Bytestream
+ * request from the given initiator JID is received.
+ *
+ * @param initiator the initiator's JID
+ * @return the listener
+ */
+ protected BytestreamListener getUserListener(String initiator) {
+ return this.userListeners.get(initiator);
+ }
+
+ /**
+ * Returns a list of {@link InBandBytestreamListener} that are informed if there are no
+ * listeners for a specific initiator.
+ *
+ * @return list of listeners
+ */
+ protected List<BytestreamListener> getAllRequestListeners() {
+ return this.allRequestListeners;
+ }
+
+ /**
+ * Returns the sessions map.
+ *
+ * @return the sessions map
+ */
+ protected Map<String, InBandBytestreamSession> getSessions() {
+ return sessions;
+ }
+
+ /**
+ * Returns the list of session IDs that should be ignored by the InitialtionListener
+ *
+ * @return list of session IDs
+ */
+ protected List<String> getIgnoredBytestreamRequests() {
+ return ignoredBytestreamRequests;
+ }
+
+ /**
+ * Disables the InBandBytestreamManager by removing its packet listeners and resetting its
+ * internal status.
+ */
+ private void disableService() {
+
+ // remove manager from static managers map
+ managers.remove(connection);
+
+ // remove all listeners registered by this manager
+ this.connection.removePacketListener(this.initiationListener);
+ this.connection.removePacketListener(this.dataListener);
+ this.connection.removePacketListener(this.closeListener);
+
+ // shutdown threads
+ this.initiationListener.shutdown();
+
+ // reset internal status
+ this.userListeners.clear();
+ this.allRequestListeners.clear();
+ this.sessions.clear();
+ this.ignoredBytestreamRequests.clear();
+
+ }
+
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamRequest.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamRequest.java
index 5bc689a4a..310b844b0 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamRequest.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamRequest.java
@@ -1,92 +1,92 @@
-/**
- * All rights reserved. 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 org.jivesoftware.smackx.bytestreams.ibb;
-
-import org.jivesoftware.smack.Connection;
-import org.jivesoftware.smack.XMPPException;
-import org.jivesoftware.smack.packet.IQ;
-import org.jivesoftware.smackx.bytestreams.BytestreamRequest;
-import org.jivesoftware.smackx.bytestreams.ibb.packet.Open;
-
-/**
- * InBandBytestreamRequest class handles incoming In-Band Bytestream requests.
- *
- * @author Henning Staib
- */
-public class InBandBytestreamRequest implements BytestreamRequest {
-
- /* the bytestream initialization request */
- private final Open byteStreamRequest;
-
- /*
- * In-Band Bytestream manager containing the XMPP connection and helper
- * methods
- */
- private final InBandBytestreamManager manager;
-
- protected InBandBytestreamRequest(InBandBytestreamManager manager,
- Open byteStreamRequest) {
- this.manager = manager;
- this.byteStreamRequest = byteStreamRequest;
- }
-
- /**
- * Returns the sender of the In-Band Bytestream open request.
- *
- * @return the sender of the In-Band Bytestream open request
- */
- public String getFrom() {
- return this.byteStreamRequest.getFrom();
- }
-
- /**
- * Returns the session ID of the In-Band Bytestream open request.
- *
- * @return the session ID of the In-Band Bytestream open request
- */
- public String getSessionID() {
- return this.byteStreamRequest.getSessionID();
- }
-
- /**
- * Accepts the In-Band Bytestream open request and returns the session to
- * send/receive data.
- *
- * @return the session to send/receive data
- * @throws XMPPException if stream is invalid.
- */
- public InBandBytestreamSession accept() throws XMPPException {
- Connection connection = this.manager.getConnection();
-
- // create In-Band Bytestream session and store it
- InBandBytestreamSession ibbSession = new InBandBytestreamSession(connection,
- this.byteStreamRequest, this.byteStreamRequest.getFrom());
- this.manager.getSessions().put(this.byteStreamRequest.getSessionID(), ibbSession);
-
- // acknowledge request
- IQ resultIQ = IQ.createResultIQ(this.byteStreamRequest);
- connection.sendPacket(resultIQ);
-
- return ibbSession;
- }
-
- /**
- * Rejects the In-Band Bytestream request by sending a reject error to the
- * initiator.
- */
- public void reject() {
- this.manager.replyRejectPacket(this.byteStreamRequest);
- }
-
-}
+/**
+ * All rights reserved. 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 org.jivesoftware.smackx.bytestreams.ibb;
+
+import org.jivesoftware.smack.Connection;
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smack.packet.IQ;
+import org.jivesoftware.smackx.bytestreams.BytestreamRequest;
+import org.jivesoftware.smackx.bytestreams.ibb.packet.Open;
+
+/**
+ * InBandBytestreamRequest class handles incoming In-Band Bytestream requests.
+ *
+ * @author Henning Staib
+ */
+public class InBandBytestreamRequest implements BytestreamRequest {
+
+ /* the bytestream initialization request */
+ private final Open byteStreamRequest;
+
+ /*
+ * In-Band Bytestream manager containing the XMPP connection and helper
+ * methods
+ */
+ private final InBandBytestreamManager manager;
+
+ protected InBandBytestreamRequest(InBandBytestreamManager manager,
+ Open byteStreamRequest) {
+ this.manager = manager;
+ this.byteStreamRequest = byteStreamRequest;
+ }
+
+ /**
+ * Returns the sender of the In-Band Bytestream open request.
+ *
+ * @return the sender of the In-Band Bytestream open request
+ */
+ public String getFrom() {
+ return this.byteStreamRequest.getFrom();
+ }
+
+ /**
+ * Returns the session ID of the In-Band Bytestream open request.
+ *
+ * @return the session ID of the In-Band Bytestream open request
+ */
+ public String getSessionID() {
+ return this.byteStreamRequest.getSessionID();
+ }
+
+ /**
+ * Accepts the In-Band Bytestream open request and returns the session to
+ * send/receive data.
+ *
+ * @return the session to send/receive data
+ * @throws XMPPException if stream is invalid.
+ */
+ public InBandBytestreamSession accept() throws XMPPException {
+ Connection connection = this.manager.getConnection();
+
+ // create In-Band Bytestream session and store it
+ InBandBytestreamSession ibbSession = new InBandBytestreamSession(connection,
+ this.byteStreamRequest, this.byteStreamRequest.getFrom());
+ this.manager.getSessions().put(this.byteStreamRequest.getSessionID(), ibbSession);
+
+ // acknowledge request
+ IQ resultIQ = IQ.createResultIQ(this.byteStreamRequest);
+ connection.sendPacket(resultIQ);
+
+ return ibbSession;
+ }
+
+ /**
+ * Rejects the In-Band Bytestream request by sending a reject error to the
+ * initiator.
+ */
+ public void reject() {
+ this.manager.replyRejectPacket(this.byteStreamRequest);
+ }
+
+}
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java
index a33682c87..6323d872d 100644
--- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java
@@ -1,795 +1,795 @@
-/**
- * All rights reserved. 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 org.jivesoftware.smackx.bytestreams.ibb;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.SocketTimeoutException;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-
-import org.jivesoftware.smack.Connection;
-import org.jivesoftware.smack.PacketListener;
-import org.jivesoftware.smack.XMPPException;
-import org.jivesoftware.smack.filter.AndFilter;
-import org.jivesoftware.smack.filter.PacketFilter;
-import org.jivesoftware.smack.filter.PacketTypeFilter;
-import org.jivesoftware.smack.packet.IQ;
-import org.jivesoftware.smack.packet.Message;
-import org.jivesoftware.smack.packet.Packet;
-import org.jivesoftware.smack.packet.PacketExtension;
-import org.jivesoftware.smack.packet.XMPPError;
-import org.jivesoftware.smack.util.StringUtils;
-import org.jivesoftware.smack.util.SyncPacketSend;
-import org.jivesoftware.smackx.bytestreams.BytestreamSession;
-import org.jivesoftware.smackx.bytestreams.ibb.packet.Close;
-import org.jivesoftware.smackx.bytestreams.ibb.packet.Data;
-import org.jivesoftware.smackx.bytestreams.ibb.packet.DataPacketExtension;
-import org.jivesoftware.smackx.bytestreams.ibb.packet.Open;
-
-/**
- * InBandBytestreamSession class represents an In-Band Bytestream session.
- * <p>
- * In-band bytestreams are bidirectional and this session encapsulates the streams for both
- * directions.
- * <p>
- * Note that closing the In-Band Bytestream session will close both streams. If both streams are
- * closed individually the session will be closed automatically once the second stream is closed.
- * Use the {@link #setCloseBothStreamsEnabled(boolean)} method if both streams should be closed
- * automatically if one of them is closed.
- *
- * @author Henning Staib
- */
-public class InBandBytestreamSession implements BytestreamSession {
-
- /* XMPP connection */
- private final Connection connection;
-
- /* the In-Band Bytestream open request for this session */
- private final Open byteStreamRequest;
-
- /*
- * the input stream for this session (either IQIBBInputStream or MessageIBBInputStream)
- */
- private IBBInputStream inputStream;
-
- /*
- * the output stream for this session (either IQIBBOutputStream or MessageIBBOutputStream)
- */
- private IBBOutputStream outputStream;
-
- /* JID of the remote peer */
- private String remoteJID;
-
- /* flag to close both streams if one of them is closed */
- private boolean closeBothStreamsEnabled = false;
-
- /* flag to indicate if session is closed */
- private boolean isClosed = false;
-
- /**
- * Constructor.
- *
- * @param connection the XMPP connection
- * @param byteStreamRequest the In-Band Bytestream open request for this session
- * @param remoteJID JID of the remote peer
- */
- protected InBandBytestreamSession(Connection connection, Open byteStreamRequest,
- String remoteJID) {
- this.connection = connection;
- this.byteStreamRequest = byteStreamRequest;
- this.remoteJID = remoteJID;
-
- // initialize streams dependent to the uses stanza type
- switch (byteStreamRequest.getStanza()) {
- case IQ:
- this.inputStream = new IQIBBInputStream();
- this.outputStream = new IQIBBOutputStream();
- break;
- case MESSAGE:
- this.inputStream = new MessageIBBInputStream();
- this.outputStream = new MessageIBBOutputStream();
- break;
- }
-
- }
-
- public InputStream getInputStream() {
- return this.inputStream;
- }
-
- public OutputStream getOutputStream() {
- return this.outputStream;
- }
-
- public int getReadTimeout() {
- return this.inputStream.readTimeout;
- }
-
- public void setReadTimeout(int timeout) {
- if (timeout < 0) {
- throw new IllegalArgumentException("Timeout must be >= 0");
- }
- this.inputStream.readTimeout = timeout;
- }
-
- /**
- * Returns whether both streams should be closed automatically if one of the streams is closed.
- * Default is <code>false</code>.
- *
- * @return <code>true</code> if both streams will be closed if one of the streams is closed,
- * <code>false</code> if both streams can be closed independently.
- */
- public boolean isCloseBothStreamsEnabled() {
- return closeBothStreamsEnabled;
- }
-
- /**
- * Sets whether both streams should be closed automatically if one of the streams is closed.
- * Default is <code>false</code>.
- *
- * @param closeBothStreamsEnabled <code>true</code> if both streams should be closed if one of
- * the streams is closed, <code>false</code> if both streams should be closed
- * independently
- */
- public void setCloseBothStreamsEnabled(boolean closeBothStreamsEnabled) {
- this.closeBothStreamsEnabled = closeBothStreamsEnabled;
- }
-
- public void close() throws IOException {
- closeByLocal(true); // close input stream
- closeByLocal(false); // close output stream
- }
-
- /**
- * This method is invoked if a request to close the In-Band Bytestream has been received.
- *
- * @param closeRequest the close request from the remote peer
- */
- protected void closeByPeer(Close closeRequest) {
-
- /*
- * close streams without flushing them, because stream is already considered closed on the
- * remote peers side
- */
- this.inputStream.closeInternal();
- this.inputStream.cleanup();
- this.outputStream.closeInternal(false);
-
- // acknowledge close request
- IQ confirmClose = IQ.createResultIQ(closeRequest);
- this.connection.sendPacket(confirmClose);
-
- }
-
- /**
- * This method is invoked if one of the streams has been closed locally, if an error occurred
- * locally or if the whole session should be closed.
- *
- * @throws IOException if an error occurs while sending the close request
- */
- protected synchronized void closeByLocal(boolean in) throws IOException {
- if (this.isClosed) {
- return;
- }
-
- if (this.closeBothStreamsEnabled) {
- this.inputStream.closeInternal();
- this.outputStream.closeInternal(true);
- }
- else {
- if (in) {
- this.inputStream.closeInternal();
- }
- else {
- // close stream but try to send any data left
- this.outputStream.closeInternal(true);
- }
- }
-
- if (this.inputStream.isClosed && this.outputStream.isClosed) {
- this.isClosed = true;
-
- // send close request
- Close close = new Close(this.byteStreamRequest.getSessionID());
- close.setTo(this.remoteJID);
- try {
- SyncPacketSend.getReply(this.connection, close);
- }
- catch (XMPPException e) {
- throw new IOException("Error while closing stream: " + e.getMessage());
- }
-
- this.inputStream.cleanup();
-
- // remove session from manager
- InBandBytestreamManager.getByteStreamManager(this.connection).getSessions().remove(this);
- }
-
- }
-
- /**
- * IBBInputStream class is the base implementation of an In-Band Bytestream input stream.
- * Subclasses of this input stream must provide a packet listener along with a packet filter to
- * collect the In-Band Bytestream data packets.
- */
- private abstract class IBBInputStream extends InputStream {
-
- /* the data packet listener to fill the data queue */
- private final PacketListener dataPacketListener;
-
- /* queue containing received In-Band Bytestream data packets */
- protected final BlockingQueue<DataPacketExtension> dataQueue = new LinkedBlockingQueue<DataPacketExtension>();
-
- /* buffer containing the data from one data packet */
- private byte[] buffer;
-
- /* pointer to the next byte to read from buffer */
- private int bufferPointer = -1;
-
- /* data packet sequence (range from 0 to 65535) */
- private long seq = -1;
-
- /* flag to indicate if input stream is closed */
- private boolean isClosed = false;
-
- /* flag to indicate if close method was invoked */
- private boolean closeInvoked = false;
-
- /* timeout for read operations */
- private int readTimeout = 0;
-
- /**
- * Constructor.
- */
- public IBBInputStream() {
- // add data packet listener to connection
- this.dataPacketListener = getDataPacketListener();
- connection.addPacketListener(this.dataPacketListener, getDataPacketFilter());
- }
-
- /**
- * Returns the packet listener that processes In-Band Bytestream data packets.
- *
- * @return the data packet listener
- */
- protected abstract PacketListener getDataPacketListener();
-
- /**
- * Returns the packet filter that accepts In-Band Bytestream data packets.
- *
- * @return the data packet filter
- */
- protected abstract PacketFilter getDataPacketFilter();
-
- public synchronized int read() throws IOException {
- checkClosed();
-
- // if nothing read yet or whole buffer has been read fill buffer
- if (bufferPointer == -1 || bufferPointer >= buffer.length) {
- // if no data available and stream was closed return -1
- if (!loadBuffer()) {
- return -1;
- }
- }
-
- // return byte and increment buffer pointer
- return ((int) buffer[bufferPointer++]) & 0xff;
- }
-
- public synchronized int read(byte[] b, int off, int len) throws IOException {
- if (b == null) {
- throw new NullPointerException();
- }
- else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length)
- || ((off + len) < 0)) {
- throw new IndexOutOfBoundsException();
- }
- else if (len == 0) {
- return 0;