Add asmack build environemnt.

Downloaded from https://github.com/Flowdalic/asmack/archive/master.zip.

Change-Id: I93fb953348f2d2c058113874923777530a24bcc6
diff --git a/asmack-master/.gitignore b/asmack-master/.gitignore
new file mode 100644
index 0000000..cc97859
--- /dev/null
+++ b/asmack-master/.gitignore
@@ -0,0 +1,2 @@
+build
+local.properties
diff --git a/asmack-master/CHANGELOG b/asmack-master/CHANGELOG
new file mode 100644
index 0000000..e5f9f21
--- /dev/null
+++ b/asmack-master/CHANGELOG
@@ -0,0 +1,12 @@
+Release 0.8.2
+	- Removed the whitespace ping code SMACK-412
+	- SMACK-419 PacketWriter: Only flush the BufferedWriter if the packet queue is empty
+	- SMACK-417 If both PacketReader and PacketWriter fail at the same time, connectionClosedonError() is called two times
+	- The default ping intervall is now configured in seconds and not milliseconds
+
+Release 0.8.1.1
+	- Improved 'caps' XEP-0115 support
+	- Fixes an NPE in 0.8.1
+
+Release 0.8
+	- First release to test the release process
diff --git a/asmack-master/LICENSE b/asmack-master/LICENSE
new file mode 100644
index 0000000..d50ac8e
--- /dev/null
+++ b/asmack-master/LICENSE
@@ -0,0 +1,291 @@
+Licences
+
+All code in this repository is licensed under either
+(1) Apache License Version 2.0
+(2) THE OPENLDAP PUBLIC LICENSE (only src/novell-openldap-jldap)
+
+No GNU code will be included. Other patches are always welcome.
+
+
+
+                   The OpenLDAP Public License
+                   Version 2.8, 17 August 2003
+
+Redistribution and use of this software and associated documentation
+("Software"), with or without modification, are permitted provided
+that the following conditions are met:
+
+1. Redistributions in source form must retain copyright statements
+   and notices,
+
+2. Redistributions in binary form must reproduce applicable copyright
+   statements and notices, this list of conditions, and the following
+   disclaimer in the documentation and/or other materials provided
+   with the distribution, and
+
+3. Redistributions must contain a verbatim copy of this document.
+
+The OpenLDAP Foundation may revise this license from time to time.
+Each revision is distinguished by a version number.  You may use
+this Software under terms of this license revision or under the
+terms of any subsequent revision of the license.
+
+THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS
+CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT
+SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S)
+OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+The names of the authors and copyright holders must not be used in
+advertising or otherwise to promote the sale, use or other dealing
+in this Software without specific, written prior permission.  Title
+to copyright in this Software shall at all times remain with copyright
+holders.
+
+OpenLDAP is a registered trademark of the OpenLDAP Foundation.
+
+Copyright 1999-2003 The OpenLDAP Foundation, Redwood City,
+California, USA.  All Rights Reserved.  Permission to copy and
+distribute verbatim copies of this document is granted.
+
+
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
++++++++++++
++ dnsjava +
++++++++++++
+
+Copyright (c) 1998-2011, Brian Wellington.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/asmack-master/README.asmack b/asmack-master/README.asmack
new file mode 100644
index 0000000..9ca40b7
--- /dev/null
+++ b/asmack-master/README.asmack
@@ -0,0 +1,71 @@
+aSmack README
+=============
+
+Version: $VERSION_TAG
+Build date: $BUILD_DATE
+
+Important Notes
+===============
+
+Read this, or aSmack won't work for you!
+
+Static Code
+-----------
+
+In order to work correctly on Android, you need to register Smack's
+XMPP Providers and Extensions manually and init some static code
+blocks before you doing any XMPP activty. Calling
+SmackAndroid.init(Context) (in org.jivesoftware.smack) will do this
+for you.
+
+ConnectionConfiguration
+-----------------------
+
+Please use the provided AndroidConnectionConfiguration class if
+possible to create a new connection.
+
+Compression
+-----------
+
+If you want compressed XMPP streams you have to add
+[jzlib-1.0.7](http://www.jcraft.com/jzlib/) to your project. Note that
+every version higher then 1.0.7 wont work.
+More Info: https://github.com/Flowdalic/smack/issues/12
+
+Problems / Debugging
+==============================
+
+aSmack Wiki
+-----------
+
+More information about XMPP File Transfers, SSL Certificates and other
+stuff related to aSmack can be found in the wiki:
+https://github.com/Flowdalic/asmack/wiki
+
+How to debug your problem
+-------------------------
+
+We always provide source zips. Attach them to the jar in your favorite
+IDE. Enable debugging mode with [BOSH|XMPP]Connection.DEBUG and
+config.setDebug. See also:
+http://www.igniterealtime.org/builds/smack/docs/latest/documentation/debugging.html
+
+Reporting a bug
+---------------
+
+Your issue should contain
+1. a logcat
+2. a server to reproduce
+3. the code you are using (for FOSS project we'll accept reposituroy URLs)
+
+If you record a logcat and make sure to remove your credentials
+(usually a base64 block inside <auth></auth>).
+
+There is no guarantee that we will reply immediatly. But we will try
+to investigate the problem. Feel free to join ##smack @ freenode and
+ask for help (you may have to idle for some time before you get a
+reply).
+
+Component Revision Information for this Release
+===============================================
+
diff --git a/asmack-master/README.markdown b/asmack-master/README.markdown
new file mode 100644
index 0000000..751291b
--- /dev/null
+++ b/asmack-master/README.markdown
@@ -0,0 +1,100 @@
+aSmack - buildsystem for Smack on Android
+=========================================
+
+*This repository doesn't contain much code, it's a build environment!*
+
+Tracking trunk can be hard. Doing massive changes on top of trunk can
+be near impossible. We are mixing 6 open source projects to provide a
+working xmpp library for Android. All trunk-based.
+
+This repository contains a source fetching, patching and building
+script.  As well as all the minor changes to make an Android version
+fly.  See the patches/ folder for a detailed list of changes and
+scripts.
+
+Compiled JARs
+=============
+
+Can be found @ http://asmack.freakempire.de/ 
+
+Make sure to [*read the
+README*](https://github.com/Flowdalic/asmack/blob/master/README.asmack)
+for every release.
+
+Support
+=======
+[![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=Flowdalic&url=https://github.com/flowdalic/asmack&title=asmack&language=&tags=github&category=software)
+
+Compiling aSmack
+================
+
+1. copy local.properties.example to local.properties and set the
+Android SDK path (e.g. sdk-location=/opt/android-sdk-update-manager/
+on a gentoo system)
+
+2. Run build.bash
+
+aSmack uses a [special fork of
+smack](https://github.com/Flowdalic/smack). You can read about the
+results you will get when using one of the various branches provides
+in the
+[README](https://github.com/Flowdalic/smack/blob/master/README.markdown).
+
+Apps that use this fork of aSmack
+=================================
+- [GTalkSMS](http://code.google.com/p/gtalksms/) uses many features of Smack and XMPP on Android:
+    - File Transfer
+    - DNS SRV
+    - MUC
+    - Entity Caps
+    - and many more 
+
+- [yaxim](https://github.com/ge0rg/yaxim)
+- your app?
+
+Contribution
+============
+
+If possible, please base patches on smack, not on aSmack. You can use
+the 'upstream' branch from [smack @
+github](https://github.com/Flowdalic/smack). Only in some cases the
+'master' branch should be used.
+
+If your code follows [Smack's contributor guidelines](
+http://community.igniterealtime.org/docs/DOC-1984), is good documented
+and comes with some testcases, then it's possible to commit it
+upstream. Simply join ##smack @ freenode and ask for a code review.
+
+Contributors
+============
+
+We do not keep a seperate CONTRIBUTORS file, and we discourage @author
+tags.  However you're free to add your full name to every git commit,
+and we will preserver this. Let us know if you've helped on
+non-technical stuff and we'll find a way to give you the deserved
+credit.
+
+Contact
+=======
+
+Join ##smack @ freenode
+
+Licences / Used libraries
+=========================
+
+We only accept Apache and BSD-like licences.
+We are currently using code from
+
+ * Apache Harmony (sasl/xml) (Apache Licence)
+ * smack (xmpp) (Apache Licence)
+ * novell-openldap-jldap (sasl) ([OpenLDAP Licence][1])
+ * Apache qpid (sasl) (Apache Licence)
+ * jbosh (BOSH) (Apache Licence)
+ * dnsjava (dns srv lookups) (BSD)
+ * custom code (various glue stuff) (WTFPL | BSD | Apache)
+
+This should work for just about every project. Contact us if you have
+problems with the licence.
+
+  [1]: http://www.openldap.org/devel/cvsweb.cgi/~checkout~/LICENSE?rev=1.23.2.1&hideattic=1&sortbydate=0  "OpenLDAP Licence"
+
diff --git a/asmack-master/build.bash b/asmack-master/build.bash
new file mode 100755
index 0000000..874f238
--- /dev/null
+++ b/asmack-master/build.bash
@@ -0,0 +1,570 @@
+#!/bin/bash
+
+svnfetch() {
+    REV="${3:-HEAD}"
+    echo "Fetching from ${1} to ${2} at revision ${REV}"
+    cd $SRC_DIR
+    if ! [ -f "${2}/.svn/entries" ]; then
+	mkdir "${2}"
+	cd "${2}"
+	svn co --non-interactive --trust-server-cert "${1}" -r "${REV}" "."
+    else
+	cd "${2}"
+	svn cleanup
+	svn up -r "${REV}"
+    fi
+}
+
+gitfetch() {
+    echo "Fetching ${2} branch/commit from ${1} to ${3} via git"
+    cd $SRC_DIR
+    if ! [ -f "${3}/.git/config" ]; then
+	git clone "${1}" "${3}"
+	cd "${3}"
+	git checkout "${2}"
+    else
+	cd "${3}"
+	git fetch
+	git checkout "${2}"
+    fi
+
+    if [ $? -ne 0 ]; then
+	exit
+    fi
+}
+
+hgfetch() {
+(
+  echo "Fetching ${2} branch from ${1} to ${3} via mercurial"
+  cd src
+  if [ -e "${2}/.hg" ] ; then
+      cd ${2}
+      hg pull
+  else
+      hg clone "${1}" "${2}"
+  fi
+  hg up -r ${3}
+)
+    if [ $? -ne 0 ]; then
+	exit
+    fi
+}
+
+
+testsmackgit() {
+    cd $SRC_DIR
+    if [ -f .used-smack-git-repo ] && [ $(cat .used-smack-git-repo) != $SMACK_REPO ] ; then
+	    echo "Used smack repository has changed!"
+	    echo "Old: $(cat .used-smack-git-repo) New: ${SMACK_REPO}."
+	    echo "Deleting old local copy"
+	    rm -rf smack
+    fi
+    echo "${SMACK_REPO}" > .used-smack-git-repo
+}
+
+fetchall() {
+    echo "## Step 15: fetching sources"
+    if $SMACK_LOCAL ; then
+	# always clean the local copy first
+	rm -rf ${SRC_DIR}/smack
+	mkdir ${SRC_DIR}/smack
+	cd $SMACK_REPO
+	git archive $SMACK_BRANCH | tar -x -C ${SRC_DIR}/smack
+	if [ $? -ne 0 ]; then
+	    exit
+	fi
+    else
+	execute gitfetch "$SMACK_REPO" "$SMACK_BRANCH" "smack"
+    fi
+
+    if ! $UPDATE_REMOTE ; then
+	echo "Won't update or fetch third party resources"
+	wait
+	return
+    fi
+
+    execute svnfetch "http://svn.apache.org/repos/asf/qpid/trunk/qpid/java/management/common/src/main/" "qpid"
+    execute svnfetch "http://svn.apache.org/repos/asf/harmony/enhanced/java/trunk/classlib/modules/auth/src/main/java/common/" "harmony" 
+    execute svnfetch "https://dnsjava.svn.sourceforge.net/svnroot/dnsjava/trunk" "dnsjava"
+    execute gitfetch "git://kenai.com/jbosh~origin" "master" "jbosh"
+    # jldap doesn't compile with the latest version (missing deps?), therefore it's a fixed version for now
+    #  execute gitfetch "git://git.openldap.org/openldap-jldap.git" "master" "novell-openldap-jldap"
+    wait
+}
+
+createVersionTag() {
+    # Skip this step is no version tag is given
+    [[ -z $VERSION_TAG ]] && return
+
+    local v
+    cat <<EOF  > $TAG_FILE
+#!/bin/bash
+
+# This file contains the version information of the components that
+# were used to build this aSmack version
+
+declare -g -A COMPONENT_VERSIONS
+EOF
+
+    for d in $(ls $SRC_DIR) ; do
+	cd $SRC_DIR
+
+	# Don't record the components version for static-src
+	for static in $(ls ${ASMACK_BASE}/static-src) ; do
+	    # Don't record the version if it's from the static sources
+	    [ $d == $static ] && continue
+	done
+
+	if [[ -d $d/.git ]] ; then
+	    v=$(cd $d && git rev-parse HEAD)
+	    key=$d
+	    COMPONENT_VERSIONS["$d"]=$v
+	elif [[ -d $d/.svn ]] ; then
+	    v=$(cd $d && svn info |grep Revision |cut -f 2 -d ' ')
+	    key=$d
+	    COMPONENT_VERSIONS["$d"]=$v
+	fi
+    done
+
+    if $SMACK_LOCAL ; then
+	cd $SMACK_REPO
+	v=$(git rev-parse HEAD)
+	COMPONENT_VERSIONS[smack]=$v
+    fi
+
+    cd ${ASMACK_BASE}
+    v=$(git rev-parse HEAD)
+    COMPONENT_VERSIONS[asmack]=$v
+
+    for i in "${!COMPONENT_VERSIONS[@]}" ; do
+	echo "COMPONENT_VERSIONS[$i]=${COMPONENT_VERSIONS[$i]}" >> $TAG_FILE
+    done
+}
+
+copyfolder() {
+  cd ${ASMACK_BASE}
+  (
+    cd "${1}"
+    tar -cSsp --exclude-vcs "${3}"
+  ) | (
+    cd "${2}"
+    tar -xSsp
+  )
+  wait
+}
+
+createbuildsrc() {
+  echo "## Step 20: creating build/src"
+  cd "${ASMACK_BASE}"
+  rm -rf build/src
+  mkdir -p build/src/trunk
+
+  execute copyfolder "src/smack/source/" "build/src/trunk" "."
+  execute copyfolder "src/qpid/java" "build/src/trunk" "org/apache/qpid/management/common/sasl"
+  execute copyfolder "src/novell-openldap-jldap" "build/src/trunk" "."
+  execute copyfolder "src/dnsjava"  "build/src/trunk" "org"
+  execute copyfolder "src/harmony" "build/src/trunk" "."
+  execute copyfolder "src/jbosh/src/main/java" "build/src/trunk" "."
+  if $BUILD_JINGLE ; then
+    execute copyfolder "src/smack/jingle/extension/source/" "build/src/trunk" "."
+  fi
+  wait
+  # custom overwrites some files from smack, so this has to be done as last
+  copyfolder "src/custom" "build/src/trunk" "."
+}
+
+patchsrc() {
+    echo "## Step 25: patch build/src"
+    cd ${ASMACK_BASE}/build/src/trunk/
+    for PATCH in `(cd "../../../${1}" ; find -maxdepth 1 -type f)|sort` ; do
+	echo $PATCH
+	if [[ $PATCH == *.sh ]]; then
+	    "../../../${1}/$PATCH" || exit 1
+	elif [[ $PATCH == *.patch ]]; then
+	    patch -p0 < "../../../${1}/$PATCH" || exit 1
+	fi
+    done
+}
+
+build() {
+  echo "## Step 30: compile"
+  buildandroid
+  if [ $? -ne 0 ]; then
+      exit 1
+  fi
+}
+
+buildandroid() {
+    local sdklocation
+    local version
+    local sdks
+    local minSdkVer=8
+
+    cd $ASMACK_BASE
+
+    if [ ! -f local.properties ] ; then
+	echo "Could not find local.properties file"
+	echo "See local.properties.example"
+	exit 1
+    fi
+
+    sdklocation=$(grep sdk-location local.properties| cut -d= -f2)
+    if [ -z "$sdklocation" ] ; then
+	echo "Android SDK not found. Don't build android version"
+	exit 1
+    fi
+    for f in ${sdklocation/\$\{user.home\}/$HOME}/platforms/* ; do
+	version=`basename $f`
+	if [[ "$version" != android-* ]] ; then
+	    echo "$sdklocation contains no Android SDKs"
+	    exit 1
+	fi
+	if [[ ${version#android-} -ge $minSdkVer ]] ; then
+	    if [ -n $BUILD_ANDROID_VERSIONS ] ; then
+		for build_version in $BUILD_ANDROID_VERSIONS ; do
+		    [ ${version#android-} != $build_version ] && continue 2
+		done
+	    fi
+	    echo "Building for ${version}"
+	    sdks="${sdks} ${version}\n"
+	fi
+
+    done
+
+    if [ -z "${sdks}" ] ; then
+	echo "No SDKs of a suitable minimal API (${minSdkVer}) version found"
+	exit 1
+    fi
+
+    local asmack_suffix
+    if [[ -n ${VERSION_TAG} ]] && [[ -n ${1} ]] ; then
+	asmack_suffix="${1}-${VERSION_TAG}"
+    elif [[ -n ${VERSION_TAG} ]] ; then
+	asmack_suffix="-${VERSION_TAG}"
+    else
+	asmack_suffix="${1}"
+    fi
+    if ! echo -e ${sdks} \
+	| xargs -I{} -n 1 $XARGS_ARGS ant \
+		-Dandroid.version={} \
+		-Djar.suffix="${asmack_suffix}" \
+		compile-android ; then
+	exit 1
+    fi
+}
+
+buildcustom() {
+  for dir in `find patch -maxdepth 1 -mindepth 1 -type d`; do
+    buildsrc
+    patchsrc "patch"
+    if $BUILD_JINGLE ; then
+      patchsrc "jingle"
+      JINGLE_ARGS="-Djingle=lib/jstun.jar"
+    fi
+    patchsrc "${dir}"
+    local custom
+    custom=$(echo ${dir} | sed 's:patch/:-:')
+    ant -Djar.suffix="${custom}" $JINGLE_ARGS
+    buildandroid "${custom}"
+  done
+}
+
+parseopts() {
+    while getopts a:b:r:t:cdhjpux OPTION "$@"; do
+	case $OPTION in
+	    a)
+		BUILD_ANDROID_VERSIONS="${OPTARG}"
+		;;
+	    r)
+		SMACK_REPO="${OPTARG}"
+		;;
+	    b)
+		SMACK_BRANCH="${OPTARG}"
+		;;
+	    d)
+		set -x
+		XARGS_ARGS="-t"
+		;;
+	    j)
+		BUILD_JINGLE=true
+		;;
+	    u)
+		UPDATE_REMOTE=false
+		;;
+	    c)
+		BUILD_CUSTOM=true
+		;;
+	    p)
+		PARALLEL_BUILD=true
+		;;
+	    t)
+		VERSION_TAG="${OPTARG}"
+		;;
+	    x)
+		PUBLISH_RELEASE=true
+		;;
+	    h)
+		echo "$0 -d -c -u -j -r <repo> -b <branch>"
+		echo "-d: Enable debug"
+		echo "-j: Build jingle code"
+		echo "-c: Apply custom patchs from patch directory"
+		echo "-u: DON'T update remote third party resources"
+		echo "-r <repo>: Git repository (can be local or remote) for underlying smack repository"
+		echo "-b <branch>: Git branch used to build aSmack from underlying smack repository"
+		echo "-p use parallel build where possible"
+		echo "-t <version>: Create a new version tag. You should build aSmack before calling this"
+		echo "-x: Publish the release"
+		echo "-a <SDK Version(s)>: Build only for the given Android SDK versions"
+		exit
+		;;
+	esac
+    done
+}
+
+prepareRelease() {
+    if [[ -z ${VERSION_TAG} ]]; then
+	echo "Version tag is not set. Not going to prepare a release"
+	return
+    fi
+
+    if [ -d $RELEASE_DIR ] ; then
+	rm -rf $RELEASE_DIR
+    fi
+    mkdir -p $RELEASE_DIR
+
+    mv ${ASMACK_BASE}/build/*.{jar,zip} ${RELEASE_DIR}/
+    cp $TAG_FILE ${RELEASE_DIR}/
+    cp ${ASMACK_BASE}/CHANGELOG ${RELEASE_DIR}
+
+    if [ -n $GPG_KEY ] ; then
+	find $RELEASE_DIR -maxdepth 1 -and \( -name '*.jar' -or -name '*.zip' \) -print0 \
+	    | xargs -n 1 -0 $XARGS_ARGS gpg --local-user $GPG_KEY --detach-sign
+    fi
+
+    find $RELEASE_DIR -maxdepth 1 -and \( -name '*.jar' -or -name '*.zip' \) -print0 \
+	| xargs -I{} -n 1 -0 $XARGS_ARGS sh -c 'md5sum {} > {}.md5'
+
+    local release_readme
+    release_readme=${RELEASE_DIR}/README
+
+    sed \
+	-e "s/\$VERSION_TAG/${VERSION_TAG}/" \
+	-e "s/\$BUILD_DATE/${BUILD_DATE}/" \
+	README.asmack > $release_readme
+
+    # Pretty print the component versions at the end of README
+    # Note that there is an exclamation mark at the beginning of the
+    # associative array to access the keys
+    for i in "${!COMPONENT_VERSIONS[@]}" ; do
+	local tabs
+	if [[ ${#i} -le 6 ]] ; then
+	    tabs="\t\t"
+	else
+	    tabs="\t"
+	fi
+	echo -e "${i}:${tabs}${COMPONENT_VERSIONS[$i]}" >> $release_readme
+    done
+}
+
+publishRelease() {
+    if [[ -z ${VERSION_TAG} ]]; then
+	echo "Version tag is not set. Not going to prepare a release"
+	return
+    fi
+
+    if [[ -z ${PUBLISH_RELEASE} ]]; then
+	echo "User doesn't want to publish this release"
+	return
+    fi
+
+    if [[ -z $PUBLISH_HOST || -z $PUBLISH_DIR ]]; then
+	echo "WARNING: Not going to publish this release as either $PUBLISH_HOST or $PUBLISH_DIR is not set"
+	return
+    fi
+
+    cd ${ASMACK_RELEASES}
+    cat <<EOF | sftp $PUBLISH_HOST
+rm ${PUBLISH_DIR}/${VERSION_TAG}/*
+mkdir ${PUBLISH_DIR}/${VERSION_TAG}
+put -r $VERSION_TAG $PUBLISH_DIR
+EOF
+}
+
+islocalrepo() {
+    local R="^(git|ssh)"
+    if [[ $1 =~ $R ]]; then
+	return 1
+    else
+	return 0
+    fi
+}
+
+initialize() {
+    echo "## Step 00: initialize"
+    if ! [ -d build/src/trunk ]; then
+	mkdir -p build/src/trunk
+    fi
+    if [ ! -d src/ ]; then
+	mkdir src
+    fi
+    find build \( -name '*.jar' -or -name '*.zip' \) -print0 | xargs -0 rm -f
+    rm -rf src/custom
+}
+
+cleanup() {
+    echo "## Deleting all temporary files"
+    rm -rf build
+    rm -rf src
+}
+
+copystaticsrc() {
+    cp -ur static-src/* src/
+}
+
+cmdExists() {
+    command -v $1 &> /dev/null
+    return $?
+}
+
+prettyPrintSeconds() {
+    local ttime
+    if (( $1 > 59 )); then
+	ttime=$(printf "%dm %ds\n" $(($1/60%60)) $(($1%60)) )
+    else
+	ttime=$(printf "%ds\n" $(($1)) )
+    fi
+    echo "Execution took $ttime"
+}
+
+execute() {
+    if [ -n "$BACKGROUND" ]; then
+	"$@" &
+    else
+	"$@"
+    fi
+}
+
+setdefaults() {
+    # Default configuration, can be changed with script arguments
+    SMACK_REPO=git://github.com/Flowdalic/smack.git
+    SMACK_BRANCH=master
+    SMACK_LOCAL=false
+    UPDATE_REMOTE=true
+    BUILD_CUSTOM=false
+    BUILD_JINGLE=false
+    JINGLE_ARGS=""
+    PARALLEL_BUILD=false
+    VERSION_TAG=""
+    PUBLISH_RELEASE=""
+    PUBLISH_HOST=""
+    PUBLISH_DIR=""
+    BUILD_ANDROID_VERSIONS=""
+
+    # Often used variables
+    ASMACK_BASE=$(pwd)
+    ASMACK_RELEASES=${ASMACK_BASE}/releases
+    SRC_DIR=${ASMACK_BASE}/src
+    VERSION_TAG_DIR=${ASMACK_BASE}/version-tags
+    STARTTIME=$(date -u "+%s")
+    BUILD_DATE=$(date)
+    # Declare an associative array that is in global scope ('-g')
+    declare -g -A COMPONENT_VERSIONS
+}
+
+parseconfig() {
+    if [ -f ${ASMACK_BASE}/config ]; then
+	source ${ASMACK_BASE}/config
+    fi
+}
+
+setconfig() {
+    if [ ${PARALLEL_BUILD} == "true" ]; then
+	XARGS_ARGS="${XARGS_ARGS} -P4"
+	BACKGROUND="true"
+    else
+	XARGS_ARGS=""
+	BACKGROUND=""
+    fi
+
+    if islocalrepo $SMACK_REPO; then
+	SMACK_LOCAL=true
+	SMACK_REPO=`readlink -f $SMACK_REPO`
+    fi
+
+    if [[ -n ${VERSION_TAG} ]]; then
+	if ! grep ${VERSION_TAG} CHANGELOG; then
+	    echo "Could not find the tag in the CHANGELOG file. Please write a short summary of changes"
+	    exit 1
+	fi
+	if ! git diff --exit-code; then
+	    echo "Unstaged changes found, please stages your changes"
+	    exit 1
+	fi
+	if ! git diff --cached --exit-code; then
+	    echo "Staged, but uncommited changes found, please commit"
+	    exit 1
+	fi
+	RELEASE_DIR=${ASMACK_RELEASES}/${VERSION_TAG}
+	TAG_FILE=${VERSION_TAG_DIR}/${VERSION_TAG}.tag
+    fi
+}
+
+printconfig() {
+    echo "Smack git repository $SMACK_REPO with branch $SMACK_BRANCH"
+    echo -e "SMACK_LOCAL:$SMACK_LOCAL\tUPDATE_REMOTE:$UPDATE_REMOTE\tBUILD_CUSTOM:$BUILD_CUSTOM\tBUILD_JINGLE:$BUILD_JINGLE"
+    echo -e "PARALLEL_BUILD:$PARALLEL_BUILD\tBASE:$ASMACK_BASE"
+}
+
+checkPrerequisites() {
+    if [[ $BASH_VERSION < 4 ]] ; then
+	echo "aSmack's build.bash needs at least bash version 4"
+	exit 1
+    fi
+
+    if ! tar --version |grep GNU &> /dev/null ; then
+	echo "aSmack's build.bash needs GNU tar"
+	exit 1
+    fi
+}
+
+# Main
+
+setdefaults
+parseopts $@
+checkPrerequisites
+parseconfig
+setconfig
+printconfig
+initialize
+copystaticsrc
+testsmackgit
+fetchall
+createVersionTag
+createbuildsrc
+patchsrc "patch"
+if $BUILD_JINGLE ; then
+  patchsrc "jingle"
+  JINGLE_ARGS="-Djingle=lib/jstun.jar"
+fi
+build
+
+if $BUILD_CUSTOM ; then
+    buildcustom
+fi
+
+if cmdExists advzip ; then
+  echo "advzip found, compressing files"
+  find build \( -name '*.jar' -or -name '*.zip' \) -print0 | xargs -n 1 -0 $XARGS_ARGS advzip -z4
+else
+  echo "Could not find the advzip command."
+  echo "advzip will further reduce the size of the generated jar and zip files,"
+  echo "consider installing advzip"
+fi
+
+prepareRelease
+publishRelease
+
+STOPTIME=$(date -u "+%s")
+RUNTIME=$(( $STOPTIME - $STARTTIME ))
+prettyPrintSeconds $RUNTIME
+printconfig
diff --git a/asmack-master/build.xml b/asmack-master/build.xml
new file mode 100644
index 0000000..9ecfb84
--- /dev/null
+++ b/asmack-master/build.xml
@@ -0,0 +1,80 @@
+<project name="asmack" default="compile" basedir=".">
+
+<property name="jar.suffix" value="" />
+<property name="jingle" value="" />
+<property file="local.properties" />
+<property name="android.version" value="" />
+<target name="compile-jse"  description="Compile for java se">
+    <delete dir="build/classes" failonerror="false" />
+    <mkdir dir="build/classes" />
+    <mkdir dir="build/classes/trunk" />
+    <javac
+      target="6"
+      source="6"
+      srcdir="build/src/trunk"
+      destdir="build/classes/trunk"
+      classpath="lib/xpp3-1.1.4c.jar:lib/httpclient-4.1.3.jar:lib/httpcore-4.1.4.jar"
+      debug="true"
+      debuglevel="source,lines"
+      excludes="**/de/measite/smack/AndroidDebugger.java"
+    />
+    <copy todir="build/classes/trunk"><fileset dir="build/src/trunk" includes="META-INF/**" /></copy>
+    <jar
+      basedir="build/classes/trunk"
+      destfile="build/asmack-jse${jar.suffix}.jar"
+      filesonly="true"
+      level="9"
+    />
+    <zip
+      basedir="build/src/trunk"
+      destfile="build/asmack-jse-source${jar.suffix}.zip"
+      excludes="**/de/measite/smack/AndroidDebugger.java"
+      filesonly="true"
+      level="9"
+    />
+</target>
+
+<target name="check-android-exists" >
+    <available property="android.exists" file="${sdk-location}/platforms/${android.version}/android.jar" />
+    <fail unless="${android.exists}" message="Android version ${android.version} does not is not available : ${sdk-location}/platforms/${android.version}/android.jar is not found" />
+</target>
+
+<target name="compile-android" description="Compile for android" depends="check-android-exists" >
+    <delete dir="build/classes/${android.version}" failonerror="false" />
+    <mkdir dir="build/classes/${android.version}" />
+    <mkdir dir="build/classes/${android.version}/trunk" />
+    <javac
+      target="6"
+      source="6"
+      srcdir="build/src/trunk"
+      destdir="build/classes/${android.version}/trunk"
+      bootclasspath="${sdk-location}/platforms/${android.version}/android.jar:${jingle}"
+      debug="true"
+      debuglevel="source,lines"
+    />
+    <copy todir="build/classes/${android.version}/trunk">
+      <fileset dir="build/src/trunk" includes="META-INF/**" />
+    </copy>
+    <jar
+      basedir="build/classes/${android.version}/trunk"
+      destfile="build/asmack-${android.version}${jar.suffix}.jar"
+      filesonly="true"
+      level="9"
+    />
+    <zip
+      basedir="build/src/trunk"
+      destfile="build/asmack-${android.version}-source${jar.suffix}.zip"
+      filesonly="true"
+      level="9"
+    />
+</target>
+
+
+<target
+  name="compile"
+  description="Compile for jse targets"
+  depends="compile-jse"
+/>
+
+</project>
+
diff --git a/asmack-master/jingle/60-jingle-ext.patch b/asmack-master/jingle/60-jingle-ext.patch
new file mode 100644
index 0000000..4e81be5
--- /dev/null
+++ b/asmack-master/jingle/60-jingle-ext.patch
@@ -0,0 +1,171 @@
+Index: org/jivesoftware/smackx/packet/JingleContentInfo.java
+===================================================================
+--- org/jivesoftware/smackx/packet/JingleContentInfo.java	(revision 11644)
++++ org/jivesoftware/smackx/packet/JingleContentInfo.java	(working copy)
+@@ -96,7 +96,7 @@
+      */
+     public static class Audio extends JingleContentInfo {
+ 
+-        public static final String NAMESPACE = "urn:xmpp:tmp:jingle:apps:rtp";
++        public static final String NAMESPACE = "urn:xmpp:jingle:apps:rtp:1";
+ 
+         public Audio(final ContentInfo mi) {
+             super(mi);
+Index: org/jivesoftware/smackx/packet/JingleError.java
+===================================================================
+--- org/jivesoftware/smackx/packet/JingleError.java	(revision 11644)
++++ org/jivesoftware/smackx/packet/JingleError.java	(working copy)
+@@ -27,7 +27,7 @@
+ 
+ public class JingleError implements PacketExtension {
+ 
+-    public static String NAMESPACE = "urn:xmpp:tmp:jingle:errors";
++    public static String NAMESPACE = "urn:xmpp:jingle:errors:1";
+ 
+     public static final JingleError OUT_OF_ORDER = new JingleError("out-of-order");
+ 
+Index: org/jivesoftware/smackx/packet/JingleTransport.java
+===================================================================
+--- org/jivesoftware/smackx/packet/JingleTransport.java	(revision 11644)
++++ org/jivesoftware/smackx/packet/JingleTransport.java	(working copy)
+@@ -270,7 +270,7 @@
+      * RTP-ICE profile
+      */
+     public static class Ice extends JingleTransport {
+-        public static final String NAMESPACE = "urn:xmpp:tmp:jingle:transports:ice-udp";
++        public static final String NAMESPACE = "urn:xmpp:jingle:transports:ice-udp:1";
+ 
+         public Ice() {
+             super();
+@@ -352,7 +352,7 @@
+      * Raw UDP profile.
+      */
+     public static class RawUdp extends JingleTransport {
+-        public static final String NAMESPACE = "http://www.xmpp.org/extensions/xep-0177.html#ns";
++        public static final String NAMESPACE = "urn:xmpp:jingle:transports:raw-udp:1";
+ 
+         public RawUdp() {
+             super();
+Index: org/jivesoftware/smackx/packet/JingleContentDescription.java
+===================================================================
+--- org/jivesoftware/smackx/packet/JingleContentDescription.java	(revision 11644)
++++ org/jivesoftware/smackx/packet/JingleContentDescription.java	(working copy)
+@@ -66,6 +66,13 @@
+     public abstract String getNamespace();
+ 
+     /**
++     * Return the media type.
++     *
++     * @return The media type
++     */
++    public abstract String getMediaType();
++
++    /**
+      * Adds a audio payload type to the packet.
+      *
+      * @param pt the audio payload type to add.
+@@ -153,7 +160,8 @@
+         synchronized (payloads) {
+             if (payloads.size() > 0) {
+                 buf.append("<").append(getElementName());
+-                buf.append(" xmlns=\"").append(getNamespace()).append("\" >");
++                buf.append(" xmlns=\"").append(getNamespace()).append("\"");
++                buf.append(" media=\"").append(getMediaType()).append("\" >");
+ 
+                 Iterator pt = payloads.listIterator();
+                 while (pt.hasNext()) {
+@@ -172,7 +180,8 @@
+      */
+     public static class Audio extends JingleContentDescription {
+ 
+-        public static final String NAMESPACE = "urn:xmpp:tmp:jingle:apps:rtp";
++        public static final String NAMESPACE = "urn:xmpp:jingle:apps:rtp:1";
++        public static final String MEDIA_TYPE = "audio";
+ 
+         public Audio() {
+             super();
+@@ -189,6 +198,10 @@
+         public String getNamespace() {
+             return NAMESPACE;
+         }
++
++        public String getMediaType() {
++            return MEDIA_TYPE;
++        }
+     }
+ 
+     /**
+Index: org/jivesoftware/smackx/packet/Jingle.java
+===================================================================
+--- org/jivesoftware/smackx/packet/Jingle.java	(revision 11644)
++++ org/jivesoftware/smackx/packet/Jingle.java	(working copy)
+@@ -44,7 +44,7 @@
+ 
+     // static
+ 
+-    public static final String NAMESPACE = "urn:xmpp:tmp:jingle";
++    public static final String NAMESPACE = "urn:xmpp:jingle:1";
+ 
+     public static final String NODENAME = "jingle";
+ 
+Index: org/jivesoftware/smackx/packet/JingleDescription.java
+===================================================================
+--- org/jivesoftware/smackx/packet/JingleDescription.java	(revision 11644)
++++ org/jivesoftware/smackx/packet/JingleDescription.java	(working copy)
+@@ -69,6 +69,13 @@
+     public abstract String getNamespace();
+ 
+     /**
++     * Return the media type.
++     *
++     * @return The media type
++     */
++    public abstract String getMediaType();
++
++    /**
+      * Adds a audio payload type to the packet.
+      *
+      * @param pt the audio payload type to add.
+@@ -160,7 +167,8 @@
+         synchronized (payloads) {
+             if (payloads.size() > 0) {
+                 buf.append("<").append(getElementName());
+-                buf.append(" xmlns=\"").append(getNamespace()).append("\" >");
++                buf.append(" xmlns=\"").append(getNamespace()).append("\"");
++                buf.append(" media=\"").append(getMediaType()).append("\" >");
+ 
+                 for (PayloadType payloadType : payloads) {
+                     if (payloadType != null) {
+@@ -179,7 +187,8 @@
+      */
+     public static class Audio extends JingleDescription {
+ 
+-        public static final String NAMESPACE = "urn:xmpp:tmp:jingle:apps:rtp";
++        public static final String NAMESPACE = "urn:xmpp:jingle:apps:rtp:1";
++        public static final String MEDIA_TYPE = "audio";
+ 
+         public Audio() {
+             super();
+@@ -196,5 +205,9 @@
+         public String getNamespace() {
+             return NAMESPACE;
+         }
++
++        public String getMediaType() {
++            return MEDIA_TYPE;
++        }
+     }
+ }
+Index: org/jivesoftware/smackx/jingle/JingleManager.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/JingleManager.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/JingleManager.java	(working copy)
+@@ -255,7 +255,7 @@
+      */
+     public static void setJingleServiceEnabled() {
+         ProviderManager providerManager = ProviderManager.getInstance();
+-        providerManager.addIQProvider("jingle", "urn:xmpp:tmp:jingle", new JingleProvider());
++        providerManager.addIQProvider("jingle", "urn:xmpp:jingle:1", new JingleProvider());
+ 
+         // Enable the Jingle support on every established connection
+         // The ServiceDiscoveryManager class should have been already
diff --git a/asmack-master/jingle/60-remove-jingle_mediaimpl.patch b/asmack-master/jingle/60-remove-jingle_mediaimpl.patch
new file mode 100644
index 0000000..9aefc18
--- /dev/null
+++ b/asmack-master/jingle/60-remove-jingle_mediaimpl.patch
@@ -0,0 +1,4039 @@
+Index: org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaSession.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaSession.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaSession.java	(working copy)
+@@ -1,92 +0,0 @@
+-/**
+- * $RCSfile: TestMediaSession.java,v $
+- * $Revision: 1.1 $
+- * $Date: 08/11/2006
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * Unless required by applicable law or agreed to in writing, software
+- * distributed under the License is distributed on an "AS IS" BASIS,
+- * WITHOUT 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.jingle.mediaimpl.test;
+-
+-import org.jivesoftware.smackx.jingle.JingleSession;
+-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
+-import org.jivesoftware.smackx.jingle.media.PayloadType;
+-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
+-
+-/**
+- * This Class implements a complete JingleMediaSession for unit testing.
+- *
+- * @author Thiago Camargo
+- */
+-public class TestMediaSession extends JingleMediaSession {
+-
+-     /**
+-     * Creates a TestMediaSession with defined payload type, remote and local candidates
+-     *
+-     * @param payloadType Payload of the jmf
+-     * @param remote      the remote information. The candidate that the jmf will be sent to.
+-     * @param local       the local information. The candidate that will receive the jmf
+-     * @param locator     media locator
+-     */
+-    public TestMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local,
+-            final String locator, JingleSession jingleSession) {
+-        super(payloadType, remote, local, "Test", jingleSession);
+-        initialize();
+-    }
+-
+-    /**
+-     * Initialize the screen share channels.
+-     */
+-    public void initialize() {
+-
+-    }
+-
+-    /**
+-     * Starts transmission and for NAT Traversal reasons start receiving also.
+-     */
+-    public void startTrasmit() {
+-        
+-    }
+-
+-    /**
+-     * Set transmit activity. If the active is true, the instance should trasmit.
+-     * If it is set to false, the instance should pause transmit.
+-     *
+-     * @param active active state
+-     */
+-    public void setTrasmit(boolean active) {
+-        
+-    }
+-
+-    /**
+-     * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
+-     */
+-    public void startReceive() {
+-        // Do nothing
+-    }
+-
+-    /**
+-     * Stops transmission and for NAT Traversal reasons stop receiving also.
+-     */
+-    public void stopTrasmit() {
+-       
+-    }
+-
+-    /**
+-     * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
+-     */
+-    public void stopReceive() {
+-       
+-    }
+-}
+Index: org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaManager.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaManager.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaManager.java	(working copy)
+@@ -1,93 +0,0 @@
+-/**
+- * $RCSfile: TestMediaManager.java,v $
+- * $Revision: 1.3 $
+- * $Date: 25/12/2006
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * Unless required by applicable law or agreed to in writing, software
+- * distributed under the License is distributed on an "AS IS" BASIS,
+- * WITHOUT 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.jingle.mediaimpl.test;
+-
+-import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
+-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
+-import org.jivesoftware.smackx.jingle.media.PayloadType;
+-import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
+-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
+-import org.jivesoftware.smackx.jingle.JingleSession;
+-
+-import java.util.*;
+-
+-/**
+- * Implements a MediaManager for test purposes.
+- *
+- * @author Thiago Camargo
+- */
+-
+-public class TestMediaManager extends JingleMediaManager {
+-
+-    public static final String MEDIA_NAME = "TestMedia";
+-
+-    private List<PayloadType> payloads = new ArrayList<PayloadType>();
+-
+-    private PayloadType preferredPayloadType = null;
+-
+-    public TestMediaManager(JingleTransportManager transportManager) {
+-        super(transportManager);
+-    }
+-
+-    /**
+-    * Return all supported Payloads for this Manager.
+-    *
+-    * @return The Payload List
+-    */
+-    public List<PayloadType> getPayloads() {
+-        return payloads;
+-    }
+-
+-    public void setPayloads(List<PayloadType> payloads) {
+-        this.payloads.addAll(payloads);
+-    }
+-
+-    /**
+-     * Returns a new JingleMediaSession
+-     *
+-     * @param payloadType payloadType
+-     * @param remote      remote Candidate
+-     * @param local       local Candidate
+-     * @return JingleMediaSession JingleMediaSession
+-     */
+-    public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote,
+-            final TransportCandidate local, final JingleSession jingleSession) {
+-        TestMediaSession session = null;
+-
+-        session = new TestMediaSession(payloadType, remote, local, "", jingleSession);
+-
+-        return session;
+-    }
+-
+-    public PayloadType getPreferredPayloadType() {
+-        if (preferredPayloadType != null)
+-            return preferredPayloadType;
+-        return super.getPreferredPayloadType();
+-    }
+-
+-    public void setPreferredPayloadType(PayloadType preferredPayloadType) {
+-        this.preferredPayloadType = preferredPayloadType;
+-    }
+-
+-    public String getName() {
+-        return MEDIA_NAME;
+-    }
+-}
+Index: org/jivesoftware/smackx/jingle/mediaimpl/JMFInit.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/JMFInit.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/JMFInit.java	(working copy)
+@@ -1,282 +0,0 @@
+-package org.jivesoftware.smackx.jingle.mediaimpl;

+-

+-import java.awt.Frame;

+-import java.awt.TextArea;

+-import java.awt.Toolkit;

+-import java.util.Vector;

+-

+-import javax.media.Format;

+-import javax.media.PlugInManager;

+-import javax.media.Renderer;

+-import javax.media.format.AudioFormat;

+-

+-import org.jivesoftware.smackx.jingle.SmackLogger;

+-

+-import com.sun.media.ExclusiveUse;

+-import com.sun.media.util.Registry;

+-

+-public class JMFInit extends Frame implements Runnable {

+-

+-	private static final SmackLogger LOGGER = SmackLogger.getLogger(JMFInit.class);

+-

+-	private String tempDir = "/tmp";

+-

+-    private boolean done = false;

+-

+-    private String userHome;

+-

+-    private boolean visible = false;

+-

+-    public JMFInit(String[] args, boolean visible) {

+-        super("Initializing JMF...");

+-

+-        this.visible = visible;

+-

+-        Registry.set("secure.allowCaptureFromApplets", true);

+-        Registry.set("secure.allowSaveFileFromApplets", true);

+-

+-        updateTemp(args);

+-

+-        try {

+-            Registry.commit();

+-        }

+-        catch (Exception e) {

+-

+-            message("Failed to commit to JMFRegistry!");

+-        }

+-

+-        Thread detectThread = new Thread(this);

+-        detectThread.run();

+-

+-        /*

+-           * int slept = 0; while (!done && slept < 60 * 1000 * 2) { try {

+-           * Thread.currentThread().sleep(500); } catch (InterruptedException ie) { }

+-           * slept += 500; }

+-           *

+-           * if (!done) { console.error("Detection is taking too long!

+-           * Aborting!"); message("Detection is taking too long! Aborting!"); }

+-           *

+-           * try { Thread.currentThread().sleep(2000); } catch

+-           * (InterruptedException ie) { }

+-           */

+-    }

+-

+-    public void run() {

+-        detectDirectAudio();

+-        detectS8DirectAudio();

+-        detectCaptureDevices();

+-        done = true;

+-    }

+-

+-    private void updateTemp(String[] args) {

+-        if (args != null && args.length > 0) {

+-            tempDir = args[0];

+-

+-            message("Setting cache directory to " + tempDir);

+-            Registry r = new Registry();

+-            try {

+-                r.set("secure.cacheDir", tempDir);

+-                r.commit();

+-

+-                message("Updated registry");

+-            }

+-            catch (Exception e) {

+-                message("Couldn't update registry!");

+-            }

+-        }

+-    }

+-

+-    private void detectCaptureDevices() {

+-        // check if JavaSound capture is available

+-        message("Looking for Audio capturer");

+-        Class dsauto;

+-        try {

+-            dsauto = Class.forName("DirectSoundAuto");

+-            dsauto.newInstance();

+-            message("Finished detecting DirectSound capturer");

+-        }

+-        catch (ThreadDeath td) {

+-            throw td;

+-        }

+-        catch (Throwable t) {

+-            //Do nothing

+-        }

+-

+-        Class jsauto;

+-        try {

+-            jsauto = Class.forName("JavaSoundAuto");

+-            jsauto.newInstance();

+-            message("Finished detecting javasound capturer");

+-        }

+-        catch (ThreadDeath td) {

+-            throw td;

+-        }

+-        catch (Throwable t) {

+-            message("JavaSound capturer detection failed!");

+-        }

+-

+-        /*

+-        // Check if VFWAuto or SunVideoAuto is available

+-        message("Looking for video capture devices");

+-        Class auto = null;

+-        Class autoPlus = null;

+-        try {

+-            auto = Class.forName("VFWAuto");

+-        }

+-        catch (Exception e) {

+-        }

+-        if (auto == null) {

+-            try {

+-                auto = Class.forName("SunVideoAuto");

+-            }

+-            catch (Exception ee) {

+-

+-            }

+-            try {

+-                autoPlus = Class.forName("SunVideoPlusAuto");

+-            }

+-            catch (Exception ee) {

+-

+-            }

+-        }

+-        if (auto == null) {

+-            try {

+-                auto = Class.forName("V4LAuto");

+-            }

+-            catch (Exception ee) {

+-

+-            }

+-        }

+-        try {

+-            Object instance = auto.newInstance();

+-            if (autoPlus != null) {

+-                Object instancePlus = autoPlus.newInstance();

+-            }

+-

+-            message("Finished detecting video capture devices");

+-        }

+-        catch (ThreadDeath td) {

+-            throw td;

+-        }

+-        catch (Throwable t) {

+-

+-            message("Capture device detection failed!");

+-        }

+-        */

+-    }

+-

+-    private void detectDirectAudio() {

+-        Class cls;

+-        int plType = PlugInManager.RENDERER;

+-        String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";

+-        try {

+-            // Check if this is the Windows Performance Pack - hack

+-            cls = Class.forName("VFWAuto");

+-            // Check if DS capture is supported, otherwise fail DS renderer

+-            // since NT doesn't have capture

+-            cls = Class.forName("com.sun.media.protocol.dsound.DSound");

+-            // Find the renderer class and instantiate it.

+-            cls = Class.forName(dar);

+-

+-            Renderer rend = (Renderer) cls.newInstance();

+-            try {

+-                // Set the format and open the device

+-                AudioFormat af = new AudioFormat(AudioFormat.LINEAR, 44100, 16,

+-                        2);

+-                rend.setInputFormat(af);

+-                rend.open();

+-                Format[] inputFormats = rend.getSupportedInputFormats();

+-                // Register the device

+-                PlugInManager.addPlugIn(dar, inputFormats, new Format[0],

+-                        plType);

+-                // Move it to the top of the list

+-                Vector rendList = PlugInManager.getPlugInList(null, null,

+-                        plType);

+-                int listSize = rendList.size();

+-                if (rendList.elementAt(listSize - 1).equals(dar)) {

+-                    rendList.removeElementAt(listSize - 1);

+-                    rendList.insertElementAt(dar, 0);

+-                    PlugInManager.setPlugInList(rendList, plType);

+-                    PlugInManager.commit();

+-                    // Log.debug("registered");

+-                }

+-                rend.close();

+-            }

+-            catch (Throwable t) {

+-                // Log.debug("Error " + t);

+-            }

+-        }

+-        catch (Throwable tt) {

+-            //Do nothing

+-        }

+-    }

+-

+-    private void detectS8DirectAudio() {

+-        Class cls;

+-        int plType = PlugInManager.RENDERER;

+-        String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";

+-        try {

+-            // Check if this is the solaris Performance Pack - hack

+-            cls = Class.forName("SunVideoAuto");

+-

+-            // Find the renderer class and instantiate it.

+-            cls = Class.forName(dar);

+-

+-            Renderer rend = (Renderer) cls.newInstance();

+-

+-            if (rend instanceof ExclusiveUse

+-                    && !((ExclusiveUse) rend).isExclusive()) {

+-                // sol8+, DAR supports mixing

+-                Vector rendList = PlugInManager.getPlugInList(null, null,

+-                        plType);

+-                int listSize = rendList.size();

+-                boolean found = false;

+-                String rname = null;

+-

+-                for (int i = 0; i < listSize; i++) {

+-                    rname = (String) (rendList.elementAt(i));

+-                    if (rname.equals(dar)) { // DAR is in the registry

+-                        found = true;

+-                        rendList.removeElementAt(i);

+-                        break;

+-                    }

+-                }

+-

+-                if (found) {

+-                    rendList.insertElementAt(dar, 0);

+-                    PlugInManager.setPlugInList(rendList, plType);

+-                    PlugInManager.commit();

+-                }

+-            }

+-        }

+-        catch (Throwable tt) {

+-            //Do nothing

+-        }

+-    }

+-

+-    private void message(String mesg) {

+-        LOGGER.debug(mesg);

+-    }

+-

+-    private void createGUI() {

+-        TextArea textBox = new TextArea(5, 50);

+-        add("Center", textBox);

+-        textBox.setEditable(false);

+-        addNotify();

+-        pack();

+-

+-        int scrWidth = (int) Toolkit.getDefaultToolkit().getScreenSize()

+-                .getWidth();

+-        int scrHeight = (int) Toolkit.getDefaultToolkit().getScreenSize()

+-                .getHeight();

+-

+-        setLocation((scrWidth - getWidth()) / 2, (scrHeight - getHeight()) / 2);

+-

+-        setVisible(visible);

+-

+-    }

+-

+-    public static void start(boolean visible) {

+-        new JMFInit(null, visible);

+-    }

+-}

+Index: org/jivesoftware/smackx/jingle/mediaimpl/demo/Demo.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/demo/Demo.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/demo/Demo.java	(working copy)
+@@ -1,174 +0,0 @@
+-/**

+- * $RCSfile: Demo.java,v $

+- * $Revision: 1.3 $

+- * $Date: 28/12/2006

+- * <p/>

+- * Copyright 2003-2006 Jive Software.

+- * <p/>

+- * 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

+- * <p/>

+- * http://www.apache.org/licenses/LICENSE-2.0

+- * <p/>

+- * Unless required by applicable law or agreed to in writing, software

+- * distributed under the License is distributed on an "AS IS" BASIS,

+- * WITHOUT 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.jingle.mediaimpl.demo;

+-

+-import org.jivesoftware.smack.Connection;

+-import org.jivesoftware.smack.XMPPConnection;

+-import org.jivesoftware.smack.XMPPException;

+-import org.jivesoftware.smackx.jingle.JingleManager;

+-import org.jivesoftware.smackx.jingle.JingleSession;

+-import org.jivesoftware.smackx.jingle.JingleSessionRequest;

+-import org.jivesoftware.smackx.jingle.listeners.JingleSessionRequestListener;

+-import org.jivesoftware.smackx.jingle.media.JingleMediaManager;

+-import org.jivesoftware.smackx.jingle.mediaimpl.jspeex.SpeexMediaManager;

+-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.ScreenShareMediaManager;

+-import org.jivesoftware.smackx.jingle.nat.ICETransportManager;

+-import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;

+-

+-import javax.swing.*;

+-import java.awt.event.ActionEvent;

+-import java.util.ArrayList;

+-import java.util.List;

+-

+-/**

+- * Jingle Demo Application. It register in a XMPP Server and let users place calls using a full JID and auto-receive calls.

+- * Parameters: Server User Pass.

+- */

+-public class Demo extends JFrame {

+-

+-    private JingleTransportManager transportManager = null;

+-    private Connection xmppConnection = null;

+-

+-    private String server = null;

+-    private String user = null;

+-    private String pass = null;

+-

+-    private JingleManager jm = null;

+-    private JingleSession incoming = null;

+-    private JingleSession outgoing = null;

+-

+-    private JTextField jid;

+-

+-    public Demo(String server, String user, String pass) {

+-

+-        this.server = server;

+-        this.user = user;

+-        this.pass = pass;

+-        

+-        if (user.equals("jeffw")) {

+-            jid = new JTextField("eowyn" + "@" + server + "/Smack");

+-        } else {

+-            jid = new JTextField("jeffw" + "@" + server + "/Smack");

+-        }

+-

+-        xmppConnection = new XMPPConnection(server);

+-        try {

+-            xmppConnection.connect();

+-            xmppConnection.login(user, pass);

+-            initialize();

+-        }

+-        catch (XMPPException e) {

+-            e.printStackTrace();

+-        }

+-    }

+-

+-    public void initialize() {

+-        ICETransportManager icetm0 = new ICETransportManager(xmppConnection, "10.47.47.53", 3478);

+-        List<JingleMediaManager> mediaManagers = new ArrayList<JingleMediaManager>();

+-        //mediaManagers.add(new JmfMediaManager(icetm0));

+-        mediaManagers.add(new SpeexMediaManager(icetm0));

+-        mediaManagers.add(new ScreenShareMediaManager(icetm0));

+-        jm = new JingleManager(xmppConnection, mediaManagers);

+-        jm.addCreationListener(icetm0);

+-

+-        jm.addJingleSessionRequestListener(new JingleSessionRequestListener() {

+-            public void sessionRequested(JingleSessionRequest request) {

+-

+-//                if (incoming != null)

+-//                    return;

+-

+-                try {

+-                    // Accept the call

+-                    incoming = request.accept();

+-

+-                    // Start the call

+-                    incoming.startIncoming();

+-                }

+-                catch (XMPPException e) {

+-                    e.printStackTrace();

+-                }

+-

+-            }

+-        });

+-        createGUI();

+-    }

+-

+-    public void createGUI() {

+-

+-        JPanel jPanel = new JPanel();

+-

+-        jPanel.add(jid);

+-

+-        jPanel.add(new JButton(new AbstractAction("Call") {

+-            public void actionPerformed(ActionEvent e) {

+-                if (outgoing != null) return;

+-                try {

+-                    outgoing = jm.createOutgoingJingleSession(jid.getText());

+-                    outgoing.startOutgoing();

+-                }

+-                catch (XMPPException e1) {

+-                    e1.printStackTrace();

+-                }

+-            }

+-        }));

+-

+-        jPanel.add(new JButton(new AbstractAction("Hangup") {

+-            public void actionPerformed(ActionEvent e) {

+-                if (outgoing != null)

+-                    try {

+-                        outgoing.terminate();

+-                    }

+-                    catch (XMPPException e1) {

+-                        e1.printStackTrace();

+-                    }

+-                    finally {

+-                        outgoing = null;

+-                    }

+-                if (incoming != null)

+-                    try {

+-                        incoming.terminate();

+-                    }

+-                    catch (XMPPException e1) {

+-                        e1.printStackTrace();

+-                    }

+-                    finally {

+-                        incoming = null;

+-                    }

+-            }

+-        }));

+-

+-        this.add(jPanel);

+-

+-    }

+-

+-    public static void main(String args[]) {

+-

+-        Demo demo = null;

+-

+-        if (args.length > 2) {

+-            demo = new Demo(args[0], args[1], args[2]);

+-            demo.pack();

+-            demo.setVisible(true);

+-            demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

+-        }

+-

+-    }

+-

+-}

+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareSession.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareSession.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareSession.java	(working copy)
+@@ -1,206 +0,0 @@
+-/**
+- * $RCSfile: ScreenShareSession.java,v $
+- * $Revision: 1.2 $
+- * $Date: 08/11/2006
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * Unless required by applicable law or agreed to in writing, software
+- * distributed under the License is distributed on an "AS IS" BASIS,
+- * WITHOUT 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.jingle.mediaimpl.sshare;
+-
+-import java.awt.Rectangle;
+-import java.awt.event.WindowAdapter;
+-import java.awt.event.WindowEvent;
+-import java.io.IOException;
+-import java.net.DatagramSocket;
+-import java.net.InetAddress;
+-import java.net.ServerSocket;
+-import java.net.UnknownHostException;
+-
+-import javax.swing.JFrame;
+-import javax.swing.JPanel;
+-
+-import org.jivesoftware.smackx.jingle.JingleSession;
+-import org.jivesoftware.smackx.jingle.SmackLogger;
+-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
+-import org.jivesoftware.smackx.jingle.media.PayloadType;
+-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageDecoder;
+-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageEncoder;
+-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageReceiver;
+-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageTransmitter;
+-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
+-
+-/**
+- * This Class implements a complete JingleMediaSession.
+- * It sould be used to transmit and receive captured images from the Display.
+- * This Class should be automaticly controlled by JingleSession.
+- * For better NAT Traversal support this implementation don't support only receive or only transmit.
+- * To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit()
+- *
+- * @author Thiago Camargo
+- */
+-public class ScreenShareSession extends JingleMediaSession {
+-
+-	private static final SmackLogger LOGGER = SmackLogger.getLogger(ScreenShareSession.class);
+-
+-	private ImageTransmitter transmitter = null;
+-    private ImageReceiver receiver = null;
+-    private int width = 600;
+-    private int height = 600;
+-
+-    /**
+-     * Creates a org.jivesoftware.jingleaudio.jmf.AudioMediaSession with defined payload type, remote and local candidates
+-     *
+-     * @param payloadType Payload of the jmf
+-     * @param remote      the remote information. The candidate that the jmf will be sent to.
+-     * @param local       the local information. The candidate that will receive the jmf
+-     * @param locator     media locator
+-     */
+-    public ScreenShareSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local,
+-            final String locator, JingleSession jingleSession) {
+-        super(payloadType, remote, local, "Screen", jingleSession);
+-        initialize();
+-    }
+-
+-    /**
+-     * Initialize the screen share channels.
+-     */
+-    public void initialize() {
+-
+-        JingleSession session = getJingleSession();
+-        if ((session != null) && (session.getInitiator().equals(session.getConnection().getUser()))) {
+-            // If the initiator of the jingle session is us then we transmit a screen share.
+-            try {
+-                InetAddress remote = InetAddress.getByName(getRemote().getIp());
+-                transmitter = new ImageTransmitter(new DatagramSocket(getLocal().getPort()), remote, getRemote().getPort(),
+-                        new Rectangle(0, 0, width, height));
+-            } catch (Exception e) {
+-                e.printStackTrace();
+-            }
+-
+-        } else {
+-            // Otherwise we receive a screen share.
+-            JFrame window = new JFrame();
+-            JPanel jp = new JPanel();
+-            window.add(jp);
+-
+-            window.setLocation(0, 0);
+-            window.setSize(600, 600);
+-
+-            window.addWindowListener(new WindowAdapter() {
+-                public void windowClosed(WindowEvent e) {
+-                    receiver.stop();
+-                }
+-            });
+-
+-            try {
+-                receiver = new ImageReceiver(InetAddress.getByName("0.0.0.0"), getRemote().getPort(), getLocal().getPort(), width,
+-                        height);
+-                LOGGER.debug("Receiving on:" + receiver.getLocalPort());
+-            } catch (UnknownHostException e) {
+-                e.printStackTrace();
+-            }
+-
+-            jp.add(receiver);
+-            receiver.setVisible(true);
+-            window.setAlwaysOnTop(true);
+-            window.setVisible(true);
+-        }
+-    }
+-
+-    /**
+-     * Starts transmission and for NAT Traversal reasons start receiving also.
+-     */
+-    public void startTrasmit() {
+-        new Thread(transmitter).start();
+-    }
+-
+-    /**
+-     * Set transmit activity. If the active is true, the instance should trasmit.
+-     * If it is set to false, the instance should pause transmit.
+-     *
+-     * @param active active state
+-     */
+-    public void setTrasmit(boolean active) {
+-        transmitter.setTransmit(true);
+-    }
+-
+-    /**
+-     * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
+-     */
+-    public void startReceive() {
+-        // Do nothing
+-    }
+-
+-    /**
+-     * Stops transmission and for NAT Traversal reasons stop receiving also.
+-     */
+-    public void stopTrasmit() {
+-        if (transmitter != null) {
+-            transmitter.stop();
+-        }
+-    }
+-
+-    /**
+-     * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
+-     */
+-    public void stopReceive() {
+-        if (receiver != null) {
+-            receiver.stop();
+-        }
+-    }
+-
+-    /**
+-     * Obtain a free port we can use.
+-     *
+-     * @return A free port number.
+-     */
+-    protected int getFreePort() {
+-        ServerSocket ss;
+-        int freePort = 0;
+-
+-        for (int i = 0; i < 10; i++) {
+-            freePort = (int) (10000 + Math.round(Math.random() * 10000));
+-            freePort = freePort % 2 == 0 ? freePort : freePort + 1;
+-            try {
+-                ss = new ServerSocket(freePort);
+-                freePort = ss.getLocalPort();
+-                ss.close();
+-                return freePort;
+-            } catch (IOException e) {
+-                e.printStackTrace();
+-            }
+-        }
+-        try {
+-            ss = new ServerSocket(0);
+-            freePort = ss.getLocalPort();
+-            ss.close();
+-        } catch (IOException e) {
+-            e.printStackTrace();
+-        }
+-        return freePort;
+-    }
+-
+-    public void setEncoder(ImageEncoder encoder) {
+-        if (encoder != null) {
+-            this.transmitter.setEncoder(encoder);
+-        }
+-    }
+-
+-    public void setDecoder(ImageDecoder decoder) {
+-        if (decoder != null) {
+-            this.receiver.setDecoder(decoder);
+-        }
+-    }
+-}
+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageTransmitter.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageTransmitter.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageTransmitter.java	(working copy)
+@@ -1,204 +0,0 @@
+-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;

+-

+-import java.awt.AWTException;

+-import java.awt.Rectangle;

+-import java.awt.Robot;

+-import java.awt.image.BufferedImage;

+-import java.awt.image.PixelGrabber;

+-import java.io.ByteArrayOutputStream;

+-import java.io.IOException;

+-import java.net.DatagramPacket;

+-import java.net.DatagramSocket;

+-import java.net.InetAddress;

+-import java.util.Arrays;

+-

+-import org.jivesoftware.smackx.jingle.SmackLogger;

+-

+-/**

+- * UDP Image Receiver.

+- * It uses PNG Tiles into UDP packets.

+- *

+- * @author Thiago Rocha Camargo

+- */

+-public class ImageTransmitter implements Runnable {

+-

+-	private static final SmackLogger LOGGER = SmackLogger.getLogger(ImageTransmitter.class);

+-

+-	private Robot robot;

+-    private InetAddress localHost;

+-    private InetAddress remoteHost;

+-    private int localPort;

+-    private int remotePort;

+-    public static final int tileWidth = 25;

+-    private boolean on = true;

+-    private boolean transmit = false;

+-    private DatagramSocket socket;

+-    private Rectangle area;

+-    private int tiles[][][];

+-    private int maxI;

+-    private int maxJ;

+-    private ImageEncoder encoder;

+-    public final static int KEYFRAME = 10;

+-

+-    public ImageTransmitter(DatagramSocket socket, InetAddress remoteHost, int remotePort, Rectangle area) {

+-

+-        try {

+-            robot = new Robot();

+-

+-            maxI = (int) Math.ceil(area.getWidth() / tileWidth);

+-            maxJ = (int) Math.ceil(area.getHeight() / tileWidth);

+-

+-            tiles = new int[maxI][maxJ][tileWidth * tileWidth];

+-

+-            this.area = area;

+-            this.socket = socket;

+-            localHost = socket.getLocalAddress();

+-            localPort = socket.getLocalPort();

+-            this.remoteHost = remoteHost;

+-            this.remotePort = remotePort;

+-            this.encoder = new DefaultEncoder();

+-

+-            transmit = true;

+-

+-        }

+-        catch (AWTException e) {

+-            e.printStackTrace();

+-        }

+-

+-    }

+-

+-    public void start() {

+-        byte buf[] = new byte[1024];

+-        final DatagramPacket p = new DatagramPacket(buf, 1024);

+-

+-        int keyframe = 0;

+-

+-        while (on) {

+-            if (transmit) {

+-

+-                BufferedImage capture = robot.createScreenCapture(area);

+-

+-                QuantizeFilter filter = new QuantizeFilter();

+-                capture = filter.filter(capture, null);

+-

+-                long trace = System.currentTimeMillis();

+-

+-                if (++keyframe > KEYFRAME) {

+-                    keyframe = 0;

+-                }

+-                LOGGER.debug("KEYFRAME:" + keyframe);

+-

+-                for (int i = 0; i < maxI; i++) {

+-                    for (int j = 0; j < maxJ; j++) {

+-

+-                        final BufferedImage bufferedImage = capture.getSubimage(i * tileWidth, j * tileWidth, tileWidth, tileWidth);

+-

+-                        int pixels[] = new int[tileWidth * tileWidth];

+-

+-                        PixelGrabber pg = new PixelGrabber(bufferedImage, 0, 0, tileWidth, tileWidth, pixels, 0, tileWidth);

+-

+-                        try {

+-                            if (pg.grabPixels()) {

+-

+-                                if (keyframe == KEYFRAME || !Arrays.equals(tiles[i][j], pixels)) {

+-

+-                                    ByteArrayOutputStream baos = encoder.encode(bufferedImage);

+-

+-                                    if (baos != null) {

+-

+-                                        try {

+-

+-                                            Thread.sleep(1);

+-

+-                                            baos.write(i);

+-                                            baos.write(j);

+-

+-                                            byte[] bytesOut = baos.toByteArray();

+-

+-                                            if (bytesOut.length > 1000)

+-                                                LOGGER.error("Bytes out > 1000. Equals " + bytesOut.length);

+-

+-                                            p.setData(bytesOut);

+-                                            p.setAddress(remoteHost);

+-                                            p.setPort(remotePort);

+-

+-                                            try {

+-                                                socket.send(p);

+-                                            }

+-                                            catch (IOException e) {

+-                                                e.printStackTrace();

+-                                            }

+-

+-                                            tiles[i][j] = pixels;

+-

+-                                        }

+-                                        catch (Exception e) {

+-                                        }

+-

+-                                    }

+-

+-                                }

+-

+-                            }

+-                        }

+-                        catch (InterruptedException e) {

+-                            e.printStackTrace();

+-                        }

+-                    }

+-                }

+-

+-                trace = (System.currentTimeMillis() - trace);

+-                LOGGER.debug("Loop Time:" + trace);

+-

+-                if (trace < 500) {

+-                    try {

+-                        Thread.sleep(500 - trace);

+-                    }

+-                    catch (InterruptedException e) {

+-                        e.printStackTrace();

+-                    }

+-                }

+-            }

+-        }

+-    }

+-

+-    public void run() {

+-        start();

+-    }

+-

+-    /**

+-     * Set Transmit Enabled/Disabled

+-     *

+-     * @param transmit boolean Enabled/Disabled

+-     */

+-    public void setTransmit(boolean transmit) {

+-        this.transmit = transmit;

+-    }

+-

+-    /**

+-     * Get the encoder used to encode Images Tiles

+-     *

+-     * @return encoder

+-     */

+-    public ImageEncoder getEncoder() {

+-        return encoder;

+-    }

+-

+-    /**

+-     * Set the encoder used to encode Image Tiles

+-     *

+-     * @param encoder encoder

+-     */

+-    public void setEncoder(ImageEncoder encoder) {

+-        this.encoder = encoder;

+-    }

+-

+-    /**

+-     * Stops Transmitter

+-     */

+-    public void stop() {

+-        this.transmit = false;

+-        this.on = false;

+-        socket.close();

+-    }

+-}

+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageEncoder.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageEncoder.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageEncoder.java	(working copy)
+@@ -1,13 +0,0 @@
+-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
+-
+-import java.awt.image.BufferedImage;
+-import java.io.ByteArrayOutputStream;
+-
+-/**
+- * Image Encoder Interface use this interface if you want to change the default encoder
+-  *
+- * @author Thiago Rocha Camargo
+- */
+-public interface ImageEncoder {
+-    public ByteArrayOutputStream encode(BufferedImage bufferedImage);
+-}
+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/PixelUtils.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/PixelUtils.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/PixelUtils.java	(working copy)
+@@ -1,223 +0,0 @@
+-/*
+-Copyright 2006 Jerry Huxtable
+-
+-Licensed under the Apache License, Version 2.0 (the "License");
+-you may not use this file except in compliance with the License.
+-You may obtain a copy of the License at
+-
+-   http://www.apache.org/licenses/LICENSE-2.0
+-
+-Unless required by applicable law or agreed to in writing, software
+-distributed under the License is distributed on an "AS IS" BASIS,
+-WITHOUT 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.jingle.mediaimpl.sshare.api;
+-
+-import java.awt.*;
+-import java.util.Random;
+-
+-/**
+- * Some more useful math functions for image processing.
+- * These are becoming obsolete as we move to Java2D. Use MiscComposite instead.
+- */
+-public class PixelUtils {
+-
+-	public final static int REPLACE = 0;
+-	public final static int NORMAL = 1;
+-	public final static int MIN = 2;
+-	public final static int MAX = 3;
+-	public final static int ADD = 4;
+-	public final static int SUBTRACT = 5;
+-	public final static int DIFFERENCE = 6;
+-	public final static int MULTIPLY = 7;
+-	public final static int HUE = 8;
+-	public final static int SATURATION = 9;
+-	public final static int VALUE = 10;
+-	public final static int COLOR = 11;
+-	public final static int SCREEN = 12;
+-	public final static int AVERAGE = 13;
+-	public final static int OVERLAY = 14;
+-	public final static int CLEAR = 15;
+-	public final static int EXCHANGE = 16;
+-	public final static int DISSOLVE = 17;
+-	public final static int DST_IN = 18;
+-	public final static int ALPHA = 19;
+-	public final static int ALPHA_TO_GRAY = 20;
+-
+-	private static Random randomGenerator = new Random();
+-
+-	/**
+-	 * Clamp a value to the range 0..255
+-	 */
+-	public static int clamp(int c) {
+-		if (c < 0)
+-			return 0;
+-		if (c > 255)
+-			return 255;
+-		return c;
+-	}
+-
+-	public static int interpolate(int v1, int v2, float f) {
+-		return clamp((int)(v1+f*(v2-v1)));
+-	}
+-	
+-	public static int brightness(int rgb) {
+-		int r = (rgb >> 16) & 0xff;
+-		int g = (rgb >> 8) & 0xff;
+-		int b = rgb & 0xff;
+-		return (r+g+b)/3;
+-	}
+-	
+-	public static boolean nearColors(int rgb1, int rgb2, int tolerance) {
+-		int r1 = (rgb1 >> 16) & 0xff;
+-		int g1 = (rgb1 >> 8) & 0xff;
+-		int b1 = rgb1 & 0xff;
+-		int r2 = (rgb2 >> 16) & 0xff;
+-		int g2 = (rgb2 >> 8) & 0xff;
+-		int b2 = rgb2 & 0xff;
+-		return Math.abs(r1-r2) <= tolerance && Math.abs(g1-g2) <= tolerance && Math.abs(b1-b2) <= tolerance;
+-	}
+-	
+-	private final static float hsb1[] = new float[3];//FIXME-not thread safe
+-	private final static float hsb2[] = new float[3];//FIXME-not thread safe
+-	
+-	// Return rgb1 painted onto rgb2
+-	public static int combinePixels(int rgb1, int rgb2, int op) {
+-		return combinePixels(rgb1, rgb2, op, 0xff);
+-	}
+-	
+-	public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha, int channelMask) {
+-		return (rgb2 & ~channelMask) | combinePixels(rgb1 & channelMask, rgb2, op, extraAlpha);
+-	}
+-	
+-	public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha) {
+-		if (op == REPLACE)
+-			return rgb1;
+-		int a1 = (rgb1 >> 24) & 0xff;
+-		int r1 = (rgb1 >> 16) & 0xff;
+-		int g1 = (rgb1 >> 8) & 0xff;
+-		int b1 = rgb1 & 0xff;
+-		int a2 = (rgb2 >> 24) & 0xff;
+-		int r2 = (rgb2 >> 16) & 0xff;
+-		int g2 = (rgb2 >> 8) & 0xff;
+-		int b2 = rgb2 & 0xff;
+-
+-		switch (op) {
+-		case NORMAL:
+-			break;
+-		case MIN:
+-			r1 = Math.min(r1, r2);
+-			g1 = Math.min(g1, g2);
+-			b1 = Math.min(b1, b2);
+-			break;
+-		case MAX:
+-			r1 = Math.max(r1, r2);
+-			g1 = Math.max(g1, g2);
+-			b1 = Math.max(b1, b2);
+-			break;
+-		case ADD:
+-			r1 = clamp(r1+r2);
+-			g1 = clamp(g1+g2);
+-			b1 = clamp(b1+b2);
+-			break;
+-		case SUBTRACT:
+-			r1 = clamp(r2-r1);
+-			g1 = clamp(g2-g1);
+-			b1 = clamp(b2-b1);
+-			break;
+-		case DIFFERENCE:
+-			r1 = clamp(Math.abs(r1-r2));
+-			g1 = clamp(Math.abs(g1-g2));
+-			b1 = clamp(Math.abs(b1-b2));
+-			break;
+-		case MULTIPLY:
+-			r1 = clamp(r1*r2/255);
+-			g1 = clamp(g1*g2/255);
+-			b1 = clamp(b1*b2/255);
+-			break;
+-		case DISSOLVE:
+-			if ((randomGenerator.nextInt() & 0xff) <= a1) {
+-				r1 = r2;
+-				g1 = g2;
+-				b1 = b2;
+-			}
+-			break;
+-		case AVERAGE:
+-			r1 = (r1+r2)/2;
+-			g1 = (g1+g2)/2;
+-			b1 = (b1+b2)/2;
+-			break;
+-		case HUE:
+-		case SATURATION:
+-		case VALUE:
+-		case COLOR:
+-			Color.RGBtoHSB(r1, g1, b1, hsb1);
+-			Color.RGBtoHSB(r2, g2, b2, hsb2);
+-			switch (op) {
+-			case HUE:
+-				hsb2[0] = hsb1[0];
+-				break;
+-			case SATURATION:
+-				hsb2[1] = hsb1[1];
+-				break;
+-			case VALUE:
+-				hsb2[2] = hsb1[2];
+-				break;
+-			case COLOR:
+-				hsb2[0] = hsb1[0];
+-				hsb2[1] = hsb1[1];
+-				break;
+-			}
+-			rgb1 = Color.HSBtoRGB(hsb2[0], hsb2[1], hsb2[2]);
+-			r1 = (rgb1 >> 16) & 0xff;
+-			g1 = (rgb1 >> 8) & 0xff;
+-			b1 = rgb1 & 0xff;
+-			break;
+-		case SCREEN:
+-			r1 = 255 - ((255 - r1) * (255 - r2)) / 255;
+-			g1 = 255 - ((255 - g1) * (255 - g2)) / 255;
+-			b1 = 255 - ((255 - b1) * (255 - b2)) / 255;
+-			break;
+-		case OVERLAY:
+-			int m, s;
+-			s = 255 - ((255 - r1) * (255 - r2)) / 255;
+-			m = r1 * r2 / 255;
+-			r1 = (s * r1 + m * (255 - r1)) / 255;
+-			s = 255 - ((255 - g1) * (255 - g2)) / 255;
+-			m = g1 * g2 / 255;
+-			g1 = (s * g1 + m * (255 - g1)) / 255;
+-			s = 255 - ((255 - b1) * (255 - b2)) / 255;
+-			m = b1 * b2 / 255;
+-			b1 = (s * b1 + m * (255 - b1)) / 255;
+-			break;
+-		case CLEAR:
+-			r1 = g1 = b1 = 0xff;
+-			break;
+-		case DST_IN:
+-			r1 = clamp((r2*a1)/255);
+-			g1 = clamp((g2*a1)/255);
+-			b1 = clamp((b2*a1)/255);
+-			a1 = clamp((a2*a1)/255);
+-			return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1;
+-		case ALPHA:
+-			a1 = a1*a2/255;
+-			return (a1 << 24) | (r2 << 16) | (g2 << 8) | b2;
+-		case ALPHA_TO_GRAY:
+-			int na = 255-a1;
+-			return (a1 << 24) | (na << 16) | (na << 8) | na;
+-		}
+-		if (extraAlpha != 0xff || a1 != 0xff) {
+-			a1 = a1*extraAlpha/255;
+-			int a3 = (255-a1)*a2/255;
+-			r1 = clamp((r1*a1+r2*a3)/255);
+-			g1 = clamp((g1*a1+g2*a3)/255);
+-			b1 = clamp((b1*a1+b2*a3)/255);
+-			a1 = clamp(a1+a3);
+-		}
+-		return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1;
+-	}
+-
+-}
+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/Quantizer.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/Quantizer.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/Quantizer.java	(working copy)
+@@ -1,53 +0,0 @@
+-/*
+-Copyright 2006 Jerry Huxtable
+-
+-Licensed under the Apache License, Version 2.0 (the "License");
+-you may not use this file except in compliance with the License.
+-You may obtain a copy of the License at
+-
+-   http://www.apache.org/licenses/LICENSE-2.0
+-
+-Unless required by applicable law or agreed to in writing, software
+-distributed under the License is distributed on an "AS IS" BASIS,
+-WITHOUT 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.jingle.mediaimpl.sshare.api;
+-
+-/**
+- * The interface for an image quantizer. The addColor method is called (repeatedly
+- * if necessary) with all the image pixels. A color table can then be returned by 
+- * calling the buildColorTable method.
+- */
+-public interface Quantizer {
+-	/**
+-	 * Initialize the quantizer. This should be called before adding any pixels.
+-	 * @param numColors the number of colors we're quantizing to.
+-	 */
+-	public void setup(int numColors);
+-	
+-	/**
+-	 * Add pixels to the quantizer.
+-	 * @param pixels the array of ARGB pixels
+-	 * @param offset the offset into the array
+-	 * @param count the count of pixels
+-	 */
+-	public void addPixels(int[] pixels, int offset, int count);
+-	
+-	/**
+-	 * Build a color table from the added pixels.
+-	 * @return an array of ARGB pixels representing a color table
+-	 */
+-	public int[] buildColorTable();
+-	
+-	/**
+-	 * Using the previously-built color table, return the index into that table for a pixel.
+-	 * This is guaranteed to return a valid index - returning the index of a color closer
+-	 * to that requested if necessary. 
+-	 * @param rgb the pixel to find
+-	 * @return the pixel's index in the color table
+-	 */
+-	public int getIndexForColor(int rgb);
+-}
+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultEncoder.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultEncoder.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultEncoder.java	(working copy)
+@@ -1,24 +0,0 @@
+-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
+-
+-import javax.imageio.ImageIO;
+-import java.awt.image.BufferedImage;
+-import java.io.ByteArrayOutputStream;
+-import java.io.IOException;
+-
+-/**
+- * Implements a default PNG Encoder
+- */
+-public class DefaultEncoder implements ImageEncoder{
+-
+-    public ByteArrayOutputStream encode(BufferedImage bufferedImage) {
+-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+-        try {
+-            ImageIO.write(bufferedImage, "png", baos);
+-        }
+-        catch (IOException e) {
+-            e.printStackTrace();
+-            baos = null;
+-        }
+-        return baos;
+-    }
+-}
+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/QuantizeFilter.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/QuantizeFilter.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/QuantizeFilter.java	(working copy)
+@@ -1,178 +0,0 @@
+-/*
+-Copyright 2006 Jerry Huxtable
+-
+-Licensed under the Apache License, Version 2.0 (the "License");
+-you may not use this file except in compliance with the License.
+-You may obtain a copy of the License at
+-
+-   http://www.apache.org/licenses/LICENSE-2.0
+-
+-Unless required by applicable law or agreed to in writing, software
+-distributed under the License is distributed on an "AS IS" BASIS,
+-WITHOUT 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.jingle.mediaimpl.sshare.api;
+-
+-import java.awt.*;
+-
+-/**
+- * A filter which quantizes an image to a set number of colors - useful for producing
+- * images which are to be encoded using an index color model. The filter can perform
+- * Floyd-Steinberg error-diffusion dithering if required. At present, the quantization
+- * is done using an octtree algorithm but I eventually hope to add more quantization
+- * methods such as median cut. Note: at present, the filter produces an image which
+- * uses the RGB color model (because the application it was written for required it).
+- * I hope to extend it to produce an IndexColorModel by request.
+- */
+-public class QuantizeFilter extends WholeImageFilter {
+-
+-	/**
+-	 * Floyd-Steinberg dithering matrix.
+-	 */
+-	protected final static int[] matrix = {
+-	 	 0, 0, 0,
+-	 	 0, 0, 7,
+-	 	 3, 5, 1,
+-	};
+-	private int sum = 3+5+7+1;
+-
+-	private boolean dither;
+-	private int numColors = 256;
+-	private boolean serpentine = true;
+-
+-	/**
+-	 * Set the number of colors to quantize to.
+-	 * @param numColors the number of colors. The default is 256.
+-	 */
+-	public void setNumColors(int numColors) {
+-		this.numColors = Math.min(Math.max(numColors, 8), 256);
+-	}
+-
+-	/**
+-	 * Get the number of colors to quantize to.
+-	 * @return the number of colors.
+-	 */
+-	public int getNumColors() {
+-		return numColors;
+-	}
+-
+-	/**
+-	 * Set whether to use dithering or not. If not, the image is posterized.
+-	 * @param dither true to use dithering
+-	 */
+-	public void setDither(boolean dither) {
+-		this.dither = dither;
+-	}
+-
+-	/**
+-	 * Return the dithering setting
+-	 * @return the current setting
+-	 */
+-	public boolean getDither() {
+-		return dither;
+-	}
+-
+-	/**
+-	 * Set whether to use a serpentine pattern for return or not. This can reduce 'avalanche' artifacts in the output.
+-	 * @param serpentine true to use serpentine pattern
+-	 */
+-	public void setSerpentine(boolean serpentine) {
+-		this.serpentine = serpentine;
+-	}
+-	
+-	/**
+-	 * Return the serpentine setting
+-	 * @return the current setting
+-	 */
+-	public boolean getSerpentine() {
+-		return serpentine;
+-	}
+-	
+-	public void quantize(int[] inPixels, int[] outPixels, int width, int height, int numColors, boolean dither, boolean serpentine) {
+-		int count = width*height;
+-		Quantizer quantizer = new OctTreeQuantizer();
+-		quantizer.setup(numColors);
+-		quantizer.addPixels(inPixels, 0, count);
+-		int[] table =  quantizer.buildColorTable();
+-
+-		if (!dither) {
+-			for (int i = 0; i < count; i++)
+-				outPixels[i] = table[quantizer.getIndexForColor(inPixels[i])];
+-		} else {
+-			int index = 0;
+-			for (int y = 0; y < height; y++) {
+-				boolean reverse = serpentine && (y & 1) == 1;
+-				int direction;
+-				if (reverse) {
+-					index = y*width+width-1;
+-					direction = -1;
+-				} else {
+-					index = y*width;
+-					direction = 1;
+-				}
+-				for (int x = 0; x < width; x++) {
+-					int rgb1 = inPixels[index];
+-					int rgb2 = table[quantizer.getIndexForColor(rgb1)];
+-
+-					outPixels[index] = rgb2;
+-
+-					int r1 = (rgb1 >> 16) & 0xff;
+-					int g1 = (rgb1 >> 8) & 0xff;
+-					int b1 = rgb1 & 0xff;
+-
+-					int r2 = (rgb2 >> 16) & 0xff;
+-					int g2 = (rgb2 >> 8) & 0xff;
+-					int b2 = rgb2 & 0xff;
+-
+-					int er = r1-r2;
+-					int eg = g1-g2;
+-					int eb = b1-b2;
+-
+-					for (int i = -1; i <= 1; i++) {
+-						int iy = i+y;
+-						if (0 <= iy && iy < height) {
+-							for (int j = -1; j <= 1; j++) {
+-								int jx = j+x;
+-								if (0 <= jx && jx < width) {
+-									int w;
+-									if (reverse)
+-										w = matrix[(i+1)*3-j+1];
+-									else
+-										w = matrix[(i+1)*3+j+1];
+-									if (w != 0) {
+-										int k = reverse ? index - j : index + j;
+-										rgb1 = inPixels[k];
+-										r1 = (rgb1 >> 16) & 0xff;
+-										g1 = (rgb1 >> 8) & 0xff;
+-										b1 = rgb1 & 0xff;
+-										r1 += er * w/sum;
+-										g1 += eg * w/sum;
+-										b1 += eb * w/sum;
+-										inPixels[k] = (PixelUtils.clamp(r1) << 16) | (PixelUtils.clamp(g1) << 8) | PixelUtils.clamp(b1);
+-									}
+-								}
+-							}
+-						}
+-					}
+-					index += direction;
+-				}
+-			}
+-		}
+-	}
+-
+-	protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) {
+-		int[] outPixels = new int[width*height];
+-		
+-		quantize(inPixels, outPixels, width, height, numColors, dither, serpentine);
+-
+-		return outPixels;
+-	}
+-
+-	public String toString() {
+-		return "Colors/Quantize...";
+-	}
+-	
+-}
+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageReceiver.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageReceiver.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageReceiver.java	(working copy)
+@@ -1,150 +0,0 @@
+-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;

+-

+-import java.awt.*;

+-import java.awt.image.BufferedImage;

+-import java.io.ByteArrayInputStream;

+-import java.io.IOException;

+-import java.net.DatagramPacket;

+-import java.net.DatagramSocket;

+-import java.net.InetAddress;

+-import java.net.SocketException;

+-

+-/**

+- * UDP Image Receiver.

+- * It uses PNG Tiles into UDP packets.

+- *

+- * @author Thiago Rocha Camargo

+- */

+-public class ImageReceiver extends Canvas {

+-

+-    private boolean on = true;

+-    private DatagramSocket socket;

+-    private BufferedImage tiles[][];

+-    private static final int tileWidth = ImageTransmitter.tileWidth;

+-    private InetAddress localHost;

+-    private InetAddress remoteHost;

+-    private int localPort;

+-    private int remotePort;

+-    private ImageDecoder decoder;

+-

+-    public ImageReceiver(final InetAddress remoteHost, final int remotePort, final int localPort, int width, int height) {

+-        tiles = new BufferedImage[width][height];

+-

+-        try {

+-

+-            socket = new DatagramSocket(localPort);

+-            localHost = socket.getLocalAddress();

+-            this.remoteHost = remoteHost;

+-            this.remotePort = remotePort;

+-            this.localPort = localPort;

+-            this.decoder = new DefaultDecoder();

+-

+-            new Thread(new Runnable() {

+-                public void run() {

+-                    byte buf[] = new byte[1024];

+-                    DatagramPacket p = new DatagramPacket(buf, 1024);

+-                    try {

+-                        while (on) {

+-                            socket.receive(p);

+-

+-                            int length = p.getLength();

+-

+-                            BufferedImage bufferedImage = decoder.decode(new ByteArrayInputStream(p.getData(), 0, length - 2));

+-

+-                            if (bufferedImage != null) {

+-

+-                                int x = p.getData()[length - 2];

+-                                int y = p.getData()[length - 1];

+-

+-                                drawTile(x, y, bufferedImage);

+-

+-                            }

+-

+-                        }

+-                    }

+-                    catch (IOException e) {

+-                        e.printStackTrace();

+-                    }

+-                }

+-            }).start();

+-

+-            new Thread(new Runnable() {

+-                public void run() {

+-                    byte buf[] = new byte[1024];

+-                    DatagramPacket p = new DatagramPacket(buf, 1024);

+-                    try {

+-                        while (on) {

+-

+-                            p.setAddress(remoteHost);

+-                            p.setPort(remotePort);

+-                            socket.send(p);

+-

+-                            try {

+-                                Thread.sleep(1000);

+-                            }

+-                            catch (InterruptedException e) {

+-                                e.printStackTrace();

+-                            }

+-

+-                        }

+-                    }

+-                    catch (IOException e) {

+-                        e.printStackTrace();

+-                    }

+-                }

+-            }).start();

+-

+-        }

+-        catch (SocketException e) {

+-            e.printStackTrace();

+-        }

+-        this.setSize(width, height);

+-    }

+-

+-    public InetAddress getLocalHost() {

+-        return localHost;

+-    }

+-

+-    public InetAddress getRemoteHost() {

+-        return remoteHost;

+-    }

+-

+-    public int getLocalPort() {

+-        return localPort;

+-    }

+-

+-    public int getRemotePort() {

+-        return remotePort;

+-    }

+-

+-    public DatagramSocket getDatagramSocket() {

+-        return socket;

+-    }

+-

+-    public void drawTile(int x, int y, BufferedImage bufferedImage) {

+-        tiles[x][y] = bufferedImage;

+-        //repaint(x * tileWidth, y * tileWidth, tileWidth, tileWidth);

+-        this.getGraphics().drawImage(bufferedImage, tileWidth * x, tileWidth * y, this);

+-    }

+-

+-    public void paint(Graphics g) {

+-        for (int i = 0; i < tiles.length; i++) {

+-            for (int j = 0; j < tiles[0].length; j++) {

+-                g.drawImage(tiles[i][j], tileWidth * i, tileWidth * j, this);

+-            }

+-        }

+-    }

+-

+-    public ImageDecoder getDecoder() {

+-        return decoder;

+-    }

+-

+-    public void setDecoder(ImageDecoder decoder) {

+-        this.decoder = decoder;

+-    }

+-

+-    public void stop(){

+-        this.on=false;

+-        socket.close();

+-    }

+-}

+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/WholeImageFilter.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/WholeImageFilter.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/WholeImageFilter.java	(working copy)
+@@ -1,86 +0,0 @@
+-/*
+-Copyright 2006 Jerry Huxtable
+-
+-Licensed under the Apache License, Version 2.0 (the "License");
+-you may not use this file except in compliance with the License.
+-You may obtain a copy of the License at
+-
+-   http://www.apache.org/licenses/LICENSE-2.0
+-
+-Unless required by applicable law or agreed to in writing, software
+-distributed under the License is distributed on an "AS IS" BASIS,
+-WITHOUT 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.jingle.mediaimpl.sshare.api;
+-
+-import java.awt.*;
+-import java.awt.image.BufferedImage;
+-import java.awt.image.ColorModel;
+-import java.awt.image.WritableRaster;
+-
+-/**
+- * A filter which acts as a superclass for filters which need to have the whole image in memory
+- * to do their stuff.
+- */
+-public abstract class WholeImageFilter extends AbstractBufferedImageOp {
+-
+-	/**
+-     * The output image bounds.
+-     */
+-    protected Rectangle transformedSpace;
+-
+-	/**
+-     * The input image bounds.
+-     */
+-	protected Rectangle originalSpace;
+-	
+-	/**
+-	 * Construct a WholeImageFilter.
+-	 */
+-	public WholeImageFilter() {
+-	}
+-
+-    public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
+-        int width = src.getWidth();
+-        int height = src.getHeight();
+-		int type = src.getType();
+-		WritableRaster srcRaster = src.getRaster();
+-
+-		originalSpace = new Rectangle(0, 0, width, height);
+-		transformedSpace = new Rectangle(0, 0, width, height);
+-		transformSpace(transformedSpace);
+-
+-        if ( dst == null ) {
+-            ColorModel dstCM = src.getColorModel();
+-			dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(transformedSpace.width, transformedSpace.height), dstCM.isAlphaPremultiplied(), null);
+-		}
+-		WritableRaster dstRaster = dst.getRaster();
+-
+-		int[] inPixels = getRGB( src, 0, 0, width, height, null );
+-		inPixels = filterPixels( width, height, inPixels, transformedSpace );
+-		setRGB( dst, 0, 0, transformedSpace.width, transformedSpace.height, inPixels );
+-
+-        return dst;
+-    }
+-
+-	/**
+-     * Calculate output bounds for given input bounds.
+-     * @param rect input and output rectangle
+-     */
+-	protected void transformSpace(Rectangle rect) {
+-	}
+-	
+-	/**
+-     * Actually filter the pixels.
+-     * @param width the image width
+-     * @param height the image height
+-     * @param inPixels the image pixels
+-     * @param transformedSpace the output bounds
+-     * @return the output pixels
+-     */
+-	protected abstract int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace );
+-}
+-
+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/AbstractBufferedImageOp.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/AbstractBufferedImageOp.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/AbstractBufferedImageOp.java	(working copy)
+@@ -1,98 +0,0 @@
+-/*
+-Copyright 2006 Jerry Huxtable
+-
+-Licensed under the Apache License, Version 2.0 (the "License");
+-you may not use this file except in compliance with the License.
+-You may obtain a copy of the License at
+-
+-   http://www.apache.org/licenses/LICENSE-2.0
+-
+-Unless required by applicable law or agreed to in writing, software
+-distributed under the License is distributed on an "AS IS" BASIS,
+-WITHOUT 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.jingle.mediaimpl.sshare.api;
+-
+-import java.awt.*;
+-import java.awt.geom.Point2D;
+-import java.awt.geom.Rectangle2D;
+-import java.awt.image.BufferedImage;
+-import java.awt.image.BufferedImageOp;
+-import java.awt.image.ColorModel;
+-
+-/**
+- * A convenience class which implements those methods of BufferedImageOp which are rarely changed.
+- */
+-public abstract class AbstractBufferedImageOp implements BufferedImageOp, Cloneable {
+-
+-    public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
+-        if ( dstCM == null )
+-            dstCM = src.getColorModel();
+-        return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), null);
+-    }
+-    
+-    public Rectangle2D getBounds2D( BufferedImage src ) {
+-        return new Rectangle(0, 0, src.getWidth(), src.getHeight());
+-    }
+-    
+-    public Point2D getPoint2D( Point2D srcPt, Point2D dstPt ) {
+-        if ( dstPt == null )
+-            dstPt = new Point2D.Double();
+-        dstPt.setLocation( srcPt.getX(), srcPt.getY() );
+-        return dstPt;
+-    }
+-
+-    public RenderingHints getRenderingHints() {
+-        return null;
+-    }
+-
+-	/**
+-	 * A convenience method for getting ARGB pixels from an image. This tries to avoid the performance
+-	 * penalty of BufferedImage.getRGB unmanaging the image.
+-     * @param image   a BufferedImage object
+-     * @param x       the left edge of the pixel block
+-     * @param y       the right edge of the pixel block
+-     * @param width   the width of the pixel arry
+-     * @param height  the height of the pixel arry
+-     * @param pixels  the array to hold the returned pixels. May be null.
+-     * @return the pixels
+-     * @see #setRGB
+-     */
+-	public int[] getRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) {
+-		int type = image.getType();
+-		if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB )
+-			return (int [])image.getRaster().getDataElements( x, y, width, height, pixels );
+-		return image.getRGB( x, y, width, height, pixels, 0, width );
+-    }
+-
+-	/**
+-	 * A convenience method for setting ARGB pixels in an image. This tries to avoid the performance
+-	 * penalty of BufferedImage.setRGB unmanaging the image.
+-     * @param image   a BufferedImage object
+-     * @param x       the left edge of the pixel block
+-     * @param y       the right edge of the pixel block
+-     * @param width   the width of the pixel arry
+-     * @param height  the height of the pixel arry
+-     * @param pixels  the array of pixels to set
+-     * @see #getRGB
+-	 */
+-	public void setRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) {
+-		int type = image.getType();
+-		if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB )
+-			image.getRaster().setDataElements( x, y, width, height, pixels );
+-		else
+-			image.setRGB( x, y, width, height, pixels, 0, width );
+-    }
+-
+-	public Object clone() {
+-		try {
+-			return super.clone();
+-		}
+-		catch ( CloneNotSupportedException e ) {
+-			return null;
+-		}
+-	}
+-}
+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageDecoder.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageDecoder.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageDecoder.java	(working copy)
+@@ -1,15 +0,0 @@
+-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
+-
+-import java.awt.image.BufferedImage;
+-import java.io.ByteArrayInputStream;
+-import java.io.IOException;
+-
+-/**
+- * Image Decoder Interface use this interface if you want to change the default decoder
+- *
+- * @author Thiago Rocha Camargo
+- */
+-public interface ImageDecoder {
+-
+-    public BufferedImage decode(ByteArrayInputStream stream) throws IOException;
+-}
+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/OctTreeQuantizer.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/OctTreeQuantizer.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/OctTreeQuantizer.java	(working copy)
+@@ -1,287 +0,0 @@
+-/*
+-Copyright 2006 Jerry Huxtable
+-
+-Licensed under the Apache License, Version 2.0 (the "License");
+-you may not use this file except in compliance with the License.
+-You may obtain a copy of the License at
+-
+-   http://www.apache.org/licenses/LICENSE-2.0
+-
+-Unless required by applicable law or agreed to in writing, software
+-distributed under the License is distributed on an "AS IS" BASIS,
+-WITHOUT 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.jingle.mediaimpl.sshare.api;
+-
+-import java.io.PrintStream;
+-import java.util.Vector;
+-
+-import org.jivesoftware.smackx.jingle.SmackLogger;
+-
+-/**
+- * An image Quantizer based on the Octree algorithm. This is a very basic implementation
+- * at present and could be much improved by picking the nodes to reduce more carefully 
+- * (i.e. not completely at random) when I get the time.
+- */
+-public class OctTreeQuantizer implements Quantizer {
+-
+-	private static final SmackLogger LOGGER = SmackLogger.getLogger(OctTreeQuantizer.class);
+-
+-	/**
+-	 * The greatest depth the tree is allowed to reach
+-	 */
+-	final static int MAX_LEVEL = 5;
+-
+-	/**
+-	 * An Octtree node.
+-	 */
+-	class OctTreeNode {
+-		int children;
+-		int level;
+-		OctTreeNode parent;
+-		OctTreeNode leaf[] = new OctTreeNode[8];
+-		boolean isLeaf;
+-		int count;
+-		int	totalRed;
+-		int	totalGreen;
+-		int	totalBlue;
+-		int index;
+-		
+-		/**
+-		 * A debugging method which prints the tree out.
+-		 */
+-		public void list(PrintStream s, int level) {
+-			String indentStr = "";
+-			for (int i = 0; i < level; i++)
+-				indentStr += " ";
+-			if (count == 0)
+-				LOGGER.debug(indentStr + index + ": count=" + count);
+-			else
+-				LOGGER.debug(indentStr + index + ": count=" + count + " red=" + (totalRed/count) + " green=" + (totalGreen / count) + " blue=" + (totalBlue / count));
+-			for (int i = 0; i < 8; i++)
+-				if (leaf[i] != null)
+-					leaf[i].list(s, level+2);
+-		}
+-	}
+-
+-	private int nodes = 0;
+-	private OctTreeNode root;
+-	private int reduceColors;
+-	private int maximumColors;
+-	private int colors = 0;
+-	private Vector[] colorList;
+-	
+-	public OctTreeQuantizer() {
+-		setup(256);
+-		colorList = new Vector[MAX_LEVEL+1];
+-		for (int i = 0; i < MAX_LEVEL+1; i++)
+-			colorList[i] = new Vector();
+-		root = new OctTreeNode();
+-	}
+-
+-	/**
+-	 * Initialize the quantizer. This should be called before adding any pixels.
+-	 * @param numColors the number of colors we're quantizing to.
+-	 */
+-	public void setup(int numColors) {
+-		maximumColors = numColors;
+-		reduceColors = Math.max(512, numColors * 2);
+-	}
+-	
+-	/**
+-	 * Add pixels to the quantizer.
+-	 * @param pixels the array of ARGB pixels
+-	 * @param offset the offset into the array
+-	 * @param count the count of pixels
+-	 */
+-	public void addPixels(int[] pixels, int offset, int count) {
+-		for (int i = 0; i < count; i++) {
+-			insertColor(pixels[i+offset]);
+-			if (colors > reduceColors)
+-				reduceTree(reduceColors);
+-		}
+-	}	
+-
+-    /**
+-     * Get the color table index for a color.
+-     * @param rgb the color
+-     * @return the index
+-     */
+-	public int getIndexForColor(int rgb) {
+-		int red = (rgb >> 16) & 0xff;
+-		int green = (rgb >> 8) & 0xff;
+-		int blue = rgb & 0xff;
+-
+-		OctTreeNode node = root;
+-
+-		for (int level = 0; level <= MAX_LEVEL; level++) {
+-			OctTreeNode child;
+-			int bit = 0x80 >> level;
+-
+-			int index = 0;
+-			if ((red & bit) != 0)
+-				index += 4;
+-			if ((green & bit) != 0)
+-				index += 2;
+-			if ((blue & bit) != 0)
+-				index += 1;
+-
+-			child = node.leaf[index];
+-
+-			if (child == null)
+-				return node.index;
+-			else if (child.isLeaf)
+-				return child.index;
+-			else
+-				node = child;
+-		}
+-		LOGGER.debug("getIndexForColor failed");
+-		return 0;
+-	}
+-
+-	private void insertColor(int rgb) {
+-		int red = (rgb >> 16) & 0xff;
+-		int green = (rgb >> 8) & 0xff;
+-		int blue = rgb & 0xff;
+-
+-		OctTreeNode node = root;
+-
+-//		LOGGER.debug("insertColor="+Integer.toHexString(rgb));
+-		for (int level = 0; level <= MAX_LEVEL; level++) {
+-			OctTreeNode child;
+-			int bit = 0x80 >> level;
+-
+-			int index = 0;
+-			if ((red & bit) != 0)
+-				index += 4;
+-			if ((green & bit) != 0)
+-				index += 2;
+-			if ((blue & bit) != 0)
+-				index += 1;
+-
+-			child = node.leaf[index];
+-
+-			if (child == null) {
+-				node.children++;
+-
+-				child = new OctTreeNode();
+-				child.parent = node;
+-				node.leaf[index] = child;
+-				node.isLeaf = false;
+-				nodes++;
+-				colorList[level].addElement(child);
+-
+-				if (level == MAX_LEVEL) {
+-					child.isLeaf = true;
+-					child.count = 1;
+-					child.totalRed = red;
+-					child.totalGreen = green;
+-					child.totalBlue = blue;
+-					child.level = level;
+-					colors++;
+-					return;
+-				}
+-
+-				node = child;
+-			} else if (child.isLeaf) {
+-				child.count++;
+-				child.totalRed += red;
+-				child.totalGreen += green;
+-				child.totalBlue += blue;
+-				return;
+-			} else
+-				node = child;
+-		}
+-		LOGGER.debug("insertColor failed");
+-	}
+-
+-	private void reduceTree(int numColors) {
+-		for (int level = MAX_LEVEL-1; level >= 0; level--) {
+-			Vector v = colorList[level];
+-			if (v != null && v.size() > 0) {
+-				for (int j = 0; j < v.size(); j++) {
+-					OctTreeNode node = (OctTreeNode)v.elementAt(j);
+-					if (node.children > 0) {
+-						for (int i = 0; i < 8; i++) {
+-							OctTreeNode child = node.leaf[i];
+-							if (child != null) {
+-								if (!child.isLeaf)
+-									LOGGER.debug("not a leaf!");
+-								node.count += child.count;
+-								node.totalRed += child.totalRed;
+-								node.totalGreen += child.totalGreen;
+-								node.totalBlue += child.totalBlue;
+-								node.leaf[i] = null;
+-								node.children--;
+-								colors--;
+-								nodes--;
+-								colorList[level+1].removeElement(child);
+-							}
+-						}
+-						node.isLeaf = true;
+-						colors++;
+-						if (colors <= numColors)
+-							return;
+-					}
+-				}
+-			}
+-		}
+-
+-		LOGGER.debug("Unable to reduce the OctTree");
+-	}
+-
+-    /**
+-     * Build the color table.
+-     * @return the color table
+-     */
+-	public int[] buildColorTable() {
+-		int[] table = new int[colors];
+-		buildColorTable(root, table, 0);
+-		return table;
+-	}
+-	
+-	/**
+-	 * A quick way to use the quantizer. Just create a table the right size and pass in the pixels.
+-     * @param inPixels the input colors
+-     * @param table the output color table
+-     */
+-	public void buildColorTable(int[] inPixels, int[] table) {
+-		int count = inPixels.length;
+-		maximumColors = table.length;
+-		for (int i = 0; i < count; i++) {
+-			insertColor(inPixels[i]);
+-			if (colors > reduceColors)
+-				reduceTree(reduceColors);
+-		}
+-		if (colors > maximumColors)
+-			reduceTree(maximumColors);
+-		buildColorTable(root, table, 0);
+-	}
+-
+-	private int buildColorTable(OctTreeNode node, int[] table, int index) {
+-		if (colors > maximumColors)
+-			reduceTree(maximumColors);
+-
+-		if (node.isLeaf) {
+-			int count = node.count;
+-			table[index] = 0xff000000 |
+-				((node.totalRed/count) << 16) |
+-				((node.totalGreen/count) << 8) |
+-				node.totalBlue/count;
+-			node.index = index++;
+-		} else {
+-			for (int i = 0; i < 8; i++) {
+-				if (node.leaf[i] != null) {
+-					node.index = index;
+-					index = buildColorTable(node.leaf[i], table, index);
+-				}
+-			}
+-		}
+-		return index;
+-	}
+-	
+-}
+-
+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultDecoder.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultDecoder.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultDecoder.java	(working copy)
+@@ -1,16 +0,0 @@
+-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
+-
+-import javax.imageio.ImageIO;
+-import java.awt.image.BufferedImage;
+-import java.io.ByteArrayInputStream;
+-import java.io.IOException;
+-
+-/**
+- * Implements a default PNG decoder.
+- */
+-public class DefaultDecoder implements ImageDecoder {
+-
+-    public BufferedImage decode(ByteArrayInputStream stream) throws IOException {
+-        return ImageIO.read(stream);
+-    }
+-}
+Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareMediaManager.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareMediaManager.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareMediaManager.java	(working copy)
+@@ -1,115 +0,0 @@
+-/**
+- * $RCSfile: ScreenShareMediaManager.java,v $
+- * $Revision: 1.3 $
+- * $Date: 25/12/2006
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * Unless required by applicable law or agreed to in writing, software
+- * distributed under the License is distributed on an "AS IS" BASIS,
+- * WITHOUT 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.jingle.mediaimpl.sshare;
+-
+-import org.jivesoftware.smackx.jingle.JingleSession;
+-import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
+-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
+-import org.jivesoftware.smackx.jingle.media.PayloadType;
+-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageDecoder;
+-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageEncoder;
+-import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
+-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
+-
+-import java.util.ArrayList;
+-import java.util.List;
+-
+-/**
+- * Implements a JingleMediaManager for ScreenSharing.
+- * It currently uses an Audio payload Type. Which needs to be fixed in the next version.
+- *
+- * @author Thiago Camargo
+- */
+-
+-public class ScreenShareMediaManager extends JingleMediaManager {
+-
+-    public static final String MEDIA_NAME = "ScreenShare";
+-
+-    private List<PayloadType> payloads = new ArrayList<PayloadType>();
+-
+-    private ImageDecoder decoder = null;
+-    private ImageEncoder encoder = null;
+-
+-    public ScreenShareMediaManager(JingleTransportManager transportManager) {
+-        super(transportManager);
+-        setupPayloads();
+-    }
+-
+-    /**
+-     * Setup API supported Payloads
+-     */
+-    private void setupPayloads() {
+-        payloads.add(new PayloadType.Audio(30, "sshare"));
+-    }
+-
+-    /**
+-     * Return all supported Payloads for this Manager.
+-     *
+-     * @return The Payload List
+-     */
+-    public List<PayloadType> getPayloads() {
+-        return payloads;
+-    }
+-
+-    /**
+-     * Returns a new JingleMediaSession
+-     *
+-     * @param payloadType payloadType
+-     * @param remote      remote Candidate
+-     * @param local       local Candidate
+-     * @return JingleMediaSession JingleMediaSession
+-     */
+-    public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
+-        ScreenShareSession session = null;
+-        session = new ScreenShareSession(payloadType, remote, local, "Screen", jingleSession);
+-        if (encoder != null) {
+-            session.setEncoder(encoder);
+-        }
+-        if (decoder != null) {
+-            session.setDecoder(decoder);
+-        }
+-        return session;
+-    }
+-
+-    public PayloadType getPreferredPayloadType() {
+-        return super.getPreferredPayloadType();
+-    }
+-
+-    public ImageDecoder getDecoder() {
+-        return decoder;
+-    }
+-
+-    public void setDecoder(ImageDecoder decoder) {
+-        this.decoder = decoder;
+-    }
+-
+-    public ImageEncoder getEncoder() {
+-        return encoder;
+-    }
+-
+-    public void setEncoder(ImageEncoder encoder) {
+-        this.encoder = encoder;
+-    }
+-    
+-    public  String getName() {
+-        return MEDIA_NAME;
+-    }
+-}
+Index: org/jivesoftware/smackx/jingle/mediaimpl/multi/MultiMediaManager.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/multi/MultiMediaManager.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/multi/MultiMediaManager.java	(working copy)
+@@ -1,106 +0,0 @@
+-/**
+- * $RCSfile: MultiMediaManager.java,v $
+- * $Revision: 1.3 $
+- * $Date: 25/12/2006
+- * <p/>
+- * Copyright 2003-2006 Jive Software.
+- * <p/>
+- * 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
+- * <p/>
+- * http://www.apache.org/licenses/LICENSE-2.0
+- * <p/>
+- * Unless required by applicable law or agreed to in writing, software
+- * distributed under the License is distributed on an "AS IS" BASIS,
+- * WITHOUT 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.jingle.mediaimpl.multi;
+-
+-import org.jivesoftware.smackx.jingle.JingleSession;
+-import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
+-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
+-import org.jivesoftware.smackx.jingle.media.PayloadType;
+-import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
+-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
+-
+-import java.util.ArrayList;
+-import java.util.List;
+-
+-/**
+- * Implements a MultiMediaManager using other JingleMediaManager implementations.
+- * It supports every Codecs that JingleMediaManagers added has.
+- *
+- * @author Thiago Camargo
+- */
+-
+-public class MultiMediaManager extends JingleMediaManager {
+-
+-    public static final String MEDIA_NAME = "Multi";
+-
+-    private List<JingleMediaManager> managers = new ArrayList<JingleMediaManager>();
+-
+-    private PayloadType preferredPayloadType = null;
+-
+-    public MultiMediaManager(JingleTransportManager transportManager) {
+-        super(transportManager);
+-    }
+-
+-    public void addMediaManager(JingleMediaManager manager) {
+-        managers.add(manager);
+-    }
+-
+-    public void removeMediaManager(JingleMediaManager manager) {
+-        managers.remove(manager);
+-    }
+-
+-    /**
+-     * Return all supported Payloads for this Manager.
+-     *
+-     * @return The Payload List
+-     */
+-    public List<PayloadType> getPayloads() {
+-        List<PayloadType> list = new ArrayList<PayloadType>();
+-        if (preferredPayloadType != null) list.add(preferredPayloadType);
+-        for (JingleMediaManager manager : managers) {
+-            for (PayloadType payloadType : manager.getPayloads()) {
+-                if (!list.contains(payloadType) && !payloadType.equals(preferredPayloadType))
+-                    list.add(payloadType);
+-            }
+-        }
+-        return list;
+-    }
+-
+-    /**
+-     * Returns a new JingleMediaSession
+-     *
+-     * @param payloadType payloadType
+-     * @param remote      remote Candidate
+-     * @param local       local Candidate
+-     * @return JingleMediaSession JingleMediaSession
+-     */
+-    public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
+-        for (JingleMediaManager manager : managers) {
+-            if (manager.getPayloads().contains(payloadType)) {
+-                return manager.createMediaSession(payloadType, remote, local, jingleSession);
+-            }
+-        }
+-        return null;
+-    }
+-
+-    public PayloadType getPreferredPayloadType() {
+-        if (preferredPayloadType != null) return preferredPayloadType;
+-        return super.getPreferredPayloadType();
+-    }
+-
+-    public void setPreferredPayloadType(PayloadType preferredPayloadType) {
+-        this.preferredPayloadType = preferredPayloadType;
+-    }
+-    
+-    public  String getName() {
+-        return MEDIA_NAME;
+-    }
+-}
+Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioMediaSession.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioMediaSession.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioMediaSession.java	(working copy)
+@@ -1,165 +0,0 @@
+-/**

+- * $RCSfile: AudioMediaSession.java,v $

+- * $Revision: 1.1 $

+- * $Date: 08/11/2006

+- * <p/>

+- * Copyright 2003-2006 Jive Software.

+- * <p/>

+- * 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

+- * <p/>

+- * http://www.apache.org/licenses/LICENSE-2.0

+- * <p/>

+- * Unless required by applicable law or agreed to in writing, software

+- * distributed under the License is distributed on an "AS IS" BASIS,

+- * WITHOUT 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.jingle.mediaimpl.jmf;

+-

+-import java.io.IOException;

+-import java.net.ServerSocket;

+-

+-import javax.media.MediaLocator;

+-

+-import org.jivesoftware.smackx.jingle.JingleSession;

+-import org.jivesoftware.smackx.jingle.SmackLogger;

+-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;

+-import org.jivesoftware.smackx.jingle.media.PayloadType;

+-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;

+-

+-/**

+- * This Class implements a complete JingleMediaSession.

+- * It sould be used to transmit and receive audio captured from the Mic.

+- * This Class should be automaticly controlled by JingleSession.

+- * But you could also use in any VOIP application.

+- * For better NAT Traversal support this implementation don't support only receive or only transmit.

+- * To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit()

+- *

+- * @author Thiago Camargo

+- */

+-public class AudioMediaSession extends JingleMediaSession {

+-

+-	private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioMediaSession.class);

+-

+-	private AudioChannel audioChannel;

+-

+-    /**

+-     * Creates a org.jivesoftware.jingleaudio.jmf.AudioMediaSession with defined payload type, remote and local candidates

+-     *

+-     * @param payloadType Payload of the jmf

+-     * @param remote      the remote information. The candidate that the jmf will be sent to.

+-     * @param local       the local information. The candidate that will receive the jmf

+-     * @param locator     media locator

+-     */

+-    public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote,

+-            final TransportCandidate local, String locator, JingleSession jingleSession) {

+-        super(payloadType, remote, local, locator==null?"dsound://":locator,jingleSession);

+-        initialize();

+-    }

+-

+-    /**

+-     * Initialize the Audio Channel to make it able to send and receive audio

+-     */

+-    public void initialize() {

+-

+-        String ip;

+-        String localIp;

+-        int localPort;

+-        int remotePort;

+-

+-        if (this.getLocal().getSymmetric() != null) {

+-            ip = this.getLocal().getIp();

+-            localIp = this.getLocal().getLocalIp();

+-            localPort = getFreePort();

+-            remotePort = this.getLocal().getSymmetric().getPort();

+-

+-            LOGGER.debug(this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort);

+-

+-        }

+-        else {

+-            ip = this.getRemote().getIp();

+-            localIp = this.getLocal().getLocalIp();

+-            localPort = this.getLocal().getPort();

+-            remotePort = this.getRemote().getPort();

+-        }

+-

+-        audioChannel = new AudioChannel(new MediaLocator(this.getMediaLocator()), localIp, ip, localPort, remotePort, AudioFormatUtils.getAudioFormat(this.getPayloadType()),this);

+-    }

+-

+-    /**

+-     * Starts transmission and for NAT Traversal reasons start receiving also.

+-     */

+-    public void startTrasmit() {

+-        audioChannel.start();

+-    }

+-

+-    /**

+-     * Set transmit activity. If the active is true, the instance should trasmit.

+-     * If it is set to false, the instance should pause transmit.

+-     *

+-     * @param active active state

+-     */

+-    public void setTrasmit(boolean active) {

+-        audioChannel.setTrasmit(active);

+-    }

+-

+-    /**

+-     * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf

+-     */

+-    public void startReceive() {

+-        // Do nothing

+-    }

+-

+-    /**

+-     * Stops transmission and for NAT Traversal reasons stop receiving also.

+-     */

+-    public void stopTrasmit() {

+-        if (audioChannel != null)

+-            audioChannel.stop();

+-    }

+-

+-    /**

+-     * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf

+-     */

+-    public void stopReceive() {

+-        // Do nothing

+-    }

+-

+-    /**

+-     * Obtain a free port we can use.

+-     *

+-     * @return A free port number.

+-     */

+-    protected int getFreePort() {

+-        ServerSocket ss;

+-        int freePort = 0;

+-

+-        for (int i = 0; i < 10; i++) {

+-            freePort = (int) (10000 + Math.round(Math.random() * 10000));

+-            freePort = freePort % 2 == 0 ? freePort : freePort + 1;

+-            try {

+-                ss = new ServerSocket(freePort);

+-                freePort = ss.getLocalPort();

+-                ss.close();

+-                return freePort;

+-            }

+-            catch (IOException e) {

+-                e.printStackTrace();

+-            }

+-        }

+-        try {

+-            ss = new ServerSocket(0);

+-            freePort = ss.getLocalPort();

+-            ss.close();

+-        }

+-        catch (IOException e) {

+-            e.printStackTrace();

+-        }

+-        return freePort;

+-    }

+-

+-}

+Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioReceiver.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioReceiver.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioReceiver.java	(working copy)
+@@ -1,171 +0,0 @@
+-/**

+- * $RCSfile: AudioReceiver.java,v $

+- * $Revision: 1.1 $

+- * $Date: 08/11/2006

+- * <p/>

+- * Copyright 2003-2006 Jive Software.

+- * <p/>

+- * 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

+- * <p/>

+- * http://www.apache.org/licenses/LICENSE-2.0

+- * <p/>

+- * Unless required by applicable law or agreed to in writing, software

+- * distributed under the License is distributed on an "AS IS" BASIS,

+- * WITHOUT 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.jingle.mediaimpl.jmf;

+-

+-import javax.media.ControllerErrorEvent;

+-import javax.media.ControllerEvent;

+-import javax.media.ControllerListener;

+-import javax.media.Player;

+-import javax.media.RealizeCompleteEvent;

+-import javax.media.protocol.DataSource;

+-import javax.media.rtp.Participant;

+-import javax.media.rtp.RTPControl;

+-import javax.media.rtp.ReceiveStream;

+-import javax.media.rtp.ReceiveStreamListener;

+-import javax.media.rtp.SessionListener;

+-import javax.media.rtp.event.ByeEvent;

+-import javax.media.rtp.event.NewParticipantEvent;

+-import javax.media.rtp.event.NewReceiveStreamEvent;

+-import javax.media.rtp.event.ReceiveStreamEvent;

+-import javax.media.rtp.event.RemotePayloadChangeEvent;

+-import javax.media.rtp.event.SessionEvent;

+-import javax.media.rtp.event.StreamMappedEvent;

+-

+-import org.jivesoftware.smackx.jingle.SmackLogger;

+-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;

+-

+-/**

+- * This class implements receive methods and listeners to be used in AudioChannel

+- *

+- * @author Thiago Camargo

+- */

+-public class AudioReceiver implements ReceiveStreamListener, SessionListener,

+-        ControllerListener {

+-

+-	private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioReceiver.class);

+-

+-	boolean dataReceived = false;

+-

+-    Object dataSync;

+-    JingleMediaSession jingleMediaSession;

+-

+-    public AudioReceiver(final Object dataSync, final JingleMediaSession jingleMediaSession) {

+-        this.dataSync = dataSync;

+-        this.jingleMediaSession = jingleMediaSession;

+-    }

+-

+-    /**

+-     * JingleSessionListener.

+-     */

+-    public synchronized void update(SessionEvent evt) {

+-        if (evt instanceof NewParticipantEvent) {

+-            Participant p = ((NewParticipantEvent) evt).getParticipant();

+-            LOGGER.error("  - A new participant had just joined: " + p.getCNAME());

+-        }

+-    }

+-

+-    /**

+-     * ReceiveStreamListener

+-     */

+-    public synchronized void update(ReceiveStreamEvent evt) {

+-

+-        Participant participant = evt.getParticipant();    // could be null.

+-        ReceiveStream stream = evt.getReceiveStream();  // could be null.

+-

+-        if (evt instanceof RemotePayloadChangeEvent) {

+-            LOGGER.error("  - Received an RTP PayloadChangeEvent.");

+-            LOGGER.error("Sorry, cannot handle payload change.");

+-

+-        }

+-        else if (evt instanceof NewReceiveStreamEvent) {

+-

+-            try {

+-                stream = evt.getReceiveStream();

+-                DataSource ds = stream.getDataSource();

+-

+-                // Find out the formats.

+-                RTPControl ctl = (RTPControl) ds.getControl("javax.jmf.rtp.RTPControl");

+-                if (ctl != null) {

+-                    LOGGER.error("  - Recevied new RTP stream: " + ctl.getFormat());

+-                }

+-                else

+-                    LOGGER.error("  - Recevied new RTP stream");

+-

+-                if (participant == null)

+-                    LOGGER.error("      The sender of this stream had yet to be identified.");

+-                else {

+-                    LOGGER.error("      The stream comes from: " + participant.getCNAME());

+-                }

+-

+-                // create a player by passing datasource to the Media Manager

+-                Player p = javax.media.Manager.createPlayer(ds);

+-                if (p == null)

+-                    return;

+-

+-                p.addControllerListener(this);

+-                p.realize();

+-                jingleMediaSession.mediaReceived(participant != null ? participant.getCNAME() : "");

+-

+-                // Notify intialize() that a new stream had arrived.

+-                synchronized (dataSync) {

+-                    dataReceived = true;

+-                    dataSync.notifyAll();

+-                }

+-

+-            }

+-            catch (Exception e) {

+-                LOGGER.error("NewReceiveStreamEvent exception " + e.getMessage());

+-                return;

+-            }

+-

+-        }

+-        else if (evt instanceof StreamMappedEvent) {

+-

+-            if (stream != null && stream.getDataSource() != null) {

+-                DataSource ds = stream.getDataSource();

+-                // Find out the formats.

+-                RTPControl ctl = (RTPControl) ds.getControl("javax.jmf.rtp.RTPControl");

+-                LOGGER.error("  - The previously unidentified stream ");

+-                if (ctl != null)

+-                    LOGGER.error("      " + ctl.getFormat());

+-                LOGGER.error("      had now been identified as sent by: " + participant.getCNAME());

+-            }

+-        }

+-        else if (evt instanceof ByeEvent) {

+-

+-            LOGGER.error("  - Got \"bye\" from: " + participant.getCNAME());

+-

+-        }

+-

+-    }

+-

+-    /**

+-     * ControllerListener for the Players.

+-     */

+-    public synchronized void controllerUpdate(ControllerEvent ce) {

+-

+-        Player p = (Player) ce.getSourceController();

+-

+-        if (p == null)

+-            return;

+-

+-        // Get this when the internal players are realized.

+-        if (ce instanceof RealizeCompleteEvent) {

+-            p.start();

+-        }

+-

+-        if (ce instanceof ControllerErrorEvent) {

+-            p.removeControllerListener(this);

+-            LOGGER.error("Receiver internal error: " + ce);

+-        }

+-

+-    }

+-}

+Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/JmfMediaManager.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/jmf/JmfMediaManager.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/JmfMediaManager.java	(working copy)
+@@ -1,170 +0,0 @@
+-/**

+- * $RCSfile: JmfMediaManager.java,v $

+- * $Revision: 1.3 $

+- * $Date: 08/11/2006

+- * <p/>

+- * Copyright 2003-2006 Jive Software.

+- * <p/>

+- * 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

+- * <p/>

+- * http://www.apache.org/licenses/LICENSE-2.0

+- * <p/>

+- * Unless required by applicable law or agreed to in writing, software

+- * distributed under the License is distributed on an "AS IS" BASIS,

+- * WITHOUT 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.jingle.mediaimpl.jmf;

+-

+-import java.io.File;

+-import java.io.IOException;

+-import java.util.ArrayList;

+-import java.util.List;

+-

+-import org.jivesoftware.smackx.jingle.JingleSession;

+-import org.jivesoftware.smackx.jingle.SmackLogger;

+-import org.jivesoftware.smackx.jingle.media.JingleMediaManager;

+-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;

+-import org.jivesoftware.smackx.jingle.media.PayloadType;

+-import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit;

+-import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;

+-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;

+-

+-/**

+- * Implements a jingleMediaManager using JMF based API.

+- * It supports GSM and G723 codecs.

+- * <i>This API only currently works on windows and Mac.</i>

+- *

+- * @author Thiago Camargo

+- */

+-public class JmfMediaManager extends JingleMediaManager {

+-

+-	private static final SmackLogger LOGGER = SmackLogger.getLogger(JmfMediaManager.class);

+-

+-	public static final String MEDIA_NAME = "JMF";

+-

+-    

+-    private List<PayloadType> payloads = new ArrayList<PayloadType>();

+-    private String mediaLocator = null;

+-

+-    /**

+-     * Creates a Media Manager instance

+-     */

+-    public JmfMediaManager(JingleTransportManager transportManager) {

+-        super(transportManager);

+-        setupPayloads();

+-    }

+-

+-    /**

+-     * Creates a Media Manager instance

+-     *

+-     * @param mediaLocator Media Locator

+-     */

+-    public JmfMediaManager(String mediaLocator, JingleTransportManager transportManager) {

+-        super(transportManager);

+-        this.mediaLocator = mediaLocator;

+-        setupPayloads();

+-    }

+-

+-    /**

+-     * Returns a new jingleMediaSession

+-     *

+-     * @param payloadType payloadType

+-     * @param remote      remote Candidate

+-     * @param local       local Candidate

+-     * @return JingleMediaSession

+-     */

+-    public JingleMediaSession createMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {

+-        return new AudioMediaSession(payloadType, remote, local, mediaLocator, jingleSession);

+-    }

+-

+-    /**

+-     * Setup API supported Payloads

+-     */

+-    private void setupPayloads() {

+-        payloads.add(new PayloadType.Audio(3, "gsm"));

+-        payloads.add(new PayloadType.Audio(4, "g723"));

+-        payloads.add(new PayloadType.Audio(0, "PCMU", 16000));

+-    }

+-

+-    /**

+-     * Return all supported Payloads for this Manager

+-     *

+-     * @return The Payload List

+-     */

+-    public List<PayloadType> getPayloads() {

+-        return payloads;

+-    }

+-

+-    /**

+-     * Return the media locator or null if not defined

+-     *

+-     * @return media locator

+-     */

+-    public String getMediaLocator() {

+-        return mediaLocator;

+-    }

+-

+-    /**

+-     * Set the media locator

+-     *

+-     * @param mediaLocator media locator or null to use default

+-     */

+-    public void setMediaLocator(String mediaLocator) {

+-        this.mediaLocator = mediaLocator;

+-    }

+-

+-    /**

+-     * Runs JMFInit the first time the application is started so that capture

+-     * devices are properly detected and initialized by JMF.

+-     */

+-    public static void setupJMF() {

+-        // .jmf is the place where we store the jmf.properties file used

+-        // by JMF. if the directory does not exist or it does not contain

+-        // a jmf.properties file. or if the jmf.properties file has 0 length

+-        // then this is the first time we're running and should continue to

+-        // with JMFInit

+-        String homeDir = System.getProperty("user.home");

+-        File jmfDir = new File(homeDir, ".jmf");

+-        String classpath = System.getProperty("java.class.path");

+-        classpath += System.getProperty("path.separator")

+-                + jmfDir.getAbsolutePath();

+-        System.setProperty("java.class.path", classpath);

+-

+-        if (!jmfDir.exists())

+-            jmfDir.mkdir();

+-

+-        File jmfProperties = new File(jmfDir, "jmf.properties");

+-

+-        if (!jmfProperties.exists()) {

+-            try {

+-                jmfProperties.createNewFile();

+-            }

+-            catch (IOException ex) {

+-                LOGGER.debug("Failed to create jmf.properties");

+-                ex.printStackTrace();

+-            }

+-        }

+-

+-        // if we're running on linux checkout that libjmutil.so is where it

+-        // should be and put it there.

+-        runLinuxPreInstall();

+-

+-        //if (jmfProperties.length() == 0) {

+-        new JMFInit(null, false);

+-        //}

+-

+-    }

+-

+-    private static void runLinuxPreInstall() {

+-        // @TODO Implement Linux Pre-Install

+-    }

+-    

+-    public  String getName() {

+-        return MEDIA_NAME;

+-    }

+-}

+Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioChannel.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioChannel.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioChannel.java	(working copy)
+@@ -1,553 +0,0 @@
+-/**

+- * $RCSfile: AudioChannel.java,v $

+- * $Revision: 1.1 $

+- * $Date: 08/11/2006

+- * <p/>

+- * Copyright 2003-2006 Jive Software.

+- * <p/>

+- * 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

+- * <p/>

+- * http://www.apache.org/licenses/LICENSE-2.0

+- * <p/>

+- * Unless required by applicable law or agreed to in writing, software

+- * distributed under the License is distributed on an "AS IS" BASIS,

+- * WITHOUT 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.jingle.mediaimpl.jmf;

+-

+-import java.io.IOException;

+-import java.net.InetAddress;

+-import java.net.UnknownHostException;

+-import java.util.ArrayList;

+-import java.util.List;

+-

+-import javax.media.Codec;

+-import javax.media.Controller;

+-import javax.media.ControllerClosedEvent;

+-import javax.media.ControllerEvent;

+-import javax.media.ControllerListener;

+-import javax.media.Format;

+-import javax.media.MediaLocator;

+-import javax.media.NoProcessorException;

+-import javax.media.Processor;

+-import javax.media.UnsupportedPlugInException;

+-import javax.media.control.BufferControl;

+-import javax.media.control.PacketSizeControl;

+-import javax.media.control.TrackControl;

+-import javax.media.format.AudioFormat;

+-import javax.media.protocol.ContentDescriptor;

+-import javax.media.protocol.DataSource;

+-import javax.media.protocol.PushBufferDataSource;

+-import javax.media.protocol.PushBufferStream;

+-import javax.media.rtp.InvalidSessionAddressException;

+-import javax.media.rtp.RTPManager;

+-import javax.media.rtp.SendStream;

+-import javax.media.rtp.SessionAddress;

+-

+-import org.jivesoftware.smackx.jingle.SmackLogger;

+-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;

+-

+-/**

+- * An Easy to use Audio Channel implemented using JMF.

+- * It sends and receives jmf for and from desired IPs and ports.

+- * Also has a rport Symetric behavior for better NAT Traversal.

+- * It send data from a defined port and receive data in the same port, making NAT binds easier.

+- * <p/>

+- * Send from portA to portB and receive from portB in portA.

+- * <p/>

+- * Sending

+- * portA ---> portB

+- * <p/>

+- * Receiving

+- * portB ---> portA

+- * <p/>

+- * <i>Transmit and Receive are interdependents. To receive you MUST trasmit. </i>

+- *

+- * @author Thiago Camargo

+- */

+-public class AudioChannel {

+-

+-	private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioChannel.class);

+-	

+-	private MediaLocator locator;

+-    private String localIpAddress;

+-    private String remoteIpAddress;

+-    private int localPort;

+-    private int portBase;

+-    private Format format;

+-

+-    private Processor processor = null;

+-    private RTPManager rtpMgrs[];

+-    private DataSource dataOutput = null;

+-    private AudioReceiver audioReceiver;

+-

+-    private List<SendStream> sendStreams = new ArrayList<SendStream>();

+-

+-    private JingleMediaSession jingleMediaSession;

+-

+-    private boolean started = false;

+-

+-    /**

+-     * Creates an Audio Channel for a desired jmf locator. For instance: new MediaLocator("dsound://")

+-     *

+-     * @param locator         media locator

+-     * @param localIpAddress  local IP address

+-     * @param remoteIpAddress remote IP address

+-     * @param localPort       local port number

+-     * @param remotePort      remote port number

+-     * @param format          audio format

+-     */

+-    public AudioChannel(MediaLocator locator,

+-            String localIpAddress,

+-            String remoteIpAddress,

+-            int localPort,

+-            int remotePort,

+-            Format format, JingleMediaSession jingleMediaSession) {

+-

+-        this.locator = locator;

+-        this.localIpAddress = localIpAddress;

+-        this.remoteIpAddress = remoteIpAddress;

+-        this.localPort = localPort;

+-        this.portBase = remotePort;

+-        this.format = format;

+-        this.jingleMediaSession = jingleMediaSession;

+-    }

+-

+-    /**

+-     * Starts the transmission. Returns null if transmission started ok.

+-     * Otherwise it returns a string with the reason why the setup failed.

+-     * Starts receive also.

+-     *

+-     * @return result description

+-     */

+-    public synchronized String start() {

+-        if (started) return null;

+-

+-        // Create a processor for the specified jmf locator

+-        String result = createProcessor();

+-        if (result != null) {

+-            started = false;

+-        }

+-

+-        // Create an RTP session to transmit the output of the

+-        // processor to the specified IP address and port no.

+-        result = createTransmitter();

+-        if (result != null) {

+-            processor.close();

+-            processor = null;

+-            started = false;

+-        }

+-        else {

+-            started = true;

+-        }

+-

+-        // Start the transmission

+-        processor.start();

+-

+-        return null;

+-    }

+-

+-    /**

+-     * Stops the transmission if already started.

+-     * Stops the receiver also.

+-     */

+-    public void stop() {

+-        if (!started) return;

+-        synchronized (this) {

+-            try {

+-                started = false;

+-                if (processor != null) {

+-                    processor.stop();

+-                    processor = null;

+-

+-                    for (RTPManager rtpMgr : rtpMgrs) {

+-                        rtpMgr.removeReceiveStreamListener(audioReceiver);

+-                        rtpMgr.removeSessionListener(audioReceiver);

+-                        rtpMgr.removeTargets("Session ended.");

+-                        rtpMgr.dispose();

+-                    }

+-

+-                    sendStreams.clear();

+-

+-                }

+-            }

+-            catch (Exception e) {

+-                e.printStackTrace();

+-            }

+-        }

+-    }

+-

+-    private String createProcessor() {

+-        if (locator == null)

+-            return "Locator is null";

+-

+-        DataSource ds;

+-

+-        try {

+-            ds = javax.media.Manager.createDataSource(locator);

+-        }

+-        catch (Exception e) {

+-            // Try JavaSound Locator as a last resort

+-            try {

+-                ds = javax.media.Manager.createDataSource(new MediaLocator("javasound://"));

+-            }

+-            catch (Exception ee) {

+-                return "Couldn't create DataSource";

+-            }

+-        }

+-

+-        // Try to create a processor to handle the input jmf locator

+-        try {

+-            processor = javax.media.Manager.createProcessor(ds);

+-        }

+-        catch (NoProcessorException npe) {

+-            npe.printStackTrace();

+-            return "Couldn't create processor";

+-        }

+-        catch (IOException ioe) {

+-            ioe.printStackTrace();

+-            return "IOException creating processor";

+-        }

+-

+-        // Wait for it to configure

+-        boolean result = waitForState(processor, Processor.Configured);

+-        if (!result){

+-            return "Couldn't configure processor";

+-        }

+-        

+-        // Get the tracks from the processor

+-        TrackControl[] tracks = processor.getTrackControls();

+-

+-        // Do we have atleast one track?

+-        if (tracks == null || tracks.length < 1){

+-            return "Couldn't find tracks in processor";

+-        }

+-

+-        // Set the output content descriptor to RAW_RTP

+-        // This will limit the supported formats reported from

+-        // Track.getSupportedFormats to only valid RTP formats.

+-        ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);

+-        processor.setContentDescriptor(cd);

+-

+-        Format supported[];

+-        Format chosen = null;

+-        boolean atLeastOneTrack = false;

+-

+-        // Program the tracks.

+-        for (int i = 0; i < tracks.length; i++) {

+-            if (tracks[i].isEnabled()) {

+-

+-                supported = tracks[i].getSupportedFormats();

+-

+-                if (supported.length > 0) {

+-                    for (Format format : supported) {

+-                        if (format instanceof AudioFormat) {

+-                            if (this.format.matches(format))

+-                                chosen = format;

+-                        }

+-                    }

+-                    if (chosen != null) {

+-                        tracks[i].setFormat(chosen);

+-                        LOGGER.error("Track " + i + " is set to transmit as:");

+-                        LOGGER.error("  " + chosen);

+-

+-                        if (tracks[i].getFormat() instanceof AudioFormat) {

+-                            int packetRate = 20;

+-                            PacketSizeControl pktCtrl = (PacketSizeControl) processor.getControl(PacketSizeControl.class.getName());

+-                            if (pktCtrl != null) {

+-                                try {

+-                                    pktCtrl.setPacketSize(getPacketSize(tracks[i].getFormat(), packetRate));

+-                                }

+-                                catch (IllegalArgumentException e) {

+-                                    pktCtrl.setPacketSize(80);

+-                                    // Do nothing

+-                                }

+-                            }

+-

+-                            if (tracks[i].getFormat().getEncoding().equals(AudioFormat.ULAW_RTP)) {

+-                                Codec codec[] = new Codec[3];

+-

+-                                codec[0] = new com.ibm.media.codec.audio.rc.RCModule();

+-                                codec[1] = new com.ibm.media.codec.audio.ulaw.JavaEncoder();

+-                                codec[2] = new com.sun.media.codec.audio.ulaw.Packetizer();

+-                                ((com.sun.media.codec.audio.ulaw.Packetizer) codec

+-                                        [2]).setPacketSize(160);

+-

+-                                try {

+-                                    tracks[i].setCodecChain(codec);

+-                                }

+-                                catch (UnsupportedPlugInException e) {

+-                                    e.printStackTrace();

+-                                }

+-                            }

+-

+-                        }

+-

+-                        atLeastOneTrack = true;

+-                    }

+-                    else

+-                        tracks[i].setEnabled(false);

+-                }

+-                else

+-                    tracks[i].setEnabled(false);

+-            }

+-        }

+-

+-        if (!atLeastOneTrack)

+-            return "Couldn't set any of the tracks to a valid RTP format";

+-

+-        result = waitForState(processor, Controller.Realized);

+-        if (!result)

+-            return "Couldn't realize processor";

+-

+-        // Get the output data source of the processor

+-        dataOutput = processor.getDataOutput();

+-

+-        return null;

+-    }

+-

+-    /**

+-     * Get the best packet size for a given codec and a codec rate

+-     *

+-     * @param codecFormat

+-     * @param milliseconds

+-     * @return

+-     * @throws IllegalArgumentException

+-     */

+-    private int getPacketSize(Format codecFormat, int milliseconds) throws IllegalArgumentException {

+-        String encoding = codecFormat.getEncoding();

+-        if (encoding.equalsIgnoreCase(AudioFormat.GSM) ||

+-                encoding.equalsIgnoreCase(AudioFormat.GSM_RTP)) {

+-            return milliseconds * 4; // 1 byte per millisec

+-        }

+-        else if (encoding.equalsIgnoreCase(AudioFormat.ULAW) ||

+-                encoding.equalsIgnoreCase(AudioFormat.ULAW_RTP)) {

+-            return milliseconds * 8;

+-        }

+-        else {

+-            throw new IllegalArgumentException("Unknown codec type");

+-        }

+-    }

+-

+-    /**

+-     * Use the RTPManager API to create sessions for each jmf

+-     * track of the processor.

+-     *

+-     * @return description

+-     */

+-    private String createTransmitter() {

+-

+-        // Cheated.  Should have checked the type.

+-        PushBufferDataSource pbds = (PushBufferDataSource) dataOutput;

+-        PushBufferStream pbss[] = pbds.getStreams();

+-

+-        rtpMgrs = new RTPManager[pbss.length];

+-        SessionAddress localAddr, destAddr;

+-        InetAddress ipAddr;

+-        SendStream sendStream;

+-        audioReceiver = new AudioReceiver(this, jingleMediaSession);

+-        int port;

+-

+-        for (int i = 0; i < pbss.length; i++) {

+-            try {

+-                rtpMgrs[i] = RTPManager.newInstance();

+-

+-                port = portBase + 2 * i;

+-                ipAddr = InetAddress.getByName(remoteIpAddress);

+-

+-                localAddr = new SessionAddress(InetAddress.getByName(this.localIpAddress),

+-                        localPort);

+-

+-                destAddr = new SessionAddress(ipAddr, port);

+-

+-                rtpMgrs[i].addReceiveStreamListener(audioReceiver);

+-                rtpMgrs[i].addSessionListener(audioReceiver);

+-

+-                BufferControl bc = (BufferControl) rtpMgrs[i].getControl("javax.media.control.BufferControl");

+-                if (bc != null) {

+-                    int bl = 160;

+-                    bc.setBufferLength(bl);

+-                }

+-

+-                try {

+-

+-                    rtpMgrs[i].initialize(localAddr);

+-

+-                }

+-                catch (InvalidSessionAddressException e) {

+-                    // In case the local address is not allowed to read, we user another local address

+-                    SessionAddress sessAddr = new SessionAddress();

+-                    localAddr = new SessionAddress(sessAddr.getDataAddress(),

+-                            localPort);

+-                    rtpMgrs[i].initialize(localAddr);

+-                }

+-

+-                rtpMgrs[i].addTarget(destAddr);

+-

+-                LOGGER.error("Created RTP session at " + localPort + " to: " + remoteIpAddress + " " + port);

+-

+-                sendStream = rtpMgrs[i].createSendStream(dataOutput, i);

+-

+-                sendStreams.add(sendStream);

+-

+-                sendStream.start();

+-

+-            }

+-            catch (Exception e) {

+-                e.printStackTrace();

+-                return e.getMessage();

+-            }

+-        }

+-

+-        return null;

+-    }

+-

+-    /**

+-     * Set transmit activity. If the active is true, the instance should trasmit.

+-     * If it is set to false, the instance should pause transmit.

+-     *

+-     * @param active active state

+-     */

+-    public void setTrasmit(boolean active) {

+-        for (SendStream sendStream : sendStreams) {

+-            try {

+-                if (active) {

+-                    sendStream.start();

+-                    LOGGER.debug("START");

+-                }

+-                else {

+-                    sendStream.stop();

+-                    LOGGER.debug("STOP");

+-                }

+-            }

+-            catch (IOException e) {

+-                e.printStackTrace();

+-            }

+-

+-        }

+-    }

+-

+-    /**

+-     * *************************************************************

+-     * Convenience methods to handle processor's state changes.

+-     * **************************************************************

+-     */

+-

+-    private Integer stateLock = 0;

+-    private boolean failed = false;

+-

+-    Integer getStateLock() {

+-        return stateLock;

+-    }

+-

+-    void setFailed() {

+-        failed = true;

+-    }

+-

+-    private synchronized boolean waitForState(Processor p, int state) {

+-        p.addControllerListener(new StateListener());

+-        failed = false;

+-

+-        // Call the required method on the processor

+-        if (state == Processor.Configured) {

+-            p.configure();

+-        }

+-        else if (state == Processor.Realized) {

+-            p.realize();

+-        }

+-

+-        // Wait until we get an event that confirms the

+-        // success of the method, or a failure event.

+-        // See StateListener inner class

+-        while (p.getState() < state && !failed) {

+-            synchronized (getStateLock()) {

+-                try {

+-                    getStateLock().wait();

+-                }

+-                catch (InterruptedException ie) {

+-                    return false;

+-                }

+-            }

+-        }

+-

+-        return !failed;

+-    }

+-

+-    /**

+-     * *************************************************************

+-     * Inner Classes

+-     * **************************************************************

+-     */

+-

+-    class StateListener implements ControllerListener {

+-

+-        public void controllerUpdate(ControllerEvent ce) {

+-

+-            // If there was an error during configure or

+-            // realize, the processor will be closed

+-            if (ce instanceof ControllerClosedEvent)

+-                setFailed();

+-

+-            // All controller events, send a notification

+-            // to the waiting thread in waitForState method.

+-            if (ce != null) {

+-                synchronized (getStateLock()) {

+-                    getStateLock().notifyAll();

+-                }

+-            }

+-        }

+-    }

+-

+-    public static void main(String args[]) {

+-

+-        InetAddress localhost;

+-        try {

+-            localhost = InetAddress.getLocalHost();

+-

+-            AudioChannel audioChannel0 = new AudioChannel(new MediaLocator("javasound://8000"), localhost.getHostAddress(), localhost.getHostAddress(), 7002, 7020, new AudioFormat(AudioFormat.GSM_RTP), null);

+-            AudioChannel audioChannel1 = new AudioChannel(new MediaLocator("javasound://8000"), localhost.getHostAddress(), localhost.getHostAddress(), 7020, 7002, new AudioFormat(AudioFormat.GSM_RTP), null);

+-

+-            audioChannel0.start();

+-            audioChannel1.start();

+-

+-            try {

+-                Thread.sleep(5000);

+-            }

+-            catch (InterruptedException e) {

+-                e.printStackTrace();

+-            }

+-

+-            audioChannel0.setTrasmit(false);

+-            audioChannel1.setTrasmit(false);

+-

+-            try {

+-                Thread.sleep(5000);

+-            }

+-            catch (InterruptedException e) {

+-                e.printStackTrace();

+-            }

+-

+-            audioChannel0.setTrasmit(true);

+-            audioChannel1.setTrasmit(true);

+-

+-            try {

+-                Thread.sleep(5000);

+-            }

+-            catch (InterruptedException e) {

+-                e.printStackTrace();

+-            }

+-

+-            audioChannel0.stop();

+-            audioChannel1.stop();

+-

+-        }

+-        catch (UnknownHostException e) {

+-            e.printStackTrace();

+-        }

+-

+-    }

+-}
+\ No newline at end of file
+Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioFormatUtils.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioFormatUtils.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioFormatUtils.java	(working copy)
+@@ -1,55 +0,0 @@
+-/**

+- * $RCSfile: AudioFormatUtils.java,v $

+- * $Revision: 1.1 $

+- * $Date: 08/11/2006

+- * <p/>

+- * Copyright 2003-2006 Jive Software.

+- * <p/>

+- * 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

+- * <p/>

+- * http://www.apache.org/licenses/LICENSE-2.0

+- * <p/>

+- * Unless required by applicable law or agreed to in writing, software

+- * distributed under the License is distributed on an "AS IS" BASIS,

+- * WITHOUT 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.jingle.mediaimpl.jmf;

+-

+-import org.jivesoftware.smackx.jingle.media.PayloadType;

+-

+-import javax.media.format.AudioFormat;

+-

+-/**

+- * Audio Format Utils.

+- *

+- * @author Thiago Camargo

+- */

+-public class AudioFormatUtils {

+-

+-    /**

+-     * Return a JMF AudioFormat for a given Jingle Payload type.

+-     * Return null if the payload is not supported by this jmf API.

+-     *

+-     * @param payloadtype payloadtype

+-     * @return correspondent audioType

+-     */

+-    public static AudioFormat getAudioFormat(PayloadType payloadtype) {

+-

+-        switch (payloadtype.getId()) {

+-            case 0:

+-                return new AudioFormat(AudioFormat.ULAW_RTP);

+-            case 3:

+-                return new AudioFormat(AudioFormat.GSM_RTP);

+-            case 4:

+-                return new AudioFormat(AudioFormat.G723_RTP);

+-            default:

+-                return null;

+-        }

+-

+-    }

+-

+-}

+Index: org/jivesoftware/smackx/jingle/mediaimpl/jspeex/SpeexMediaManager.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/jspeex/SpeexMediaManager.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/jspeex/SpeexMediaManager.java	(working copy)
+@@ -1,134 +0,0 @@
+-/**

+- * $RCSfile: SpeexMediaManager.java,v $

+- * $Revision: 1.3 $

+- * $Date: 25/12/2006

+- * <p/>

+- * Copyright 2003-2006 Jive Software.

+- * <p/>

+- * 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

+- * <p/>

+- * http://www.apache.org/licenses/LICENSE-2.0

+- * <p/>

+- * Unless required by applicable law or agreed to in writing, software

+- * distributed under the License is distributed on an "AS IS" BASIS,

+- * WITHOUT 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.jingle.mediaimpl.jspeex;

+-

+-import java.io.File;

+-import java.io.IOException;

+-import java.util.ArrayList;

+-import java.util.List;

+-

+-import org.jivesoftware.smackx.jingle.JingleSession;

+-import org.jivesoftware.smackx.jingle.SmackLogger;

+-import org.jivesoftware.smackx.jingle.media.JingleMediaManager;

+-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;

+-import org.jivesoftware.smackx.jingle.media.PayloadType;

+-import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit;

+-import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;

+-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;

+-

+-/**

+- * Implements a jingleMediaManager using JMF based API and JSpeex.

+- * It supports Speex codec.

+- * <i>This API only currently works on windows.</i>

+- *

+- * @author Thiago Camargo

+- */

+-public class SpeexMediaManager extends JingleMediaManager {

+-

+-	private static final SmackLogger LOGGER = SmackLogger.getLogger(SpeexMediaManager.class);

+-

+-	public static final String MEDIA_NAME = "Speex";

+-

+-    private List<PayloadType> payloads = new ArrayList<PayloadType>();

+-

+-    public SpeexMediaManager(JingleTransportManager transportManager) {

+-        super(transportManager);

+-        setupPayloads();

+-        setupJMF();

+-    }

+-

+-    /**

+-     * Returns a new jingleMediaSession

+-     *

+-     * @param payloadType payloadType

+-     * @param remote      remote Candidate

+-     * @param local       local Candidate

+-     * @return JingleMediaSession

+-     */

+-    public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {

+-        return new AudioMediaSession(payloadType, remote, local, null,null);

+-    }

+-

+-    /**

+-     * Setup API supported Payloads

+-     */

+-    private void setupPayloads() {

+-        payloads.add(new PayloadType.Audio(15, "speex"));

+-    }

+-

+-    /**

+-     * Return all supported Payloads for this Manager

+-     *

+-     * @return The Payload List

+-     */

+-    public List<PayloadType> getPayloads() {

+-        return payloads;

+-    }

+-

+-    /**

+-     * Runs JMFInit the first time the application is started so that capture

+-     * devices are properly detected and initialized by JMF.

+-     */

+-    public static void setupJMF() {

+-        // .jmf is the place where we store the jmf.properties file used

+-        // by JMF. if the directory does not exist or it does not contain

+-        // a jmf.properties file. or if the jmf.properties file has 0 length

+-        // then this is the first time we're running and should continue to

+-        // with JMFInit

+-        String homeDir = System.getProperty("user.home");

+-        File jmfDir = new File(homeDir, ".jmf");

+-        String classpath = System.getProperty("java.class.path");

+-        classpath += System.getProperty("path.separator")

+-                + jmfDir.getAbsolutePath();

+-        System.setProperty("java.class.path", classpath);

+-

+-        if (!jmfDir.exists())

+-            jmfDir.mkdir();

+-

+-        File jmfProperties = new File(jmfDir, "jmf.properties");

+-

+-        if (!jmfProperties.exists()) {

+-            try {

+-                jmfProperties.createNewFile();

+-            }

+-            catch (IOException ex) {

+-                LOGGER.debug("Failed to create jmf.properties");

+-                ex.printStackTrace();

+-            }

+-        }

+-

+-        // if we're running on linux checkout that libjmutil.so is where it

+-        // should be and put it there.

+-        runLinuxPreInstall();

+-

+-        if (jmfProperties.length() == 0) {

+-            new JMFInit(null, false);

+-        }

+-

+-    }

+-

+-    private static void runLinuxPreInstall() {

+-        // @TODO Implement Linux Pre-Install

+-    }

+-    

+-    public String getName() {

+-        return MEDIA_NAME;

+-    }

+-}

+Index: org/jivesoftware/smackx/jingle/mediaimpl/jspeex/AudioMediaSession.java
+===================================================================
+--- org/jivesoftware/smackx/jingle/mediaimpl/jspeex/AudioMediaSession.java	(revision 11644)
++++ org/jivesoftware/smackx/jingle/mediaimpl/jspeex/AudioMediaSession.java	(working copy)
+@@ -1,245 +0,0 @@
+-/**

+- * $RCSfile: AudioMediaSession.java,v $

+- * $Revision: 1.1 $

+- * $Date: 25/12/2006

+- * <p/>

+- * Copyright 2003-2006 Jive Software.

+- * <p/>

+- * 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

+- * <p/>

+- * http://www.apache.org/licenses/LICENSE-2.0

+- * <p/>

+- * Unless required by applicable law or agreed to in writing, software

+- * distributed under the License is distributed on an "AS IS" BASIS,

+- * WITHOUT 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.jingle.mediaimpl.jspeex;

+-

+-import java.io.IOException;

+-import java.net.DatagramSocket;

+-import java.net.InetAddress;

+-import java.net.ServerSocket;

+-import java.security.GeneralSecurityException;

+-

+-import javax.media.NoProcessorException;

+-import javax.media.format.UnsupportedFormatException;

+-import javax.media.rtp.rtcp.SenderReport;

+-import javax.media.rtp.rtcp.SourceDescription;

+-

+-import mil.jfcom.cie.media.session.MediaSession;

+-import mil.jfcom.cie.media.session.MediaSessionListener;

+-import mil.jfcom.cie.media.session.StreamPlayer;

+-import mil.jfcom.cie.media.srtp.packetizer.SpeexFormat;

+-

+-import org.jivesoftware.smackx.jingle.JingleSession;

+-import org.jivesoftware.smackx.jingle.SmackLogger;

+-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;

+-import org.jivesoftware.smackx.jingle.media.PayloadType;

+-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;

+-

+-/**

+- * This Class implements a complete JingleMediaSession.

+- * It sould be used to transmit and receive audio captured from the Mic.

+- * This Class should be automaticly controlled by JingleSession.

+- * But you could also use in any VOIP application.

+- * For better NAT Traversal support this implementation don't support only receive or only transmit.

+- * To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit()

+- *

+- * @author Thiago Camargo

+- */

+-

+-public class AudioMediaSession extends JingleMediaSession implements MediaSessionListener {

+-

+-	private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioMediaSession.class);

+-

+-	private MediaSession mediaSession;

+-

+-    /**

+-     * Create a Session using Speex Codec

+-     *

+-     * @param localhost    localHost

+-     * @param localPort    localPort

+-     * @param remoteHost   remoteHost

+-     * @param remotePort   remotePort

+-     * @param eventHandler eventHandler

+-     * @param quality      quality

+-     * @param secure       secure

+-     * @param micOn        micOn

+-     * @return MediaSession

+-     * @throws NoProcessorException

+-     * @throws UnsupportedFormatException

+-     * @throws IOException

+-     * @throws GeneralSecurityException

+-     */

+-    public static MediaSession createSession(String localhost, int localPort, String remoteHost, int remotePort, MediaSessionListener eventHandler, int quality, boolean secure, boolean micOn) throws NoProcessorException, UnsupportedFormatException, IOException, GeneralSecurityException {

+-

+-        SpeexFormat.setFramesPerPacket(1);

+-        /**

+-         * The master key. Hardcoded for now.

+-         */

+-        byte[] masterKey = new byte[]{(byte) 0xE1, (byte) 0xF9, 0x7A, 0x0D, 0x3E, 0x01, (byte) 0x8B, (byte) 0xE0, (byte) 0xD6, 0x4F, (byte) 0xA3, 0x2C, 0x06, (byte) 0xDE, 0x41, 0x39};

+-

+-        /**

+-         * The master salt. Hardcoded for now.

+-         */

+-        byte[] masterSalt = new byte[]{0x0E, (byte) 0xC6, 0x75, (byte) 0xAD, 0x49, (byte) 0x8A, (byte) 0xFE, (byte) 0xEB, (byte) 0xB6, (byte) 0x96, 0x0B, 0x3A, (byte) 0xAB, (byte) 0xE6};

+-

+-        DatagramSocket[] localPorts = MediaSession.getLocalPorts(InetAddress.getByName(localhost), localPort);

+-        MediaSession session = MediaSession.createInstance(remoteHost, remotePort, localPorts, quality, secure, masterKey, masterSalt);

+-        session.setListener(eventHandler);

+-

+-        session.setSourceDescription(new SourceDescription[]{new SourceDescription(SourceDescription.SOURCE_DESC_NAME, "Superman", 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_EMAIL, "cdcie.tester@je.jfcom.mil", 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_LOC, InetAddress.getByName(localhost) + " Port " + session.getLocalDataPort(), 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_TOOL, "JFCOM CDCIE Audio Chat", 1, false)});

+-        return session;

+-    }

+-

+-

+-    /**

+-     * Creates a org.jivesoftware.jingleaudio.jspeex.AudioMediaSession with defined payload type, remote and local candidates

+-     *

+-     * @param payloadType Payload of the jmf

+-     * @param remote      the remote information. The candidate that the jmf will be sent to.

+-     * @param local       the local information. The candidate that will receive the jmf

+-     * @param locator     media locator

+-     */

+-    public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote,

+-            final TransportCandidate local, String locator, JingleSession jingleSession) {

+-        super(payloadType, remote, local, locator == null ? "dsound://" : locator, jingleSession);

+-        initialize();

+-    }

+-

+-    /**

+-     * Initialize the Audio Channel to make it able to send and receive audio

+-     */

+-    public void initialize() {

+-

+-        String ip;

+-        String localIp;

+-        int localPort;

+-        int remotePort;

+-

+-        if (this.getLocal().getSymmetric() != null) {

+-            ip = this.getLocal().getIp();

+-            localIp = this.getLocal().getLocalIp();

+-            localPort = getFreePort();

+-            remotePort = this.getLocal().getSymmetric().getPort();

+-

+-            LOGGER.debug(this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort);

+-

+-        }

+-        else {

+-            ip = this.getRemote().getIp();

+-            localIp = this.getLocal().getLocalIp();

+-            localPort = this.getLocal().getPort();

+-            remotePort = this.getRemote().getPort();

+-        }

+-

+-        try {

+-            mediaSession = createSession(localIp, localPort, ip, remotePort, this, 2, false, true);

+-        }

+-        catch (NoProcessorException e) {

+-            e.printStackTrace();

+-        }

+-        catch (UnsupportedFormatException e) {

+-            e.printStackTrace();

+-        }

+-        catch (IOException e) {

+-            e.printStackTrace();

+-        }

+-        catch (GeneralSecurityException e) {

+-            e.printStackTrace();

+-        }

+-    }

+-

+-    /**

+-     * Starts transmission and for NAT Traversal reasons start receiving also.

+-     */

+-    public void startTrasmit() {

+-        try {

+-            LOGGER.debug("start");

+-            mediaSession.start(true);

+-            this.mediaReceived("");

+-        }

+-        catch (IOException e) {

+-            e.printStackTrace();

+-        }

+-    }

+-

+-    /**

+-     * Set transmit activity. If the active is true, the instance should trasmit.

+-     * If it is set to false, the instance should pause transmit.

+-     *

+-     * @param active active state

+-     */

+-    public void setTrasmit(boolean active) {

+-        // Do nothing

+-    }

+-

+-    /**

+-     * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf

+-     */

+-    public void startReceive() {

+-        // Do nothing

+-    }

+-

+-    /**

+-     * Stops transmission and for NAT Traversal reasons stop receiving also.

+-     */

+-    public void stopTrasmit() {

+-        if (mediaSession != null)

+-            mediaSession.close();

+-    }

+-

+-    /**

+-     * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf

+-     */

+-    public void stopReceive() {

+-        // Do nothing

+-    }

+-

+-    public void newStreamIdentified(StreamPlayer streamPlayer) {

+-    }

+-

+-    public void senderReportReceived(SenderReport report) {

+-    }

+-

+-    public void streamClosed(StreamPlayer stream, boolean timeout) {

+-    }

+-

+-    /**

+-     * Obtain a free port we can use.

+-     *

+-     * @return A free port number.

+-     */

+-    protected int getFreePort() {

+-        ServerSocket ss;

+-        int freePort = 0;

+-

+-        for (int i = 0; i < 10; i++) {

+-            freePort = (int) (10000 + Math.round(Math.random() * 10000));

+-            freePort = freePort % 2 == 0 ? freePort : freePort + 1;

+-            try {

+-                ss = new ServerSocket(freePort);

+-                freePort = ss.getLocalPort();

+-                ss.close();

+-                return freePort;

+-            }

+-            catch (IOException e) {

+-                e.printStackTrace();

+-            }

+-        }

+-        try {

+-            ss = new ServerSocket(0);

+-            freePort = ss.getLocalPort();

+-            ss.close();

+-        }

+-        catch (IOException e) {

+-            e.printStackTrace();

+-        }

+-        return freePort;

+-    }

+-}

diff --git a/asmack-master/lib/.gitignore b/asmack-master/lib/.gitignore
new file mode 100644
index 0000000..905be00
--- /dev/null
+++ b/asmack-master/lib/.gitignore
@@ -0,0 +1 @@
+android-*.jar
diff --git a/asmack-master/lib/httpclient-4.1.3.jar b/asmack-master/lib/httpclient-4.1.3.jar
new file mode 100644
index 0000000..dfa8793
--- /dev/null
+++ b/asmack-master/lib/httpclient-4.1.3.jar
Binary files differ
diff --git a/asmack-master/lib/httpcore-4.1.4.jar b/asmack-master/lib/httpcore-4.1.4.jar
new file mode 100644
index 0000000..1606a2e
--- /dev/null
+++ b/asmack-master/lib/httpcore-4.1.4.jar
Binary files differ
diff --git a/asmack-master/lib/jstun.jar b/asmack-master/lib/jstun.jar
new file mode 100644
index 0000000..8ef0b92
--- /dev/null
+++ b/asmack-master/lib/jstun.jar
Binary files differ
diff --git a/asmack-master/lib/xpp3-1.1.4c.jar b/asmack-master/lib/xpp3-1.1.4c.jar
new file mode 100644
index 0000000..451ac82
--- /dev/null
+++ b/asmack-master/lib/xpp3-1.1.4c.jar
Binary files differ
diff --git a/asmack-master/local.properties.example b/asmack-master/local.properties.example
new file mode 100644
index 0000000..abdf234
--- /dev/null
+++ b/asmack-master/local.properties.example
@@ -0,0 +1 @@
+sdk-location=${user.home}/android/
diff --git a/asmack-master/patch/00-relocate-javax.security.sh b/asmack-master/patch/00-relocate-javax.security.sh
new file mode 100755
index 0000000..0924208
--- /dev/null
+++ b/asmack-master/patch/00-relocate-javax.security.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+mkdir -p org/apache/harmony/
+mv javax org/apache/harmony/
+find org/apache/harmony/ -name '*.java' -exec sed -i 's:package javax:package org.apache.harmony.javax:g' '{}' ';'
+find -name '*.java' -exec sed -i 's:import javax.security.sasl:import org.apache.harmony.javax.security.sasl:g' '{}' ';'
+find -name '*.java' -exec sed -i 's:import javax.security.auth:import org.apache.harmony.javax.security.auth:g' '{}' ';'
+
diff --git a/asmack-master/patch/00-remove-javax-dns.sh b/asmack-master/patch/00-remove-javax-dns.sh
new file mode 100755
index 0000000..a4f8f23
--- /dev/null
+++ b/asmack-master/patch/00-remove-javax-dns.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+rm org/jivesoftware/smack/util/dns/JavaxResolver.java
diff --git a/asmack-master/patch/10-remove-unused-harmony.sh b/asmack-master/patch/10-remove-unused-harmony.sh
new file mode 100755
index 0000000..ae0b4e3
--- /dev/null
+++ b/asmack-master/patch/10-remove-unused-harmony.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+rm -rf org/ietf/
+
+rm -rf org/apache/harmony/auth
+rm -rf org/apache/harmony/javax/security/auth/kerberos/
+rm -rf org/apache/harmony/javax/security/auth/x500/
+
+rm org/apache/harmony/javax/security/auth/Policy.java
+
diff --git a/asmack-master/patch/11-remove-nls-harmony.sh b/asmack-master/patch/11-remove-nls-harmony.sh
new file mode 100755
index 0000000..f1281f5
--- /dev/null
+++ b/asmack-master/patch/11-remove-nls-harmony.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+find org/apache/harmony -name '*.java' -exec sed -i 's:import org.apache.harmony.auth.internal.nls.Messages;::' '{}' ';'
+find org/apache/harmony -name '*.java' -exec sed -i 's:Messages.getString(\("[^"]*"\)):\1:g' '{}' ';'
+
diff --git a/asmack-master/patch/12-harmony-nls-msg.patch b/asmack-master/patch/12-harmony-nls-msg.patch
new file mode 100644
index 0000000..b201f60
--- /dev/null
+++ b/asmack-master/patch/12-harmony-nls-msg.patch
@@ -0,0 +1,59 @@
+diff -ur ../../src-unpatched/trunk/org/apache/harmony/javax/security/auth/login/LoginContext.java ./org/apache/harmony/javax/security/auth/login/LoginContext.java
+--- ../../src-unpatched/trunk/org/apache/harmony/javax/security/auth/login/LoginContext.java	2009-12-06 15:31:24.000000000 +0100
++++ ./org/apache/harmony/javax/security/auth/login/LoginContext.java	2009-12-06 15:36:20.000000000 +0100
+@@ -161,7 +161,7 @@
+             }
+             entries = config.getAppConfigurationEntry("other"); //$NON-NLS-1$
+             if (entries == null) {
+-                throw new LoginException(Messages.getString("auth.35", name)); //$NON-NLS-1$
++                throw new LoginException("auth.35 " + name); //$NON-NLS-1$
+             }
+         }
+ 
+@@ -524,8 +524,8 @@
+                 try {
+                     klass = Class.forName(klassName, false, contextClassLoader);
+                 } catch (ClassNotFoundException ex) {
+-                    throw (LoginException) new LoginException(Messages.getString(
+-                            "auth.39", klassName)).initCause(ex); //$NON-NLS-1$
++                    throw (LoginException) new LoginException(
++                            "auth.39 " + klassName).initCause(ex); //$NON-NLS-1$
+                 }
+             }
+ 
+@@ -533,12 +533,12 @@
+                 try {
+                     module = (LoginModule) klass.newInstance();
+                 } catch (IllegalAccessException ex) {
+-                    throw (LoginException) new LoginException(Messages.getString(
+-                            "auth.3A", klassName)) //$NON-NLS-1$
++                    throw (LoginException) new LoginException(
++                            "auth.3A " + klassName) //$NON-NLS-1$
+                             .initCause(ex);
+                 } catch (InstantiationException ex) {
+-                    throw (LoginException) new LoginException(Messages.getString(
+-                            "auth.3A", klassName)) //$NON-NLS-1$
++                    throw (LoginException) new LoginException(
++                            "auth.3A" + klassName) //$NON-NLS-1$
+                             .initCause(ex);
+                 }
+                 module.initialize(subject, callbackHandler, sharedState, entry.getOptions());
+diff -ur ../../src-unpatched/trunk/org/apache/harmony/javax/security/auth/Subject.java ./org/apache/harmony/javax/security/auth/Subject.java
+--- ../../src-unpatched/trunk/org/apache/harmony/javax/security/auth/Subject.java	2009-12-06 15:31:24.000000000 +0100
++++ ./org/apache/harmony/javax/security/auth/Subject.java	2009-12-06 15:32:10.000000000 +0100
+@@ -669,7 +669,7 @@
+ 
+                     if (!c.isAssignableFrom(o.getClass())) {
+                         throw new IllegalArgumentException(
+-                                Messages.getString("auth.0C", c.getName())); //$NON-NLS-1$
++                                "auth.0C " + c.getName()); //$NON-NLS-1$
+                     }
+ 
+                     if (elements.contains(o)) {
+@@ -779,4 +779,4 @@
+             }
+         }
+     }
+-}
+\ No newline at end of file
++}
diff --git a/asmack-master/patch/13-mock-configuration.patch b/asmack-master/patch/13-mock-configuration.patch
new file mode 100644
index 0000000..ce93b26
--- /dev/null
+++ b/asmack-master/patch/13-mock-configuration.patch
@@ -0,0 +1,33 @@
+diff -ur ../../src-unpatched/trunk/org/apache/harmony/javax/security/auth/login/Configuration.java ./org/apache/harmony/javax/security/auth/login/Configuration.java
+--- ../../src-unpatched/trunk/org/apache/harmony/javax/security/auth/login/Configuration.java	2009-12-06 18:40:25.000000000 +0100
++++ ./org/apache/harmony/javax/security/auth/login/Configuration.java	2009-12-06 18:44:23.000000000 +0100
+@@ -20,8 +20,6 @@
+ import java.security.AccessController;
+ import org.apache.harmony.javax.security.auth.AuthPermission;
+ 
+-import org.apache.harmony.security.fortress.PolicyUtils;
+-
+ public abstract class Configuration {
+ 
+     // the current configuration 
+@@ -56,8 +54,18 @@
+      * exception, wraps it with SecurityException and throws further.
+      */
+     private static final Configuration getDefaultProvider() {
+-        return AccessController.doPrivileged(new PolicyUtils.ProviderLoader<Configuration>(
+-                LOGIN_CONFIGURATION_PROVIDER, Configuration.class));
++        return new Configuration() {
++			
++			@Override
++			public void refresh() {
++			}
++			
++			@Override
++			public AppConfigurationEntry[] getAppConfigurationEntry(
++					String applicationName) {
++				return new AppConfigurationEntry[0];
++			}
++		};
+     }
+ 
+     /**
diff --git a/asmack-master/patch/20-remove-mxparser.sh b/asmack-master/patch/20-remove-mxparser.sh
new file mode 100755
index 0000000..c1d6318
--- /dev/null
+++ b/asmack-master/patch/20-remove-mxparser.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+find org/jivesoftware -name '*.java' -exec sed -i 's:import org.xmlpull.mxp1.MXParser:import org.xmlpull.v1.XmlPullParserFactory:' '{}' ';'
+find org/jivesoftware -name '*.java' -exec sed -i 's:new MXParser():XmlPullParserFactory.newInstance().newPullParser():g' '{}' ';'
+
diff --git a/asmack-master/patch/21-remove-unused-smack.sh b/asmack-master/patch/21-remove-unused-smack.sh
new file mode 100755
index 0000000..078ff04
--- /dev/null
+++ b/asmack-master/patch/21-remove-unused-smack.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+rm org/jivesoftware/smack/debugger/LiteDebugger.java
+rm org/jivesoftware/smackx/debugger/EnhancedDebugger.java
+rm org/jivesoftware/smackx/debugger/EnhancedDebuggerWindow.java
+
diff --git a/asmack-master/patch/22-remove-beans.Property-deps.patch b/asmack-master/patch/22-remove-beans.Property-deps.patch
new file mode 100644
index 0000000..8653716
--- /dev/null
+++ b/asmack-master/patch/22-remove-beans.Property-deps.patch
@@ -0,0 +1,30 @@
+--- ../../src-unpatched/trunk/org/jivesoftware/smack/util/PacketParserUtils.java	2009-12-06 19:45:45.000000000 +0100
++++ org/jivesoftware/smack/util/PacketParserUtils.java	2009-12-06 19:48:13.000000000 +0100
+@@ -25,7 +25,6 @@
+ import org.jivesoftware.smack.provider.ProviderManager;
+ import org.xmlpull.v1.XmlPullParser;
+ 
+-import java.beans.PropertyDescriptor;
+ import java.io.ByteArrayInputStream;
+ import java.io.ObjectInputStream;
+ import java.util.ArrayList;
+@@ -828,14 +827,14 @@
+             if (eventType == XmlPullParser.START_TAG) {
+                 String name = parser.getName();
+                 String stringValue = parser.nextText();
+-                PropertyDescriptor descriptor = new PropertyDescriptor(name, objectClass);
+-                // Load the class type of the property.
+-                Class<?> propertyType = descriptor.getPropertyType();
++                Class propertyType = object.getClass().getMethod(
++                    "get" + Character.toUpperCase(name.charAt(0)) + name.substring(1)).getReturnType();
+                 // Get the value of the property by converting it from a
+                 // String to the correct object type.
+                 Object value = decode(propertyType, stringValue);
+                 // Set the value of the bean.
+-                descriptor.getWriteMethod().invoke(object, value);
++                object.getClass().getMethod("set" + Character.toUpperCase(name.charAt(0)) + name.substring(1), propertyType)
++                .invoke(object, value);
+             }
+             else if (eventType == XmlPullParser.END_TAG) {
+                 if (parser.getName().equals(elementName)) {
+
diff --git a/asmack-master/patch/23-strip-unused-xml-transform.patch b/asmack-master/patch/23-strip-unused-xml-transform.patch
new file mode 100644
index 0000000..24debbd
--- /dev/null
+++ b/asmack-master/patch/23-strip-unused-xml-transform.patch
@@ -0,0 +1,50 @@
+--- org/jivesoftware/smackx/pubsub/util/XmlUtils.java	2012-06-05 14:35:54.518687907 +0200
++++ org/jivesoftware/smackx/pubsub/util/XmlUtils.java	2012-06-05 21:07:13.038946699 +0200
+@@ -14,47 +14,15 @@
+ package org.jivesoftware.smackx.pubsub.util;

+ 

+ import java.io.StringReader;

+ 

+-import javax.xml.transform.OutputKeys;

+-import javax.xml.transform.Transformer;

+-import javax.xml.transform.TransformerFactory;

+-import javax.xml.transform.stream.StreamResult;

+-import javax.xml.transform.stream.StreamSource;

+-

+ /**

+  * Simple utility for pretty printing xml.

+  * 

+  * @author Robin Collier

+  */

+ public class XmlUtils

+ {

+-	/**

+-	 * 

+-	 * @param header Just a title for the stanza for readability.  Single word no spaces since

+-	 * it is inserted as the root element in the output.

+-	 * @param xml The string to pretty print

+-	 */

+-	static public void prettyPrint(String header, String xml)

+-	{

+-		try

+-		{

+-			Transformer transformer = TransformerFactory.newInstance().newTransformer();

+-			transformer.setOutputProperty(OutputKeys.INDENT, "yes");

+-			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");

+-

+-			if (header != null)

+-			{

+-				xml = "\n<" + header + ">" + xml + "</" + header + '>';

+-			}

+-			transformer.transform(new StreamSource(new StringReader(xml)), new StreamResult(System.out));

+-		}

+-		catch (Exception e)

+-		{

+-			System.out.println("Something wrong with xml in \n---------------\n" + xml + "\n---------------");

+-			e.printStackTrace();

+-		}

+-	}

+ 

+ 	static public void appendAttribute(StringBuilder builder, String att, String value)

+ 	{

+ 		builder.append(" ");

diff --git a/asmack-master/patch/24-disable-sasl-methods.patch b/asmack-master/patch/24-disable-sasl-methods.patch
new file mode 100644
index 0000000..eda5eb0
--- /dev/null
+++ b/asmack-master/patch/24-disable-sasl-methods.patch
@@ -0,0 +1,20 @@
+--- ../../src-unpatched/trunk/org/jivesoftware/smack/SASLAuthentication.java	2009-12-07 00:03:46.000000000 +0100
++++ org/jivesoftware/smack/SASLAuthentication.java	2009-12-07 00:05:46.000000000 +0100
+@@ -91,11 +91,11 @@
+         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);

++//        supportSASLMechanism("GSSAPI",0);

++        supportSASLMechanism("DIGEST-MD5",0);

++//        supportSASLMechanism("CRAM-MD5",2);

++        supportSASLMechanism("PLAIN",1);

++        supportSASLMechanism("ANONYMOUS",2);

+ 

+     }

+ 

+
diff --git a/asmack-master/patch/30-switch-debugging-implementations.patch b/asmack-master/patch/30-switch-debugging-implementations.patch
new file mode 100644
index 0000000..93be2a0
--- /dev/null
+++ b/asmack-master/patch/30-switch-debugging-implementations.patch
@@ -0,0 +1,17 @@
+--- ../../../src/smack/org/jivesoftware/smack/Connection.java	2010-02-03 23:29:21.000000000 +0100
++++ org/jivesoftware/smack/Connection.java	2010-02-03 23:56:56.000000000 +0100
+@@ -743,12 +743,12 @@
+                 if (debuggerClass == null) {
+                     try {
+                         debuggerClass =
+-                                Class.forName("org.jivesoftware.smackx.debugger.EnhancedDebugger");
++                                Class.forName("de.measite.smack.AndroidDebugger");
+                     }
+                     catch (Exception ex) {
+                         try {
+                             debuggerClass =
+-                                    Class.forName("org.jivesoftware.smack.debugger.LiteDebugger");
++                                    Class.forName("org.jivesoftware.smack.debugger.ConsoleDebugger");
+                         }
+                         catch (Exception ex2) {
+                             ex2.printStackTrace();
diff --git a/asmack-master/patch/31-remove-dns-wrapper.sh b/asmack-master/patch/31-remove-dns-wrapper.sh
new file mode 100755
index 0000000..c8c5ede
--- /dev/null
+++ b/asmack-master/patch/31-remove-dns-wrapper.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+rm org/xbill/DNS/spi/DNSJavaNameServiceDescriptor.java
+
diff --git a/asmack-master/patch/32-remove-jbosh-xlightweb.sh b/asmack-master/patch/32-remove-jbosh-xlightweb.sh
new file mode 100755
index 0000000..53ad364
--- /dev/null
+++ b/asmack-master/patch/32-remove-jbosh-xlightweb.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+rm com/kenai/jbosh/XLightWeb*.java
+
diff --git a/asmack-master/patch/33-jbosh-android.patch b/asmack-master/patch/33-jbosh-android.patch
new file mode 100644
index 0000000..33a9b7d
--- /dev/null
+++ b/asmack-master/patch/33-jbosh-android.patch
@@ -0,0 +1,446 @@
+diff --git com/kenai/jbosh/ApacheHTTPResponse.java com/kenai/jbosh/ApacheHTTPResponse.java
+new file mode 100644
+index 0000000..9f6731f
+--- /dev/null
++++ com/kenai/jbosh/ApacheHTTPResponse.java
+@@ -0,0 +1,253 @@
++/*
++ * Copyright 2009 Guenther Niess
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT 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 com.kenai.jbosh;
++
++import java.io.IOException;
++import java.util.concurrent.locks.Lock;
++import java.util.concurrent.locks.ReentrantLock;
++
++import org.apache.http.HttpEntity;
++import org.apache.http.HttpResponse;
++import org.apache.http.client.HttpClient;
++import org.apache.http.client.methods.HttpPost;
++import org.apache.http.entity.ByteArrayEntity;
++
++import org.apache.http.protocol.BasicHttpContext;
++import org.apache.http.protocol.HttpContext;
++import org.apache.http.util.EntityUtils;
++
++final class ApacheHTTPResponse implements HTTPResponse {
++
++    ///////////////////////////////////////////////////////////////////////////
++    // Constants:
++
++    /**
++     * Name of the accept encoding header.
++     */
++    private static final String ACCEPT_ENCODING = "Accept-Encoding";
++
++    /**
++     * Value to use for the ACCEPT_ENCODING header.
++     */
++    private static final String ACCEPT_ENCODING_VAL =
++            ZLIBCodec.getID() + ", " + GZIPCodec.getID();
++
++    /**
++     * Name of the character set to encode the body to/from.
++     */
++    private static final String CHARSET = "UTF-8";
++
++    /**
++     * Content type to use when transmitting the body data.
++     */
++    private static final String CONTENT_TYPE = "text/xml; charset=utf-8";
++
++    ///////////////////////////////////////////////////////////////////////////
++    // Class variables:
++
++    /**
++     * Lock used for internal synchronization.
++     */
++    private final Lock lock = new ReentrantLock();
++
++    /**
++     * The execution state of an HTTP process.
++     */
++    private final HttpContext context;
++
++    /**
++     * HttpClient instance to use to communicate.
++     */
++    private final HttpClient client;
++
++    /**
++     * The HTTP POST request is sent to the server.
++     */
++    private final HttpPost post;
++
++    /**
++     * A flag which indicates if the transmission was already done.
++     */
++    private boolean sent;
++
++    /**
++     * Exception to throw when the response data is attempted to be accessed,
++     * or {@code null} if no exception should be thrown.
++     */
++    private BOSHException toThrow;
++
++    /**
++     * The response body which was received from the server or {@code null}
++     * if that has not yet happened.
++     */
++    private AbstractBody body;
++
++    /**
++     * The HTTP response status code.
++     */
++    private int statusCode;
++
++    ///////////////////////////////////////////////////////////////////////////
++    // Constructors:
++
++    /**
++     * Create and send a new request to the upstream connection manager,
++     * providing deferred access to the results to be returned.
++     *
++     * @param client client instance to use when sending the request
++     * @param cfg client configuration
++     * @param params connection manager parameters from the session creation
++     *  response, or {@code null} if the session has not yet been established
++     * @param request body of the client request
++     */
++    ApacheHTTPResponse(
++            final HttpClient client,
++            final BOSHClientConfig cfg,
++            final CMSessionParams params,
++            final AbstractBody request) {
++        super();
++        this.client = client;
++        this.context = new BasicHttpContext();
++        this.post = new HttpPost(cfg.getURI().toString());
++        this.sent = false;
++
++        try {
++            String xml = request.toXML();
++            byte[] data = xml.getBytes(CHARSET);
++
++            String encoding = null;
++            if (cfg.isCompressionEnabled() && params != null) {
++                AttrAccept accept = params.getAccept();
++                if (accept != null) {
++                    if (accept.isAccepted(ZLIBCodec.getID())) {
++                        encoding = ZLIBCodec.getID();
++                        data = ZLIBCodec.encode(data);
++                    } else if (accept.isAccepted(GZIPCodec.getID())) {
++                        encoding = GZIPCodec.getID();
++                        data = GZIPCodec.encode(data);
++                    }
++                }
++            }
++
++            ByteArrayEntity entity = new ByteArrayEntity(data);
++            entity.setContentType(CONTENT_TYPE);
++            if (encoding != null) {
++                entity.setContentEncoding(encoding);
++            }
++            post.setEntity(entity);
++            if (cfg.isCompressionEnabled()) {
++                post.setHeader(ACCEPT_ENCODING, ACCEPT_ENCODING_VAL);
++            }
++        } catch (Exception e) {
++            toThrow = new BOSHException("Could not generate request", e);
++        }
++    }
++
++    ///////////////////////////////////////////////////////////////////////////
++    // HTTPResponse interface methods:
++
++    /**
++     * Abort the client transmission and response processing.
++     */
++    public void abort() {
++        if (post != null) {
++            post.abort();
++            toThrow = new BOSHException("HTTP request aborted");
++        }
++    }
++
++    /**
++     * Wait for and then return the response body.
++     *
++     * @return body of the response
++     * @throws InterruptedException if interrupted while awaiting the response
++     * @throws BOSHException on communication failure
++     */
++    public AbstractBody getBody() throws InterruptedException, BOSHException {
++        if (toThrow != null) {
++            throw(toThrow);
++        }
++        lock.lock();
++        try {
++            if (!sent) {
++                awaitResponse();
++            }
++        } finally {
++            lock.unlock();
++        }
++        return body;
++    }
++
++    /**
++     * Wait for and then return the response HTTP status code.
++     *
++     * @return HTTP status code of the response
++     * @throws InterruptedException if interrupted while awaiting the response
++     * @throws BOSHException on communication failure
++     */
++    public int getHTTPStatus() throws InterruptedException, BOSHException {
++        if (toThrow != null) {
++            throw(toThrow);
++        }
++        lock.lock();
++        try {
++            if (!sent) {
++                awaitResponse();
++            }
++        } finally {
++            lock.unlock();
++        }
++        return statusCode;
++    }
++
++    ///////////////////////////////////////////////////////////////////////////
++    // Package-private methods:
++
++    /**
++     * Await the response, storing the result in the instance variables of
++     * this class when they arrive.
++     *
++     * @throws InterruptedException if interrupted while awaiting the response
++     * @throws BOSHException on communication failure
++     */
++    private synchronized void awaitResponse() throws BOSHException {
++        HttpEntity entity = null;
++        try {
++            HttpResponse httpResp = client.execute(post, context);
++            entity = httpResp.getEntity();
++            byte[] data = EntityUtils.toByteArray(entity);
++            String encoding = entity.getContentEncoding() != null ?
++                    entity.getContentEncoding().getValue() :
++                    null;
++            if (ZLIBCodec.getID().equalsIgnoreCase(encoding)) {
++                data = ZLIBCodec.decode(data);
++            } else if (GZIPCodec.getID().equalsIgnoreCase(encoding)) {
++                data = GZIPCodec.decode(data);
++            }
++            body = StaticBody.fromString(new String(data, CHARSET));
++            statusCode = httpResp.getStatusLine().getStatusCode();
++            sent = true;
++        } catch (IOException iox) {
++            abort();
++            toThrow = new BOSHException("Could not obtain response", iox);
++            throw(toThrow);
++        } catch (RuntimeException ex) {
++            abort();
++            throw(ex);
++        }
++    }
++}
+diff --git com/kenai/jbosh/ApacheHTTPSender.java com/kenai/jbosh/ApacheHTTPSender.java
+new file mode 100644
+index 0000000..2abb4ee
+--- /dev/null
++++ com/kenai/jbosh/ApacheHTTPSender.java
+@@ -0,0 +1,156 @@
++/*
++ * Copyright 2009 Guenther Niess
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT 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 com.kenai.jbosh;
++
++import java.util.concurrent.locks.Lock;
++import java.util.concurrent.locks.ReentrantLock;
++
++import org.apache.http.HttpHost;
++import org.apache.http.HttpVersion;
++import org.apache.http.client.HttpClient;
++import org.apache.http.conn.ClientConnectionManager;
++import org.apache.http.conn.params.ConnManagerParams;
++import org.apache.http.conn.params.ConnRoutePNames;
++import org.apache.http.conn.scheme.PlainSocketFactory;
++import org.apache.http.conn.scheme.Scheme;
++import org.apache.http.conn.scheme.SchemeRegistry;
++import org.apache.http.conn.ssl.SSLSocketFactory;
++import org.apache.http.impl.client.DefaultHttpClient;
++import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
++import org.apache.http.params.BasicHttpParams;
++import org.apache.http.params.HttpParams;
++import org.apache.http.params.HttpProtocolParams;
++
++/**
++ * Implementation of the {@code HTTPSender} interface which uses the
++ * Apache HttpClient API to send messages to the connection manager.
++ */
++final class ApacheHTTPSender implements HTTPSender {
++
++    /**
++     * Lock used for internal synchronization.
++     */
++    private final Lock lock = new ReentrantLock();
++
++    /**
++     * Session configuration.
++     */
++    private BOSHClientConfig cfg;
++
++    /**
++     * HttpClient instance to use to communicate.
++     */
++    private HttpClient httpClient;
++
++    ///////////////////////////////////////////////////////////////////////////
++    // Constructors:
++
++    /**
++     * Prevent construction apart from our package.
++     */
++    ApacheHTTPSender() {
++        // Load Apache HTTP client class
++        HttpClient.class.getName();
++    }
++
++    ///////////////////////////////////////////////////////////////////////////
++    // HTTPSender interface methods:
++
++    /**
++     * {@inheritDoc}
++     */
++    public void init(final BOSHClientConfig session) {
++        lock.lock();
++        try {
++            cfg = session;
++            httpClient = initHttpClient(session);
++        } finally {
++            lock.unlock();
++        }
++    }
++
++    /**
++     * {@inheritDoc}
++     */
++    public void destroy() {
++        lock.lock();
++        try {
++            if (httpClient != null) {
++                httpClient.getConnectionManager().shutdown();
++            }
++        } finally {
++            cfg = null;
++            httpClient = null;
++            lock.unlock();
++        }
++    }
++
++    /**
++     * {@inheritDoc}
++     */
++    public HTTPResponse send(
++            final CMSessionParams params,
++            final AbstractBody body) {
++        HttpClient mClient;
++        BOSHClientConfig mCfg;
++        lock.lock();
++        try {
++            if (httpClient == null) {
++                httpClient = initHttpClient(cfg);
++            }
++            mClient = httpClient;
++            mCfg = cfg;
++        } finally {
++            lock.unlock();
++        }
++        return new ApacheHTTPResponse(mClient, mCfg, params, body);
++    }
++
++    ///////////////////////////////////////////////////////////////////////////
++    // Package-private methods:
++
++    private synchronized HttpClient initHttpClient(final BOSHClientConfig config) {
++        // Create and initialize HTTP parameters
++        HttpParams params = new BasicHttpParams();
++        ConnManagerParams.setMaxTotalConnections(params, 100);
++        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
++        HttpProtocolParams.setUseExpectContinue(params, false);
++        if (config != null &&
++                config.getProxyHost() != null &&
++                config.getProxyPort() != 0) {
++            HttpHost proxy = new HttpHost(
++                    config.getProxyHost(),
++                    config.getProxyPort());
++            params.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
++        }
++
++        // Create and initialize scheme registry 
++        SchemeRegistry schemeRegistry = new SchemeRegistry();
++        schemeRegistry.register(
++                new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
++            SSLSocketFactory sslFactory = SSLSocketFactory.getSocketFactory();
++            sslFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
++            schemeRegistry.register(
++                    new Scheme("https", sslFactory, 443));
++
++        // Create an HttpClient with the ThreadSafeClientConnManager.
++        // This connection manager must be used if more than one thread will
++        // be using the HttpClient.
++        ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
++        return new DefaultHttpClient(cm, params);
++    }
++}
+diff --git com/kenai/jbosh/BodyParserXmlPull.java com/kenai/jbosh/BodyParserXmlPull.java
+index cc95236..5f23b06 100644
+--- com/kenai/jbosh/BodyParserXmlPull.java
++++ com/kenai/jbosh/BodyParserXmlPull.java
+@@ -22,7 +22,6 @@ import java.lang.ref.SoftReference;
+ import java.util.logging.Level;
+ import java.util.logging.Logger;
+ import javax.xml.XMLConstants;
+-import javax.xml.namespace.QName;
+ import org.xmlpull.v1.XmlPullParser;
+ import org.xmlpull.v1.XmlPullParserException;
+ import org.xmlpull.v1.XmlPullParserFactory;
+diff --git com/kenai/jbosh/BodyQName.java com/kenai/jbosh/BodyQName.java
+index fc7ab0c..83acdf1 100644
+--- com/kenai/jbosh/BodyQName.java
++++ com/kenai/jbosh/BodyQName.java
+@@ -16,8 +16,6 @@
+ 
+ package com.kenai.jbosh;
+ 
+-import javax.xml.namespace.QName;
+-
+ /**
+  * Qualified name of an attribute of the wrapper element.  This class is
+  * analagous to the {@code javax.xml.namespace.QName} class.
diff --git a/asmack-master/patch/34-pin-jbosh-http-sender.patch b/asmack-master/patch/34-pin-jbosh-http-sender.patch
new file mode 100644
index 0000000..daf96df
--- /dev/null
+++ b/asmack-master/patch/34-pin-jbosh-http-sender.patch
@@ -0,0 +1,11 @@
+--- com/kenai/jbosh/BOSHClient.java	2010-01-13 20:57:36.000000000 +0100
++++ com/kenai/jbosh/BOSHClient.java	2010-02-04 17:40:45.678169320 +0100
+@@ -232,7 +232,7 @@
+      * HTTPSender instance.
+      */
+     private final HTTPSender httpSender =
+-            ServiceLib.loadService(HTTPSender.class);
++            new ApacheHTTPSender();
+ 
+     /**
+      * Storage for test hook implementation.
diff --git a/asmack-master/patch/35-pin-jbosh-boddy-parser.patch b/asmack-master/patch/35-pin-jbosh-boddy-parser.patch
new file mode 100644
index 0000000..f4c63e8
--- /dev/null
+++ b/asmack-master/patch/35-pin-jbosh-boddy-parser.patch
@@ -0,0 +1,11 @@
+--- com/kenai/jbosh/StaticBody.java	2010-01-13 20:57:36.000000000 +0100
++++ com/kenai/jbosh/StaticBody.java	2010-02-04 17:59:06.037770746 +0100
+@@ -42,7 +42,7 @@
+      * Selected parser to be used to process raw XML messages.
+      */
+     private static final BodyParser PARSER =
+-            ServiceLib.loadService(BodyParser.class);
++            new BodyParserXmlPull();
+ 
+     /**
+      * Size of the internal buffer when copying from a stream.
diff --git a/asmack-master/patch/40-enable-custom-sasl.sh b/asmack-master/patch/40-enable-custom-sasl.sh
new file mode 100755
index 0000000..476bd5b
--- /dev/null
+++ b/asmack-master/patch/40-enable-custom-sasl.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+find -name '*.java' -exec sed -i 's:import org.apache.harmony.javax.security.sasl.Sasl;:import de.measite.smack.Sasl;:g' '{}' ';'
+
diff --git a/asmack-master/patch/41-fix-digest-md5.patch b/asmack-master/patch/41-fix-digest-md5.patch
new file mode 100644
index 0000000..5f7f1dc
--- /dev/null
+++ b/asmack-master/patch/41-fix-digest-md5.patch
@@ -0,0 +1,13 @@
+--- ../../src-unpatched/trunk/com/novell/sasl/client/DigestMD5SaslClient.java	2009-12-07 19:14:10.000000000 +0100
++++ com/novell/sasl/client/DigestMD5SaslClient.java	2009-12-07 19:19:07.000000000 +0100
+@@ -673,8 +673,8 @@
+         digestResponse.append("00000001"); //nounce count
+         digestResponse.append(",qop=");
+         digestResponse.append(m_qopValue);
+-        digestResponse.append(",digest-uri=\"ldap/");
+-        digestResponse.append(m_serverName);
++        digestResponse.append(",digest-uri=\"");
++	digestResponse.append(m_digestURI);
+         digestResponse.append("\",response=");
+         digestResponse.append(response);
+         digestResponse.append(",charset=utf-8,nonce=\"");
diff --git a/asmack-master/patch/beem/10-PubSubManager-non-final.patch b/asmack-master/patch/beem/10-PubSubManager-non-final.patch
new file mode 100644
index 0000000..4fca228
--- /dev/null
+++ b/asmack-master/patch/beem/10-PubSubManager-non-final.patch
@@ -0,0 +1,13 @@
+Index: org/jivesoftware/smackx/pubsub/PubSubManager.java
+===================================================================
+--- org/jivesoftware/smackx/pubsub/PubSubManager.java	(revision 11464)
++++ org/jivesoftware/smackx/pubsub/PubSubManager.java	(working copy)
+@@ -41,7 +41,7 @@
+  * 

+  * @author Robin Collier

+  */

+-final public class PubSubManager

++public class PubSubManager

+ {

+ 	private XMPPConnection con;

+ 	private String to;

diff --git a/asmack-master/patch/beem/50-improved-pubsub.patch b/asmack-master/patch/beem/50-improved-pubsub.patch
new file mode 100644
index 0000000..a3704e7
--- /dev/null
+++ b/asmack-master/patch/beem/50-improved-pubsub.patch
@@ -0,0 +1,46 @@
+--- ../../../src/smack/org/jivesoftware/smackx/pubsub/provider/ItemProvider.java	(révision 11644)
++++ org/jivesoftware/smackx/pubsub/provider/ItemProvider.java	(copie de travail)
+@@ -45,6 +45,8 @@
+ 		}

+ 		else

+ 		{

++		    while (tag != XmlPullParser.START_TAG)

++			tag = parser.next();

+ 			String payloadElemName = parser.getName();

+ 			String payloadNS = parser.getNamespace();

+ 			

+--- ../../../src/org/jivesoftware/smackx/pubsub/Node.java	(révision 11644)
++++ org/jivesoftware/smackx/pubsub/Node.java	(copie de travail)
+@@ -60,7 +60,7 @@
+ 	 * 

+ 	 *   For example, OpenFire requires the server to be prefixed by <b>pubsub</b>

+ 	 */

+-	void setTo(String toAddress)

++	public void setTo(String toAddress)

+ 	{

+ 		to = toAddress;

+ 	}

+--- ../../../src/org/jivesoftware/smackx/pubsub/LeafNode.java	(révision 11644)
++++ org/jivesoftware/smackx/pubsub/LeafNode.java	(copie de travail)
+@@ -34,7 +34,7 @@
+  */

+ public class LeafNode extends Node

+ {

+-	LeafNode(Connection connection, String nodeName)

++	public LeafNode(Connection connection, String nodeName)

+ 	{

+ 		super(connection, nodeName);

+ 	}

+--- ../../../src/org/jivesoftware/smackx/pubsub/PubSubManager.java	(révision 11644)
++++ org/jivesoftware/smackx/pubsub/PubSubManager.java	(copie de travail)
+@@ -43,8 +43,8 @@
+  */

+ final public class PubSubManager

+ {

+-	private Connection con;

+-	private String to;

++	protected Connection con;

++	protected String to;

+ 	private Map<String, Node> nodeMap = new ConcurrentHashMap<String, Node>();

+ 	

+ 	/**

diff --git a/asmack-master/patch/beem/COPYING b/asmack-master/patch/beem/COPYING
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/asmack-master/patch/beem/COPYING
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/asmack-master/patch/beem/README.txt b/asmack-master/patch/beem/README.txt
new file mode 100644
index 0000000..ce58c89
--- /dev/null
+++ b/asmack-master/patch/beem/README.txt
@@ -0,0 +1,9 @@
+This directory contains different patch to apply on asmack sources. These
+patches will allow us to build a custom flavour of asmack for Beem.  This
+directory must be copied in the patch directory of asmack in order to be used.
+Then build asmack the usual way.
+
+All the patches are released under the Apache License, Version 2.0
+You may obtain a copy of the License at
+http://www.apache.org.licenses/LICENCE-2.0
+
diff --git a/asmack-master/patch/oldpatch/45-protected-xmpp-socket.patch b/asmack-master/patch/oldpatch/45-protected-xmpp-socket.patch
new file mode 100644
index 0000000..72f2d97
--- /dev/null
+++ b/asmack-master/patch/oldpatch/45-protected-xmpp-socket.patch
@@ -0,0 +1,11 @@
+--- org/jivesoftware/smack/XMPPConnection.java	2010-02-13 11:13:16.478541616 +0100
++++ org/jivesoftware/smack/XMPPConnection.java	2010-02-13 11:58:49.798590947 +0100
+@@ -55,7 +55,7 @@
+     /**
+      * The socket which is used for this connection.
+      */
+-    Socket socket;
++    protected Socket socket;
+ 
+     String connectionID = null;
+     private String user = null;
diff --git a/asmack-master/static-src/custom/META-INF/services/com.kenai.jbosh.HTTPSender b/asmack-master/static-src/custom/META-INF/services/com.kenai.jbosh.HTTPSender
new file mode 100644
index 0000000..3608d8e
--- /dev/null
+++ b/asmack-master/static-src/custom/META-INF/services/com.kenai.jbosh.HTTPSender
@@ -0,0 +1 @@
+com.kenai.jbosh.ApacheHTTPSender
diff --git a/asmack-master/static-src/custom/com/kenai/jbosh/QName.java b/asmack-master/static-src/custom/com/kenai/jbosh/QName.java
new file mode 100644
index 0000000..d395a06
--- /dev/null
+++ b/asmack-master/static-src/custom/com/kenai/jbosh/QName.java
@@ -0,0 +1,269 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Axis" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package com.kenai.jbosh;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+/**
+ * <code>QName</code> class represents the value of a qualified name
+ * as specified in <a href="http://www.w3.org/TR/xmlschema-2/#QName">XML
+ * Schema Part2: Datatypes specification</a>.
+ * <p>
+ * The value of a QName contains a <b>namespaceURI</b>, a <b>localPart</b> and a <b>prefix</b>.
+ * The localPart provides the local part of the qualified name. The
+ * namespaceURI is a URI reference identifying the namespace.
+ *
+ * @version 1.1
+ */
+public class QName implements Serializable {
+
+    /** comment/shared empty string */
+    private static final String emptyString = "".intern();
+
+    /** Field namespaceURI */
+    private String namespaceURI;
+
+    /** Field localPart */
+    private String localPart;
+
+    /** Field prefix */
+    private String prefix;
+
+    /**
+     * Constructor for the QName.
+     *
+     * @param localPart Local part of the QName
+     */
+    public QName(String localPart) {
+        this(emptyString, localPart, emptyString);
+    }
+
+    /**
+     * Constructor for the QName.
+     *
+     * @param namespaceURI Namespace URI for the QName
+     * @param localPart Local part of the QName.
+     */
+    public QName(String namespaceURI, String localPart) {
+        this(namespaceURI, localPart, emptyString);
+    }
+
+    /**
+     * Constructor for the QName.
+     *
+     * @param namespaceURI Namespace URI for the QName
+     * @param localPart Local part of the QName.
+     * @param prefix Prefix of the QName.
+     */
+    public QName(String namespaceURI, String localPart, String prefix) {
+        this.namespaceURI = (namespaceURI == null)
+                ? emptyString
+                : namespaceURI.intern();
+        if (localPart == null) {
+            throw new IllegalArgumentException("invalid QName local part");
+        } else {
+            this.localPart = localPart.intern();
+        }
+
+        if (prefix == null) {
+            throw new IllegalArgumentException("invalid QName prefix");
+        } else {
+            this.prefix = prefix.intern();
+        }
+    }
+
+    /**
+     * Gets the Namespace URI for this QName
+     *
+     * @return Namespace URI
+     */
+    public String getNamespaceURI() {
+        return namespaceURI;
+    }
+
+    /**
+     * Gets the Local part for this QName
+     *
+     * @return Local part
+     */
+    public String getLocalPart() {
+        return localPart;
+    }
+
+    /**
+     * Gets the Prefix for this QName
+     *
+     * @return Prefix
+     */
+    public String getPrefix() {
+        return prefix;
+    }
+
+    /**
+     * Returns a string representation of this QName
+     *
+     * @return  a string representation of the QName
+     */
+    public String toString() {
+
+        return ((namespaceURI == emptyString)
+                ? localPart
+                : '{' + namespaceURI + '}' + localPart);
+    }
+
+    /**
+     * Tests this QName for equality with another object.
+     * <p>
+     * If the given object is not a QName or is null then this method
+     * returns <tt>false</tt>.
+     * <p>
+     * For two QNames to be considered equal requires that both
+     * localPart and namespaceURI must be equal. This method uses
+     * <code>String.equals</code> to check equality of localPart
+     * and namespaceURI. Any class that extends QName is required
+     * to satisfy this equality contract.
+     * <p>
+     * This method satisfies the general contract of the <code>Object.equals</code> method.
+     *
+     * @param obj the reference object with which to compare
+     *
+     * @return <code>true</code> if the given object is identical to this
+     *      QName: <code>false</code> otherwise.
+     */
+    public final boolean equals(Object obj) {
+
+        if (obj == this) {
+            return true;
+        }
+
+        if (!(obj instanceof QName)) {
+            return false;
+        }
+
+        if ((namespaceURI == ((QName) obj).namespaceURI)
+                && (localPart == ((QName) obj).localPart)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns a QName holding the value of the specified String.
+     * <p>
+     * The string must be in the form returned by the QName.toString()
+     * method, i.e. "{namespaceURI}localPart", with the "{namespaceURI}"
+     * part being optional.
+     * <p>
+     * This method doesn't do a full validation of the resulting QName.
+     * In particular, it doesn't check that the resulting namespace URI
+     * is a legal URI (per RFC 2396 and RFC 2732), nor that the resulting
+     * local part is a legal NCName per the XML Namespaces specification.
+     *
+     * @param s the string to be parsed
+     * @throws java.lang.IllegalArgumentException If the specified String cannot be parsed as a QName
+     * @return QName corresponding to the given String
+     */
+    public static QName valueOf(String s) {
+
+        if ((s == null) || s.equals("")) {
+            throw new IllegalArgumentException("invalid QName literal");
+        }
+
+        if (s.charAt(0) == '{') {
+            int i = s.indexOf('}');
+
+            if (i == -1) {
+                throw new IllegalArgumentException("invalid QName literal");
+            }
+
+            if (i == s.length() - 1) {
+                throw new IllegalArgumentException("invalid QName literal");
+            } else {
+                return new QName(s.substring(1, i), s.substring(i + 1));
+            }
+        } else {
+            return new QName(s);
+        }
+    }
+
+    /**
+     * Returns a hash code value for this QName object. The hash code
+     * is based on both the localPart and namespaceURI parts of the
+     * QName. This method satisfies the  general contract of the
+     * <code>Object.hashCode</code> method.
+     *
+     * @return a hash code value for this Qname object
+     */
+    public final int hashCode() {
+        return namespaceURI.hashCode() ^ localPart.hashCode();
+    }
+
+    /**
+     * Ensure that deserialization properly interns the results.
+     * @param in the ObjectInputStream to be read
+     */
+    private void readObject(ObjectInputStream in) throws
+            IOException, ClassNotFoundException {
+        in.defaultReadObject();
+
+        namespaceURI = namespaceURI.intern();
+        localPart = localPart.intern();
+        prefix = prefix.intern();
+    }
+}
+
diff --git a/asmack-master/static-src/custom/de/measite/smack/AndroidDebugger.java b/asmack-master/static-src/custom/de/measite/smack/AndroidDebugger.java
new file mode 100644
index 0000000..4dfc622
--- /dev/null
+++ b/asmack-master/static-src/custom/de/measite/smack/AndroidDebugger.java
@@ -0,0 +1,185 @@
+package de.measite.smack;
+
+import org.jivesoftware.smack.debugger.SmackDebugger;
+import org.jivesoftware.smack.ConnectionListener;
+import org.jivesoftware.smack.PacketListener;
+import org.jivesoftware.smack.Connection;
+import org.jivesoftware.smack.packet.Packet;
+import org.jivesoftware.smack.util.*;
+
+import android.util.Log;
+
+import java.io.Reader;
+import java.io.Writer;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Very simple debugger that prints to the android log the sent and received stanzas. Use
+ * this debugger with caution since printing to the console is an expensive operation that may
+ * even block the thread since only one thread may print at a time.<p>
+ * <p/>
+ * It is possible to not only print the raw sent and received stanzas but also the interpreted
+ * packets by Smack. By default interpreted packets won't be printed. To enable this feature
+ * just change the <tt>printInterpreted</tt> static variable to <tt>true</tt>.
+ *
+ * @author Gaston Dombiak
+ */
+public class AndroidDebugger implements SmackDebugger {
+
+    public static boolean printInterpreted = false;
+    private SimpleDateFormat dateFormatter = new SimpleDateFormat("hh:mm:ss aaa");
+
+    private Connection connection = null;
+
+    private PacketListener listener = null;
+    private ConnectionListener connListener = null;
+
+    private Writer writer;
+    private Reader reader;
+    private ReaderListener readerListener;
+    private WriterListener writerListener;
+
+    public AndroidDebugger(Connection connection, Writer writer, Reader reader) {
+        this.connection = connection;
+        this.writer = writer;
+        this.reader = reader;
+        createDebug();
+    }
+
+    /**
+     * Creates the listeners that will print in the console when new activity is detected.
+     */
+    private void createDebug() {
+        // Create a special Reader that wraps the main Reader and logs data to the GUI.
+        ObservableReader debugReader = new ObservableReader(reader);
+        readerListener = new ReaderListener() {
+            public void read(String str) {
+            	Log.d("SMACK",
+                        dateFormatter.format(new Date()) + " RCV  (" + connection.hashCode() +
+                        "): " +
+                        str);
+            }
+        };
+        debugReader.addReaderListener(readerListener);
+
+        // Create a special Writer that wraps the main Writer and logs data to the GUI.
+        ObservableWriter debugWriter = new ObservableWriter(writer);
+        writerListener = new WriterListener() {
+            public void write(String str) {
+            	Log.d("SMACK",
+                        dateFormatter.format(new Date()) + " SENT (" + connection.hashCode() +
+                        "): " +
+                        str);
+            }
+        };
+        debugWriter.addWriterListener(writerListener);
+
+        // Assign the reader/writer objects to use the debug versions. The packet reader
+        // and writer will use the debug versions when they are created.
+        reader = debugReader;
+        writer = debugWriter;
+
+        // Create a thread that will listen for all incoming packets and write them to
+        // the GUI. This is what we call "interpreted" packet data, since it's the packet
+        // data as Smack sees it and not as it's coming in as raw XML.
+        listener = new PacketListener() {
+            public void processPacket(Packet packet) {
+                if (printInterpreted) {
+                	Log.d("SMACK",
+                            dateFormatter.format(new Date()) + " RCV PKT (" +
+                            connection.hashCode() +
+                            "): " +
+                            packet.toXML());
+                }
+            }
+        };
+
+        connListener = new ConnectionListener() {
+            public void connectionClosed() {
+                Log.d("SMACK",
+                        dateFormatter.format(new Date()) + " Connection closed (" +
+                        connection.hashCode() +
+                        ")");
+            }
+
+            public void connectionClosedOnError(Exception e) {
+                Log.d("SMACK",
+                        dateFormatter.format(new Date()) +
+                        " Connection closed due to an exception (" +
+                        connection.hashCode() +
+                        ")");
+                e.printStackTrace();
+            }
+            public void reconnectionFailed(Exception e) {
+                Log.d("SMACK",
+                        dateFormatter.format(new Date()) +
+                        " Reconnection failed due to an exception (" +
+                        connection.hashCode() +
+                        ")");
+                e.printStackTrace();
+            }
+            public void reconnectionSuccessful() {
+                Log.d("SMACK",
+                        dateFormatter.format(new Date()) + " Connection reconnected (" +
+                        connection.hashCode() +
+                        ")");
+            }
+            public void reconnectingIn(int seconds) {
+                Log.d("SMACK",
+                        dateFormatter.format(new Date()) + " Connection (" +
+                        connection.hashCode() +
+                        ") will reconnect in " + seconds);
+            }
+        };
+    }
+
+    public Reader newConnectionReader(Reader newReader) {
+        ((ObservableReader)reader).removeReaderListener(readerListener);
+        ObservableReader debugReader = new ObservableReader(newReader);
+        debugReader.addReaderListener(readerListener);
+        reader = debugReader;
+        return reader;
+    }
+
+    public Writer newConnectionWriter(Writer newWriter) {
+        ((ObservableWriter)writer).removeWriterListener(writerListener);
+        ObservableWriter debugWriter = new ObservableWriter(newWriter);
+        debugWriter.addWriterListener(writerListener);
+        writer = debugWriter;
+        return writer;
+    }
+
+    public void userHasLogged(String user) {
+        boolean isAnonymous = "".equals(StringUtils.parseName(user));
+        String title =
+                "User logged (" + connection.hashCode() + "): "
+                + (isAnonymous ? "" : StringUtils.parseBareAddress(user))
+                + "@"
+                + connection.getServiceName()
+                + ":"
+                + connection.getPort();
+        title += "/" + StringUtils.parseResource(user);
+        Log.d("SMACK", title);
+        // Add the connection listener to the connection so that the debugger can be notified
+        // whenever the connection is closed.
+        connection.addConnectionListener(connListener);
+    }
+
+    public Reader getReader() {
+        return reader;
+    }
+
+    public Writer getWriter() {
+        return writer;
+    }
+
+    public PacketListener getReaderListener() {
+        return listener;
+    }
+
+    public PacketListener getWriterListener() {
+        return null;
+    }
+}
+
diff --git a/asmack-master/static-src/custom/de/measite/smack/Sasl.java b/asmack-master/static-src/custom/de/measite/smack/Sasl.java
new file mode 100644
index 0000000..a59135d
--- /dev/null
+++ b/asmack-master/static-src/custom/de/measite/smack/Sasl.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2009 Rene Treffer
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 de.measite.smack;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.harmony.javax.security.auth.callback.CallbackHandler;
+import org.apache.harmony.javax.security.sasl.SaslClient;
+import org.apache.harmony.javax.security.sasl.SaslException;
+import org.apache.harmony.javax.security.sasl.SaslServer;
+import org.apache.harmony.javax.security.sasl.SaslServerFactory;
+
+public class Sasl {
+
+    // SaslClientFactory service name
+    private static final String CLIENTFACTORYSRV = "SaslClientFactory"; //$NON-NLS-1$
+
+    // SaslServerFactory service name
+    private static final String SERVERFACTORYSRV = "SaslServerFactory"; //$NON-NLS-1$
+
+    public static final String POLICY_NOPLAINTEXT = "javax.security.sasl.policy.noplaintext"; //$NON-NLS-1$
+
+    public static final String POLICY_NOACTIVE = "javax.security.sasl.policy.noactive"; //$NON-NLS-1$
+
+    public static final String POLICY_NODICTIONARY = "javax.security.sasl.policy.nodictionary"; //$NON-NLS-1$
+
+    public static final String POLICY_NOANONYMOUS = "javax.security.sasl.policy.noanonymous"; //$NON-NLS-1$
+
+    public static final String POLICY_FORWARD_SECRECY = "javax.security.sasl.policy.forward"; //$NON-NLS-1$
+
+    public static final String POLICY_PASS_CREDENTIALS = "javax.security.sasl.policy.credentials"; //$NON-NLS-1$
+
+    public static final String MAX_BUFFER = "javax.security.sasl.maxbuffer"; //$NON-NLS-1$
+
+    public static final String RAW_SEND_SIZE = "javax.security.sasl.rawsendsize"; //$NON-NLS-1$
+
+    public static final String REUSE = "javax.security.sasl.reuse"; //$NON-NLS-1$
+
+    public static final String QOP = "javax.security.sasl.qop"; //$NON-NLS-1$
+
+    public static final String STRENGTH = "javax.security.sasl.strength"; //$NON-NLS-1$
+
+    public static final String SERVER_AUTH = "javax.security.sasl.server.authentication"; //$NON-NLS-1$
+
+    public static Enumeration<SaslClientFactory> getSaslClientFactories() {
+        Hashtable<SaslClientFactory,Object> factories = new Hashtable<SaslClientFactory,Object>();
+        factories.put(new SaslClientFactory(), new Object());
+        return factories.keys();
+    }
+
+    public static Enumeration<SaslServerFactory> getSaslServerFactories() {
+        return org.apache.harmony.javax.security.sasl.Sasl.getSaslServerFactories();
+    }
+
+    public static SaslServer createSaslServer(String mechanism, String protocol,
+            String serverName, Map<String, ?> prop, CallbackHandler cbh) throws SaslException {
+        return org.apache.harmony.javax.security.sasl.Sasl.createSaslServer(mechanism, protocol, serverName, prop, cbh);
+    }
+
+    public static SaslClient createSaslClient(String[] mechanisms, String authanticationID,
+            String protocol, String serverName, Map<String, ?> prop, CallbackHandler cbh)
+            throws SaslException {
+        if (mechanisms == null) {
+            throw new NullPointerException("auth.33"); //$NON-NLS-1$
+        }
+        SaslClientFactory fact = getSaslClientFactories().nextElement();
+        String[] mech = fact.getMechanismNames(null);
+        boolean is = false;
+        if (mech != null) {
+            for (int j = 0; j < mech.length; j++) {
+                for (int n = 0; n < mechanisms.length; n++) {
+                    if (mech[j].equals(mechanisms[n])) {
+                        is = true;
+                        break;
+                    }
+                }
+            }
+        }
+        if (is) {
+            return fact.createSaslClient(
+                mechanisms,
+                authanticationID,
+                protocol,
+                serverName,
+                prop,
+                cbh
+            );
+        }
+        return null;
+    }
+
+}
diff --git a/asmack-master/static-src/custom/de/measite/smack/SaslClientFactory.java b/asmack-master/static-src/custom/de/measite/smack/SaslClientFactory.java
new file mode 100644
index 0000000..2fa1ebd
--- /dev/null
+++ b/asmack-master/static-src/custom/de/measite/smack/SaslClientFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2009 Rene Treffer
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 de.measite.smack;
+
+import java.util.Map;
+
+import com.novell.sasl.client.DigestMD5SaslClient;
+
+import org.apache.harmony.javax.security.auth.callback.CallbackHandler;
+import org.apache.harmony.javax.security.sasl.SaslClient;
+import org.apache.harmony.javax.security.sasl.SaslException;
+import org.apache.qpid.management.common.sasl.PlainSaslClient;
+
+public class SaslClientFactory implements
+		org.apache.harmony.javax.security.sasl.SaslClientFactory {
+
+	@Override
+	public SaslClient createSaslClient(String[] mechanisms,
+			String authorizationId, String protocol, String serverName,
+			Map<String, ?> props, CallbackHandler cbh) throws SaslException {
+		for (String mech: mechanisms) {
+			if ("PLAIN".equals(mech)) {
+				return new PlainSaslClient(authorizationId, cbh);
+			} else
+			if ("DIGEST-MD5".equals(mech)) {
+				return DigestMD5SaslClient.getClient(
+					authorizationId,
+					protocol,
+					serverName,
+					props,
+					cbh
+				);
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public String[] getMechanismNames(Map<String, ?> props) {
+		return new String[]{
+			"PLAIN",
+			"DIGEST-MD5"
+		};
+	}
+
+}
diff --git a/asmack-master/static-src/custom/org/jivesoftware/smack/AndroidConnectionConfiguration.java b/asmack-master/static-src/custom/org/jivesoftware/smack/AndroidConnectionConfiguration.java
new file mode 100644
index 0000000..6ec05e0
--- /dev/null
+++ b/asmack-master/static-src/custom/org/jivesoftware/smack/AndroidConnectionConfiguration.java
@@ -0,0 +1,113 @@
+package org.jivesoftware.smack;
+
+import java.io.File;
+
+import android.os.Build;
+
+import org.jivesoftware.smack.proxy.ProxyInfo;
+import org.jivesoftware.smack.util.DNSUtil;
+import org.jivesoftware.smack.util.dns.HostAddress;
+
+import java.util.List;
+
+/**
+ * This class wraps DNS SRV lookups for a new ConnectionConfiguration in a 
+ * new thread, since Android API >= 11 (Honeycomb) does not allow network 
+ * activity in the main thread. 
+ * 
+ * @author Florian Schmaus fschmaus@gmail.com
+ *
+ */
+public class AndroidConnectionConfiguration extends ConnectionConfiguration {
+    private static final int DEFAULT_TIMEOUT = 10000;
+    
+    /**
+     * Creates a new ConnectionConfiguration for the specified service name.
+     * A DNS SRV lookup will be performed to find out the actual host address
+     * and port to use for the connection.
+     *
+     * @param serviceName the name of the service provided by an XMPP server.
+     */
+    public AndroidConnectionConfiguration(String serviceName) throws XMPPException {
+        super();
+        AndroidInit(serviceName, DEFAULT_TIMEOUT);
+    }
+    
+    /**
+     * 
+     * @param serviceName
+     * @param timeout
+     * @throws XMPPException
+     */
+    public AndroidConnectionConfiguration(String serviceName, int timeout) throws XMPPException {
+        super();
+        AndroidInit(serviceName, timeout);
+    }
+
+    public AndroidConnectionConfiguration(String host, int port, String name) {
+	super(host, port, name);
+	AndroidInit();
+    }
+
+    private void AndroidInit() {
+    	// API 14 is Ice Cream Sandwich
+	if (Build.VERSION.SDK_INT >= 14) {
+	    setTruststoreType("AndroidCAStore");
+	    setTruststorePassword(null);
+	    setTruststorePath(null);
+	} else {
+	    setTruststoreType("BKS");
+	    String path = System.getProperty("javax.net.ssl.trustStore");
+	    if (path == null)
+		path = System.getProperty("java.home") + File.separator + "etc"
+		    + File.separator + "security" + File.separator
+		    + "cacerts.bks";
+	    setTruststorePath(path);
+	}
+    }
+
+    /**
+     * 
+     * @param serviceName
+     * @param timeout
+     * @throws XMPPException
+     */
+    private void AndroidInit(String serviceName, int timeout) throws XMPPException {
+	AndroidInit();
+        class DnsSrvLookupRunnable implements Runnable {
+            String serviceName;
+            List<HostAddress> addresses;
+
+            public DnsSrvLookupRunnable(String serviceName) {
+                this.serviceName = serviceName;
+            }
+
+            @Override
+            public void run() {
+                addresses = DNSUtil.resolveXMPPDomain(serviceName);
+            }
+
+            public List<HostAddress> getHostAddresses() {
+                return addresses;
+            }
+        }
+
+        DnsSrvLookupRunnable dnsSrv = new DnsSrvLookupRunnable(serviceName);
+        Thread t = new Thread(dnsSrv, "dns-srv-lookup");
+        t.start();
+        try {
+            t.join(timeout);
+        } catch (InterruptedException e) {
+            throw new XMPPException("DNS lookup timeout after " + timeout + "ms", e);
+        }
+
+        hostAddresses = dnsSrv.getHostAddresses();
+        if (hostAddresses == null) {
+        	throw new XMPPException("DNS lookup failure");
+        }
+
+        ProxyInfo proxy = ProxyInfo.forDefaultProxy();
+
+        init(serviceName, proxy);
+    }
+}
diff --git a/asmack-master/static-src/custom/org/jivesoftware/smack/SmackAndroid.java b/asmack-master/static-src/custom/org/jivesoftware/smack/SmackAndroid.java
new file mode 100644
index 0000000..a18d675
--- /dev/null
+++ b/asmack-master/static-src/custom/org/jivesoftware/smack/SmackAndroid.java
@@ -0,0 +1,59 @@
+package org.jivesoftware.smack;
+
+import org.jivesoftware.smack.util.DNSUtil;
+import org.jivesoftware.smack.util.dns.DNSJavaResolver;
+import org.jivesoftware.smackx.ConfigureProviderManager;
+import org.jivesoftware.smackx.InitStaticCode;
+import org.xbill.DNS.ResolverConfig;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+public class SmackAndroid {
+    private static SmackAndroid sSmackAndroid = null;
+
+    private BroadcastReceiver mConnectivityChangedReceiver;
+    private Context mCtx;
+
+    private SmackAndroid(Context ctx) {
+        mCtx = ctx;
+        DNSUtil.setDNSResolver(DNSJavaResolver.getInstance());
+        InitStaticCode.initStaticCode(ctx);
+        ConfigureProviderManager.configureProviderManager();
+        maybeRegisterReceiver();
+    }
+
+    public static SmackAndroid init(Context ctx) {
+        if (sSmackAndroid == null) {
+            sSmackAndroid = new SmackAndroid(ctx);
+        } else {
+            sSmackAndroid.maybeRegisterReceiver();
+        }
+        return sSmackAndroid;
+    }
+
+    public void onDestroy() {
+        if (mConnectivityChangedReceiver != null) {
+            mCtx.unregisterReceiver(mConnectivityChangedReceiver);
+            mConnectivityChangedReceiver = null;
+        }
+    }
+
+    private void maybeRegisterReceiver() {
+        if (mConnectivityChangedReceiver == null) {
+            mConnectivityChangedReceiver = new ConnectivtyChangedReceiver();
+            mCtx.registerReceiver(mConnectivityChangedReceiver, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"));
+        }
+    }
+
+    class ConnectivtyChangedReceiver extends BroadcastReceiver {
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            ResolverConfig.refresh();
+        }
+
+    }
+}
diff --git a/asmack-master/static-src/custom/org/jivesoftware/smackx/ConfigureProviderManager.java b/asmack-master/static-src/custom/org/jivesoftware/smackx/ConfigureProviderManager.java
new file mode 100644
index 0000000..7c0cdf2
--- /dev/null
+++ b/asmack-master/static-src/custom/org/jivesoftware/smackx/ConfigureProviderManager.java
@@ -0,0 +1,207 @@
+/**
+ * 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.provider.PrivacyProvider;
+import org.jivesoftware.smack.provider.ProviderManager;
+import org.jivesoftware.smackx.GroupChatInvitation;
+import org.jivesoftware.smackx.PrivateDataManager;
+import org.jivesoftware.smackx.bytestreams.ibb.provider.CloseIQProvider;
+import org.jivesoftware.smackx.bytestreams.ibb.provider.DataPacketProvider;
+import org.jivesoftware.smackx.bytestreams.ibb.provider.OpenIQProvider;
+import org.jivesoftware.smackx.bytestreams.socks5.provider.BytestreamsProvider;
+import org.jivesoftware.smackx.carbons.Carbon;
+import org.jivesoftware.smackx.entitycaps.provider.CapsExtensionProvider;
+import org.jivesoftware.smackx.forward.Forwarded;
+import org.jivesoftware.smackx.packet.AttentionExtension;
+import org.jivesoftware.smackx.packet.ChatStateExtension;
+import org.jivesoftware.smackx.packet.LastActivity;
+import org.jivesoftware.smackx.packet.Nick;
+import org.jivesoftware.smackx.packet.OfflineMessageInfo;
+import org.jivesoftware.smackx.packet.OfflineMessageRequest;
+import org.jivesoftware.smackx.packet.SharedGroupsInfo;
+import org.jivesoftware.smackx.ping.provider.PingProvider;
+import org.jivesoftware.smackx.provider.DataFormProvider;
+import org.jivesoftware.smackx.provider.DelayInformationProvider;
+import org.jivesoftware.smackx.provider.DiscoverInfoProvider;
+import org.jivesoftware.smackx.provider.DiscoverItemsProvider;
+import org.jivesoftware.smackx.provider.HeadersProvider;
+import org.jivesoftware.smackx.provider.HeaderProvider;
+import org.jivesoftware.smackx.provider.MUCAdminProvider;
+import org.jivesoftware.smackx.provider.MUCOwnerProvider;
+import org.jivesoftware.smackx.provider.MUCUserProvider;
+import org.jivesoftware.smackx.provider.MessageEventProvider;
+import org.jivesoftware.smackx.provider.MultipleAddressesProvider;
+import org.jivesoftware.smackx.provider.RosterExchangeProvider;
+import org.jivesoftware.smackx.provider.StreamInitiationProvider;
+import org.jivesoftware.smackx.provider.VCardProvider;
+import org.jivesoftware.smackx.provider.XHTMLExtensionProvider;
+import org.jivesoftware.smackx.pubsub.provider.AffiliationProvider;
+import org.jivesoftware.smackx.pubsub.provider.AffiliationsProvider;
+import org.jivesoftware.smackx.pubsub.provider.ConfigEventProvider;
+import org.jivesoftware.smackx.pubsub.provider.EventProvider;
+import org.jivesoftware.smackx.pubsub.provider.FormNodeProvider;
+import org.jivesoftware.smackx.pubsub.provider.ItemProvider;
+import org.jivesoftware.smackx.pubsub.provider.ItemsProvider;
+import org.jivesoftware.smackx.pubsub.provider.PubSubProvider;
+import org.jivesoftware.smackx.pubsub.provider.RetractEventProvider;
+import org.jivesoftware.smackx.pubsub.provider.SimpleNodeProvider;
+import org.jivesoftware.smackx.pubsub.provider.SubscriptionProvider;
+import org.jivesoftware.smackx.pubsub.provider.SubscriptionsProvider;
+import org.jivesoftware.smackx.receipts.DeliveryReceipt;
+import org.jivesoftware.smackx.search.UserSearch;
+
+/**
+ * Since dalvik on Android does not allow the loading of META-INF files from the
+ * filesystem, you have to register every provider manually.
+ *
+ * The full list of providers is at:
+ * http://fisheye.igniterealtime.org/browse/smack/trunk/build/resources/META-INF/smack.providers?hb=true
+ *
+ * @author Florian Schmaus fschmaus@gmail.com
+ *
+ */
+public class ConfigureProviderManager {
+
+    public static void configureProviderManager() {
+        ProviderManager pm = ProviderManager.getInstance();
+
+        // The order is the same as in the smack.providers file
+
+        //  Private Data Storage
+        pm.addIQProvider("query","jabber:iq:private", new PrivateDataManager.PrivateDataIQProvider());
+        //  Time
+        try {
+            pm.addIQProvider("query","jabber:iq:time", Class.forName("org.jivesoftware.smackx.packet.Time"));
+        } catch (ClassNotFoundException e) {
+            System.err.println("Can't load class for org.jivesoftware.smackx.packet.Time");
+        }
+
+        //  Roster Exchange
+        pm.addExtensionProvider("x","jabber:x:roster", new RosterExchangeProvider());
+        //  Message Events
+        pm.addExtensionProvider("x","jabber:x:event", new MessageEventProvider());
+        //  Chat State
+        pm.addExtensionProvider("active","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
+        pm.addExtensionProvider("composing","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
+        pm.addExtensionProvider("paused","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
+        pm.addExtensionProvider("inactive","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
+        pm.addExtensionProvider("gone","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
+
+        //  XHTML
+        pm.addExtensionProvider("html","http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider());
+
+        //  Group Chat Invitations
+        pm.addExtensionProvider("x","jabber:x:conference", new GroupChatInvitation.Provider());
+        //  Service Discovery # Items
+        pm.addIQProvider("query","http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
+        //  Service Discovery # Info
+        pm.addIQProvider("query","http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
+        //  Data Forms
+        pm.addExtensionProvider("x","jabber:x:data", new DataFormProvider());
+        //  MUC User
+        pm.addExtensionProvider("x","http://jabber.org/protocol/muc#user", new MUCUserProvider());
+        //  MUC Admin
+        pm.addIQProvider("query","http://jabber.org/protocol/muc#admin", new MUCAdminProvider());
+        //  MUC Owner
+        pm.addIQProvider("query","http://jabber.org/protocol/muc#owner", new MUCOwnerProvider());
+        //  Delayed Delivery
+        pm.addExtensionProvider("x","jabber:x:delay", new DelayInformationProvider());
+        pm.addExtensionProvider("delay", "urn:xmpp:delay", new DelayInformationProvider());
+        //  Version
+        try {
+            pm.addIQProvider("query","jabber:iq:version", Class.forName("org.jivesoftware.smackx.packet.Version"));
+        } catch (ClassNotFoundException e) {
+            System.err.println("Can't load class for org.jivesoftware.smackx.packet.Version");
+        }
+        //  VCard
+        pm.addIQProvider("vCard","vcard-temp", new VCardProvider());
+        //  Offline Message Requests
+        pm.addIQProvider("offline","http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider());
+        //  Offline Message Indicator
+        pm.addExtensionProvider("offline","http://jabber.org/protocol/offline", new OfflineMessageInfo.Provider());
+        //  Last Activity
+        pm.addIQProvider("query","jabber:iq:last", new LastActivity.Provider());
+        //  User Search
+        pm.addIQProvider("query","jabber:iq:search", new UserSearch.Provider());
+        //  SharedGroupsInfo
+        pm.addIQProvider("sharedgroup","http://www.jivesoftware.org/protocol/sharedgroup", new SharedGroupsInfo.Provider());
+
+        //  JEP-33: Extended Stanza Addressing
+        pm.addExtensionProvider("addresses","http://jabber.org/protocol/address", new MultipleAddressesProvider());
+
+        //   FileTransfer
+        pm.addIQProvider("si","http://jabber.org/protocol/si", new StreamInitiationProvider());
+        pm.addIQProvider("query","http://jabber.org/protocol/bytestreams", new BytestreamsProvider());
+        pm.addIQProvider("open","http://jabber.org/protocol/ibb", new OpenIQProvider());
+        pm.addIQProvider("data","http://jabber.org/protocol/ibb", new DataPacketProvider());
+        pm.addIQProvider("close","http://jabber.org/protocol/ibb", new CloseIQProvider());
+        pm.addExtensionProvider("data","http://jabber.org/protocol/ibb", new DataPacketProvider());
+
+        //  Privacy
+        pm.addIQProvider("query","jabber:iq:privacy", new PrivacyProvider());
+
+        // SHIM
+        pm.addExtensionProvider("headers", "http://jabber.org/protocol/shim", new HeadersProvider());
+        pm.addExtensionProvider("header", "http://jabber.org/protocol/shim", new HeaderProvider());
+
+        // PubSub
+        pm.addIQProvider("pubsub", "http://jabber.org/protocol/pubsub", new PubSubProvider());
+        pm.addExtensionProvider("create", "http://jabber.org/protocol/pubsub", new SimpleNodeProvider());
+        pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub", new ItemsProvider());
+        pm.addExtensionProvider("item", "http://jabber.org/protocol/pubsub", new ItemProvider());
+        pm.addExtensionProvider("subscriptions", "http://jabber.org/protocol/pubsub", new SubscriptionsProvider());
+        pm.addExtensionProvider("subscription", "http://jabber.org/protocol/pubsub", new SubscriptionProvider());
+        pm.addExtensionProvider("affiliations", "http://jabber.org/protocol/pubsub", new AffiliationsProvider());
+        pm.addExtensionProvider("affiliation", "http://jabber.org/protocol/pubsub", new AffiliationProvider());
+        pm.addExtensionProvider("options", "http://jabber.org/protocol/pubsub", new FormNodeProvider());
+        // PubSub owner
+        pm.addIQProvider("pubsub", "http://jabber.org/protocol/pubsub#owner", new PubSubProvider());
+        pm.addExtensionProvider("configure", "http://jabber.org/protocol/pubsub#owner", new FormNodeProvider());
+        pm.addExtensionProvider("default", "http://jabber.org/protocol/pubsub#owner", new FormNodeProvider());
+        // PubSub event
+        pm.addExtensionProvider("event", "http://jabber.org/protocol/pubsub#event", new EventProvider());
+        pm.addExtensionProvider("configuration", "http://jabber.org/protocol/pubsub#event", new ConfigEventProvider());
+        pm.addExtensionProvider("delete", "http://jabber.org/protocol/pubsub#event", new SimpleNodeProvider());
+        pm.addExtensionProvider("options", "http://jabber.org/protocol/pubsub#event", new FormNodeProvider());
+        pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub#event", new ItemsProvider());
+        pm.addExtensionProvider("item", "http://jabber.org/protocol/pubsub#event", new ItemProvider());
+        pm.addExtensionProvider("retract", "http://jabber.org/protocol/pubsub#event", new RetractEventProvider());
+        pm.addExtensionProvider("purge", "http://jabber.org/protocol/pubsub#event", new SimpleNodeProvider());
+
+        // Nick Exchange
+        pm.addExtensionProvider("nick", "http://jabber.org/protocol/nick", new Nick.Provider());
+
+        // Attention
+        pm.addExtensionProvider("attention", "urn:xmpp:attention:0", new AttentionExtension.Provider());
+
+	// XEP-0297 Stanza Forwarding
+	pm.addExtensionProvider("forwarded", "urn:xmpp:forward:0", new Forwarded.Provider());
+
+	// XEP-0280 Message Carbons
+	pm.addExtensionProvider("sent", "urn:xmpp:carbons:2", new Carbon.Provider());
+	pm.addExtensionProvider("received", "urn:xmpp:carbons:2", new Carbon.Provider());
+
+	// XEP-0199 XMPP Ping
+	pm.addIQProvider("ping", "urn:xmpp:ping", new PingProvider());
+
+	// XEP-184 Message Delivery Receipts
+	pm.addExtensionProvider("received", "urn:xmpp:receipts", new DeliveryReceipt.Provider());
+	pm.addExtensionProvider("request", "urn:xmpp:receipts", new DeliveryReceipt.Provider());
+
+	// XEP-0115 Entity Capabilities
+	pm.addExtensionProvider("c", "http://jabber.org/protocol/caps", new CapsExtensionProvider());
+    }
+}
diff --git a/asmack-master/static-src/custom/org/jivesoftware/smackx/InitStaticCode.java b/asmack-master/static-src/custom/org/jivesoftware/smackx/InitStaticCode.java
new file mode 100644
index 0000000..12de5af
--- /dev/null
+++ b/asmack-master/static-src/custom/org/jivesoftware/smackx/InitStaticCode.java
@@ -0,0 +1,51 @@
+/**
+ * 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 android.content.Context;
+
+/**
+ * Since dalvik on Android does not allow the loading of META-INF files from the
+ * filesystem, the static blocks of some classes have to be inited manually.
+ *
+ * The full list can be found here:
+ * http://fisheye.igniterealtime.org/browse/smack/trunk/build/resources/META-INF/smack-config.xml?hb=true
+ *
+ * @author Florian Schmaus fschmaus@gmail.com
+ *
+ */
+public class InitStaticCode {
+
+    public static void initStaticCode(Context ctx) {
+	    // This has the be the application class loader,
+	    // *not* the system class loader
+	    ClassLoader appClassLoader = ctx.getClassLoader();
+
+	    try {
+		    Class.forName(org.jivesoftware.smackx.ServiceDiscoveryManager.class.getName(), true, appClassLoader);
+		    Class.forName(org.jivesoftware.smack.PrivacyListManager.class.getName(), true, appClassLoader);
+		    Class.forName(org.jivesoftware.smackx.XHTMLManager.class.getName(), true, appClassLoader);
+		    Class.forName(org.jivesoftware.smackx.muc.MultiUserChat.class.getName(), true, appClassLoader);
+		    Class.forName(org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager.class.getName(), true, appClassLoader);
+		    Class.forName(org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamManager.class.getName(), true, appClassLoader);
+		    Class.forName(org.jivesoftware.smackx.filetransfer.FileTransferManager.class.getName(), true, appClassLoader);
+		    Class.forName(org.jivesoftware.smackx.LastActivityManager.class.getName(), true, appClassLoader);
+		    Class.forName(org.jivesoftware.smack.ReconnectionManager.class.getName(), true, appClassLoader);
+		    Class.forName(org.jivesoftware.smackx.commands.AdHocCommandManager.class.getName(), true, appClassLoader);
+	    } catch (ClassNotFoundException e) {
+		    throw new IllegalStateException("Could not init static class blocks", e);
+	    }
+    }
+}
diff --git a/asmack-master/static-src/custom/org/jivesoftware/smackx/pubsub/provider/ItemProvider.java b/asmack-master/static-src/custom/org/jivesoftware/smackx/pubsub/provider/ItemProvider.java
new file mode 100644
index 0000000..a6b8694
--- /dev/null
+++ b/asmack-master/static-src/custom/org/jivesoftware/smackx/pubsub/provider/ItemProvider.java
@@ -0,0 +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.pubsub.provider;

+

+import org.jivesoftware.smack.packet.PacketExtension;

+import org.jivesoftware.smack.provider.PacketExtensionProvider;

+import org.jivesoftware.smack.provider.ProviderManager;

+import org.jivesoftware.smack.util.PacketParserUtils;

+import org.jivesoftware.smackx.pubsub.Item;

+import org.jivesoftware.smackx.pubsub.PayloadItem;

+import org.jivesoftware.smackx.pubsub.SimplePayload;

+import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;

+import org.xmlpull.v1.XmlPullParser;

+

+/**

+ * Parses an <b>item</b> element as is defined in both the {@link PubSubNamespace#BASIC} and {@link PubSubNamespace#EVENT}

+ * namespaces.  To parse the item contents, it will use whatever {@link PacketExtensionProvider} is registered in

+ * <b>smack.providers</b> for its element name and namespace.  If no provider is registered, it will return a {@link SimplePayload}.

+ *

+ * @author Robin Collier

+ */

+public class ItemProvider implements PacketExtensionProvider {

+    public PacketExtension parseExtension(XmlPullParser parser) throws Exception {

+        String id = parser.getAttributeValue(null, "id");

+        String node = parser.getAttributeValue(null, "node");

+        String elem = parser.getName();

+

+        int tag = parser.next();

+

+        if (tag == XmlPullParser.END_TAG) {

+            return new Item(id, node);

+        } else {

+            String payloadElemName = parser.getName();

+            String payloadNS = parser.getNamespace();

+

+            if (ProviderManager.getInstance().getExtensionProvider(payloadElemName, payloadNS) == null) {

+                StringBuilder payloadText = new StringBuilder();

+                boolean done = false;

+                boolean isEmptyElement = false;

+

+                // Parse custom payload

+                while (!done) {

+                    if (tag == XmlPullParser.END_TAG && parser.getName().equals(elem)) {

+                        done = true;

+                    } else if (parser.getEventType() == XmlPullParser.START_TAG) {

+                        payloadText.append("<").append(parser.getName());

+                        if (parser.getName().equals(payloadElemName) && (!"".equals(payloadNS))) {

+                            payloadText.append(" xmlns=\"").append(payloadNS).append("\"");

+                        }

+                        int n = parser.getAttributeCount();

+                        for (int i = 0; i < n; i++) {

+                            payloadText.append(" ").append(parser.getAttributeName(i)).append("=\"")

+                                    .append(parser.getAttributeValue(i)).append("\"");

+                        }

+                        if (parser.isEmptyElementTag()) {

+                            payloadText.append("/>");

+                            isEmptyElement = true;

+                        } else {

+                            payloadText.append(">");

+                        }

+                    } else if (parser.getEventType() == XmlPullParser.END_TAG) {

+                        if (isEmptyElement) {

+                            isEmptyElement = false;

+                        } else {

+                            payloadText.append("</").append(parser.getName()).append(">");

+                        }

+                    } else if (parser.getEventType() == XmlPullParser.TEXT) {

+                        payloadText.append(parser.getText());

+                    }

+

+                    tag = parser.next();

+                }

+                return new PayloadItem<SimplePayload>(id, node, new SimplePayload(payloadElemName, payloadNS,

+                        payloadText.toString()));

+            } else {

+                return new PayloadItem<PacketExtension>(id, node, PacketParserUtils.parsePacketExtension(

+                        payloadElemName, payloadNS, parser));

+            }

+        }

+    }

+}

diff --git a/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/DigestChallenge.java b/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/DigestChallenge.java
new file mode 100644
index 0000000..90e6247
--- /dev/null
+++ b/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/DigestChallenge.java
@@ -0,0 +1,393 @@
+/* **************************************************************************
+ * $OpenLDAP: /com/novell/sasl/client/DigestChallenge.java,v 1.3 2005/01/17 15:00:54 sunilk Exp $
+ *
+ * Copyright (C) 2003 Novell, Inc. All Rights Reserved.
+ *
+ * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
+ * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
+ * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
+ * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
+ * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
+ * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
+ * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
+ * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
+ ******************************************************************************/
+package com.novell.sasl.client;
+
+import java.util.*;
+import org.apache.harmony.javax.security.sasl.*;
+
+/**
+ * Implements the DigestChallenge class which will be used by the
+ * DigestMD5SaslClient class
+ */
+class DigestChallenge extends Object
+{
+    public static final int QOP_AUTH           =    0x01;
+    public static final int QOP_AUTH_INT       =    0x02;
+    public static final int QOP_AUTH_CONF       =    0x04;
+    public static final int QOP_UNRECOGNIZED   =    0x08;
+
+    private static final int CIPHER_3DES          = 0x01;
+    private static final int CIPHER_DES           = 0x02;
+    private static final int CIPHER_RC4_40        = 0x04;
+    private static final int CIPHER_RC4           = 0x08;
+    private static final int CIPHER_RC4_56        = 0x10;
+    private static final int CIPHER_UNRECOGNIZED  = 0x20;
+    private static final int CIPHER_RECOGNIZED_MASK =
+     CIPHER_3DES | CIPHER_DES | CIPHER_RC4_40 | CIPHER_RC4 | CIPHER_RC4_56;
+
+    private ArrayList m_realms;
+    private String    m_nonce;
+    private int       m_qop;
+    private boolean   m_staleFlag;
+    private int       m_maxBuf;
+    private String    m_characterSet;
+    private String    m_algorithm;
+    private int       m_cipherOptions;
+
+    DigestChallenge(
+        byte[] challenge)
+            throws SaslException
+    {
+        m_realms = new ArrayList(5);
+        m_nonce = null;
+        m_qop = 0;
+        m_staleFlag = false;
+        m_maxBuf = -1;
+        m_characterSet = null;
+        m_algorithm = null;
+        m_cipherOptions = 0;
+
+        DirectiveList dirList = new DirectiveList(challenge);
+        try
+        {
+            dirList.parseDirectives();
+            checkSemantics(dirList);
+        }
+        catch (SaslException e)
+        {
+        }
+    }
+
+    /**
+     * Checks the semantics of the directives in the directive list as parsed
+     * from the digest challenge byte array.
+     *
+     * @param dirList  the list of directives parsed from the digest challenge
+     *
+     * @exception SaslException   If a semantic error occurs
+     */
+    void checkSemantics(
+        DirectiveList dirList) throws SaslException
+    {
+    Iterator        directives = dirList.getIterator();
+    ParsedDirective directive;
+    String          name;
+
+    while (directives.hasNext())
+    {
+        directive = (ParsedDirective)directives.next();
+        name = directive.getName();
+        if (name.equals("realm"))
+            handleRealm(directive);
+        else if (name.equals("nonce"))
+            handleNonce(directive);
+        else if (name.equals("qop"))
+            handleQop(directive);
+        else if (name.equals("maxbuf"))
+            handleMaxbuf(directive);
+        else if (name.equals("charset"))
+            handleCharset(directive);
+        else if (name.equals("algorithm"))
+            handleAlgorithm(directive);
+        else if (name.equals("cipher"))
+            handleCipher(directive);
+        else if (name.equals("stale"))
+            handleStale(directive);
+    }
+
+    /* post semantic check */
+    if (-1 == m_maxBuf)
+        m_maxBuf = 65536;
+
+    if (m_qop == 0)
+        m_qop = QOP_AUTH;
+    else if ( (m_qop & QOP_AUTH) != QOP_AUTH )
+        throw new SaslException("Only qop-auth is supported by client");
+    else if ( ((m_qop & QOP_AUTH_CONF) == QOP_AUTH_CONF) &&
+              (0 == (m_cipherOptions & CIPHER_RECOGNIZED_MASK)) )
+        throw new SaslException("Invalid cipher options");
+    else if (null == m_nonce)
+        throw new SaslException("Missing nonce directive");
+    else if (m_staleFlag)
+        throw new SaslException("Unexpected stale flag");
+    else if ( null == m_algorithm )
+        throw new SaslException("Missing algorithm directive");
+    }
+
+    /**
+     * This function implements the semenatics of the nonce directive.
+     *
+     * @param      pd   ParsedDirective
+     *
+     * @exception  SaslException   If an error occurs due to too many nonce
+     *                             values
+     */
+    void handleNonce(
+        ParsedDirective  pd) throws SaslException
+    {
+        if (null != m_nonce)
+            throw new SaslException("Too many nonce values.");
+
+        m_nonce = pd.getValue();
+    }
+
+    /**
+     * This function implements the semenatics of the realm directive.
+     *
+     * @param      pd   ParsedDirective
+     */
+    void handleRealm(
+        ParsedDirective  pd)
+    {
+        m_realms.add(pd.getValue());
+    }
+
+    /**
+     * This function implements the semenatics of the qop (quality of protection)
+     * directive. The value of the qop directive is as defined below:
+     *      qop-options =     "qop" "=" <"> qop-list <">
+     *      qop-list    =     1#qop-value
+     *      qop-value    =     "auth" | "auth-int"  | "auth-conf" | token
+     *
+     * @param      pd   ParsedDirective
+     *
+     * @exception  SaslException   If an error occurs due to too many qop
+     *                             directives
+     */
+    void handleQop(
+        ParsedDirective  pd) throws SaslException
+    {
+        String       token;
+        TokenParser  parser;
+
+        if (m_qop != 0)
+            throw new SaslException("Too many qop directives.");
+
+        parser = new TokenParser(pd.getValue());
+        for (token = parser.parseToken();
+             token != null;
+             token = parser.parseToken())
+        {
+            if (token.equals("auth"))
+                  m_qop |= QOP_AUTH;
+              else if (token.equals("auth-int"))
+                  m_qop |= QOP_AUTH_INT;
+            else if (token.equals("auth-conf"))
+                m_qop |= QOP_AUTH_CONF;
+            else
+                m_qop |= QOP_UNRECOGNIZED;
+        }
+    }
+
+    /**
+     * This function implements the semenatics of the Maxbuf directive.
+     * the value is defined as: 1*DIGIT
+     *
+     * @param      pd   ParsedDirective
+     *
+     * @exception  SaslException If an error occur    
+     */
+    void handleMaxbuf(
+        ParsedDirective  pd) throws SaslException
+    {
+        if (-1 != m_maxBuf) /*it's initialized to -1 */
+            throw new SaslException("Too many maxBuf directives.");
+
+        m_maxBuf = Integer.parseInt(pd.getValue());
+
+        if (0 == m_maxBuf)
+            throw new SaslException("Max buf value must be greater than zero.");
+    }
+
+    /**
+     * This function implements the semenatics of the charset directive.
+     * the value is defined as: 1*DIGIT
+     *
+     * @param      pd   ParsedDirective
+     *
+     * @exception  SaslException If an error occurs dur to too many charset
+     *                           directives or Invalid character encoding
+     *                           directive
+     */
+    void handleCharset(
+        ParsedDirective  pd) throws SaslException
+    {
+        if (null != m_characterSet)
+            throw new SaslException("Too many charset directives.");
+
+        m_characterSet = pd.getValue();
+
+        if (!m_characterSet.equals("utf-8"))
+            throw new SaslException("Invalid character encoding directive");
+    }
+
+    /**
+     * This function implements the semenatics of the charset directive.
+     * the value is defined as: 1*DIGIT
+     *
+     * @param      pd   ParsedDirective
+     *
+     * @exception  SaslException If an error occurs due to too many algorith
+     *                           directive or Invalid algorithm directive
+     *                           value
+     */
+    void handleAlgorithm(
+        ParsedDirective  pd) throws SaslException
+    {
+        if (null != m_algorithm)
+            throw new SaslException("Too many algorithm directives.");
+
+          m_algorithm = pd.getValue();
+
+        if (!"md5-sess".equals(m_algorithm))
+            throw new SaslException("Invalid algorithm directive value: " +
+                                    m_algorithm);
+    }
+
+    /**
+     * This function implements the semenatics of the cipher-opts directive
+     * directive. The value of the qop directive is as defined below:
+     *      qop-options =     "qop" "=" <"> qop-list <">
+     *      qop-list    =     1#qop-value
+     *      qop-value    =     "auth" | "auth-int"  | "auth-conf" | token
+     *
+     * @param      pd   ParsedDirective
+     *
+     * @exception  SaslException If an error occurs due to Too many cipher
+     *                           directives 
+     */
+    void handleCipher(
+        ParsedDirective  pd) throws SaslException
+    {
+        String  token;
+        TokenParser parser;
+
+        if (0 != m_cipherOptions)
+            throw new SaslException("Too many cipher directives.");
+
+        parser = new TokenParser(pd.getValue());
+        token = parser.parseToken();
+        for (token = parser.parseToken();
+             token != null;
+             token = parser.parseToken())
+        {
+              if ("3des".equals(token))
+                  m_cipherOptions |= CIPHER_3DES;
+              else if ("des".equals(token))
+                  m_cipherOptions |= CIPHER_DES;
+            else if ("rc4-40".equals(token))
+                m_cipherOptions |= CIPHER_RC4_40;
+            else if ("rc4".equals(token))
+                m_cipherOptions |= CIPHER_RC4;
+            else if ("rc4-56".equals(token))
+                m_cipherOptions |= CIPHER_RC4_56;
+            else
+                m_cipherOptions |= CIPHER_UNRECOGNIZED;
+        }
+
+        if (m_cipherOptions == 0)
+            m_cipherOptions = CIPHER_UNRECOGNIZED;
+    }
+
+    /**
+     * This function implements the semenatics of the stale directive.
+     *
+     * @param      pd   ParsedDirective
+     *
+     * @exception  SaslException If an error occurs due to Too many stale
+     *                           directives or Invalid stale directive value
+     */
+    void handleStale(
+        ParsedDirective  pd) throws SaslException
+    {
+        if (false != m_staleFlag)
+            throw new SaslException("Too many stale directives.");
+
+        if ("true".equals(pd.getValue()))
+            m_staleFlag = true;
+        else
+            throw new SaslException("Invalid stale directive value: " +
+                                    pd.getValue());
+    }
+
+    /**
+     * Return the list of the All the Realms
+     *
+     * @return  List of all the realms 
+     */
+    public ArrayList getRealms()
+    {
+        return m_realms;
+    }
+
+    /**
+     * @return Returns the Nonce
+     */
+    public String getNonce()
+    {
+        return m_nonce;
+    }
+
+    /**
+     * Return the quality-of-protection
+     * 
+     * @return The quality-of-protection
+     */
+    public int getQop()
+    {
+        return m_qop;
+    }
+
+    /**
+     * @return The state of the Staleflag
+     */
+    public boolean getStaleFlag()
+    {
+        return m_staleFlag;
+    }
+
+    /**
+     * @return The Maximum Buffer value
+     */
+    public int getMaxBuf()
+    {
+        return m_maxBuf;
+    }
+
+    /**
+     * @return character set values as string
+     */
+    public String getCharacterSet()
+    {
+        return m_characterSet;
+    }
+
+    /**
+     * @return The String value of the algorithm
+     */
+    public String getAlgorithm()
+    {
+        return m_algorithm;
+    }
+
+    /**
+     * @return The cipher options
+     */
+    public int getCipherOptions()
+    {
+        return m_cipherOptions;
+    }
+}
+
diff --git a/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/DigestMD5SaslClient.java b/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/DigestMD5SaslClient.java
new file mode 100644
index 0000000..eb488fe
--- /dev/null
+++ b/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/DigestMD5SaslClient.java
@@ -0,0 +1,820 @@
+/* **************************************************************************
+ * $OpenLDAP: /com/novell/sasl/client/DigestMD5SaslClient.java,v 1.4 2005/01/17 15:00:54 sunilk Exp $
+ *
+ * Copyright (C) 2003 Novell, Inc. All Rights Reserved.
+ *
+ * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
+ * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
+ * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
+ * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
+ * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
+ * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
+ * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
+ * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
+ ******************************************************************************/
+package com.novell.sasl.client;
+
+import org.apache.harmony.javax.security.sasl.*;
+import org.apache.harmony.javax.security.auth.callback.*;
+import java.security.SecureRandom;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.io.UnsupportedEncodingException;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Implements the Client portion of DigestMD5 Sasl mechanism.
+ */
+public class DigestMD5SaslClient implements SaslClient
+{
+    private String           m_authorizationId = "";
+    private String           m_protocol = "";
+    private String           m_serverName = "";
+    private Map              m_props;
+    private CallbackHandler  m_cbh;
+    private int              m_state;
+    private String           m_qopValue = "";
+    private char[]              m_HA1 = null;
+    private String           m_digestURI;
+    private DigestChallenge  m_dc;
+    private String           m_clientNonce = "";
+    private String           m_realm = "";
+    private String           m_name = "";
+
+    private static final int   STATE_INITIAL = 0;
+    private static final int   STATE_DIGEST_RESPONSE_SENT = 1;
+    private static final int   STATE_VALID_SERVER_RESPONSE = 2;
+    private static final int   STATE_INVALID_SERVER_RESPONSE = 3;
+    private static final int   STATE_DISPOSED = 4;
+
+    private static final int   NONCE_BYTE_COUNT = 32;
+    private static final int   NONCE_HEX_COUNT = 2*NONCE_BYTE_COUNT;
+
+    private static final String DIGEST_METHOD = "AUTHENTICATE";
+
+    /**
+     * Creates an DigestMD5SaslClient object using the parameters supplied.
+     * Assumes that the QOP, STRENGTH, and SERVER_AUTH properties are
+     * contained in props
+     *
+     * @param authorizationId  The possibly null protocol-dependent
+     *                     identification to be used for authorization. If
+     *                     null or empty, the server derives an authorization
+     *                     ID from the client's authentication credentials.
+     *                     When the SASL authentication completes
+     *                     successfully, the specified entity is granted
+     *                     access.
+     *
+     * @param protocol     The non-null string name of the protocol for which
+     *                     the authentication is being performed (e.g. "ldap")
+     *
+     * @param serverName   The non-null fully qualified host name of the server
+     *                     to authenticate to
+     *
+     * @param props        The possibly null set of properties used to select
+     *                     the SASL mechanism and to configure the
+     *                     authentication exchange of the selected mechanism.
+     *                     See the Sasl class for a list of standard properties.
+     *                     Other, possibly mechanism-specific, properties can
+     *                     be included. Properties not relevant to the selected
+     *                     mechanism are ignored.
+     *
+     * @param cbh          The possibly null callback handler to used by the
+     *                     SASL mechanisms to get further information from the
+     *                     application/library to complete the authentication.
+     *                     For example, a SASL mechanism might require the
+     *                     authentication ID, password and realm from the
+     *                     caller. The authentication ID is requested by using
+     *                     a NameCallback. The password is requested by using
+     *                     a PasswordCallback. The realm is requested by using
+     *                     a RealmChoiceCallback if there is a list of realms
+     *                     to choose from, and by using a RealmCallback if the
+     *                     realm must be entered.
+     *
+     * @return            A possibly null SaslClient created using the
+     *                     parameters supplied. If null, this factory cannot
+     *                     produce a SaslClient using the parameters supplied.
+     *
+     * @exception SaslException  If a SaslClient instance cannot be created
+     *                     because of an error
+     */
+    public static SaslClient getClient(
+        String          authorizationId,
+        String          protocol,
+        String          serverName,
+        Map             props,
+        CallbackHandler cbh)
+    {
+        String desiredQOP = (String)props.get(Sasl.QOP);
+        String desiredStrength = (String)props.get(Sasl.STRENGTH);
+        String serverAuth = (String)props.get(Sasl.SERVER_AUTH);
+
+        //only support qop equal to auth
+        if ((desiredQOP != null) && !"auth".equals(desiredQOP))
+            return null;
+
+        //doesn't support server authentication
+        if ((serverAuth != null) && !"false".equals(serverAuth))
+            return null;
+
+        //need a callback handler to get the password
+        if (cbh == null)
+            return null;
+
+        return new DigestMD5SaslClient(authorizationId, protocol,
+                                       serverName, props, cbh);
+    }
+
+    /**
+     * Creates an DigestMD5SaslClient object using the parameters supplied.
+     * Assumes that the QOP, STRENGTH, and SERVER_AUTH properties are
+     * contained in props
+     *
+     * @param authorizationId  The possibly null protocol-dependent
+     *                     identification to be used for authorization. If
+     *                     null or empty, the server derives an authorization
+     *                     ID from the client's authentication credentials.
+     *                     When the SASL authentication completes
+     *                     successfully, the specified entity is granted
+     *                     access.
+     *
+     * @param protocol     The non-null string name of the protocol for which
+     *                     the authentication is being performed (e.g. "ldap")
+     *
+     * @param serverName   The non-null fully qualified host name of the server
+     *                     to authenticate to
+     *
+     * @param props        The possibly null set of properties used to select
+     *                     the SASL mechanism and to configure the
+     *                     authentication exchange of the selected mechanism.
+     *                     See the Sasl class for a list of standard properties.
+     *                     Other, possibly mechanism-specific, properties can
+     *                     be included. Properties not relevant to the selected
+     *                     mechanism are ignored.
+     *
+     * @param cbh          The possibly null callback handler to used by the
+     *                     SASL mechanisms to get further information from the
+     *                     application/library to complete the authentication.
+     *                     For example, a SASL mechanism might require the
+     *                     authentication ID, password and realm from the
+     *                     caller. The authentication ID is requested by using
+     *                     a NameCallback. The password is requested by using
+     *                     a PasswordCallback. The realm is requested by using
+     *                     a RealmChoiceCallback if there is a list of realms
+     *                     to choose from, and by using a RealmCallback if the
+     *                     realm must be entered.
+     *
+     */
+    private  DigestMD5SaslClient(
+        String          authorizationId,
+        String          protocol,
+        String          serverName,
+        Map             props,
+        CallbackHandler cbh)
+    {
+        m_authorizationId = authorizationId;
+        m_protocol = protocol;
+        m_serverName = serverName;
+        m_props = props;
+        m_cbh = cbh;
+
+        m_state = STATE_INITIAL;
+    }
+
+    /**
+     * Determines if this mechanism has an optional initial response. If true,
+     * caller should call evaluateChallenge() with an empty array to get the
+     * initial response.
+     *
+     * @return  true if this mechanism has an initial response
+     */
+    public boolean hasInitialResponse()
+    {
+        return false;
+    }
+
+    /**
+     * Determines if the authentication exchange has completed. This method
+     * may be called at any time, but typically, it will not be called until
+     * the caller has received indication from the server (in a protocol-
+     * specific manner) that the exchange has completed.
+     *
+     * @return  true if the authentication exchange has completed;
+     *           false otherwise.
+     */
+    public boolean isComplete()
+    {
+        if ((m_state == STATE_VALID_SERVER_RESPONSE) ||
+            (m_state == STATE_INVALID_SERVER_RESPONSE) ||
+            (m_state == STATE_DISPOSED))
+            return true;
+        else
+            return false;
+    }
+
+    /**
+     * Unwraps a byte array received from the server. This method can be called
+     * only after the authentication exchange has completed (i.e., when
+     * isComplete() returns true) and only if the authentication exchange has
+     * negotiated integrity and/or privacy as the quality of protection;
+     * otherwise, an IllegalStateException is thrown.
+     *
+     * incoming is the contents of the SASL buffer as defined in RFC 2222
+     * without the leading four octet field that represents the length.
+     * offset and len specify the portion of incoming to use.
+     *
+     * @param incoming   A non-null byte array containing the encoded bytes
+     *                   from the server
+     * @param offset     The starting position at incoming of the bytes to use
+     *
+     * @param len        The number of bytes from incoming to use
+     *
+     * @return           A non-null byte array containing the decoded bytes
+     *
+     */
+    public byte[] unwrap(
+        byte[] incoming,
+        int    offset,
+        int    len)
+            throws SaslException
+    {
+        throw new IllegalStateException(
+         "unwrap: QOP has neither integrity nor privacy>");
+    }
+
+    /**
+     * Wraps a byte array to be sent to the server. This method can be called
+     * only after the authentication exchange has completed (i.e., when
+     * isComplete() returns true) and only if the authentication exchange has
+     * negotiated integrity and/or privacy as the quality of protection;
+     * otherwise, an IllegalStateException is thrown.
+     *
+     * The result of this method will make up the contents of the SASL buffer as
+     * defined in RFC 2222 without the leading four octet field that represents
+     * the length. offset and len specify the portion of outgoing to use.
+     *
+     * @param outgoing   A non-null byte array containing the bytes to encode
+     * @param offset     The starting position at outgoing of the bytes to use
+     * @param len        The number of bytes from outgoing to use
+     *
+     * @return A non-null byte array containing the encoded bytes
+     *
+     * @exception SaslException  if incoming cannot be successfully unwrapped.
+     *
+     * @exception IllegalStateException   if the authentication exchange has
+     *                   not completed, or if the negotiated quality of
+     *                   protection has neither integrity nor privacy.
+     */
+    public byte[] wrap(
+        byte[]  outgoing,
+        int     offset,
+        int     len)
+            throws SaslException
+    {
+        throw new IllegalStateException(
+         "wrap: QOP has neither integrity nor privacy>");
+    }
+
+    /**
+     * Retrieves the negotiated property. This method can be called only after
+     * the authentication exchange has completed (i.e., when isComplete()
+     * returns true); otherwise, an IllegalStateException is thrown.
+     *
+     * @param propName   The non-null property name
+     *
+     * @return  The value of the negotiated property. If null, the property was
+     *          not negotiated or is not applicable to this mechanism.
+     *
+     * @exception IllegalStateException   if this authentication exchange has
+     *                                    not completed
+     */
+    public Object getNegotiatedProperty(
+        String propName)
+    {
+        if (m_state != STATE_VALID_SERVER_RESPONSE)
+            throw new IllegalStateException(
+             "getNegotiatedProperty: authentication exchange not complete.");
+
+        if (Sasl.QOP.equals(propName))
+            return "auth";
+        else
+            return null;
+    }
+
+    /**
+     * Disposes of any system resources or security-sensitive information the
+     * SaslClient might be using. Invoking this method invalidates the
+     * SaslClient instance. This method is idempotent.
+     *
+     * @exception SaslException  if a problem was encountered while disposing
+     *                           of the resources
+     */
+    public void dispose()
+            throws SaslException
+    {
+        if (m_state != STATE_DISPOSED)
+        {
+            m_state = STATE_DISPOSED;
+        }
+    }
+
+    /**
+     * Evaluates the challenge data and generates a response. If a challenge
+     * is received from the server during the authentication process, this
+     * method is called to prepare an appropriate next response to submit to
+     * the server.
+     *
+     * @param challenge  The non-null challenge sent from the server. The
+     *                   challenge array may have zero length.
+     *
+     * @return    The possibly null reponse to send to the server. It is null
+     *            if the challenge accompanied a "SUCCESS" status and the
+     *            challenge only contains data for the client to update its
+     *            state and no response needs to be sent to the server.
+     *            The response is a zero-length byte array if the client is to
+     *            send a response with no data.
+     *
+     * @exception SaslException   If an error occurred while processing the
+     *                            challenge or generating a response.
+     */
+    public byte[] evaluateChallenge(
+        byte[] challenge)
+            throws SaslException
+    {
+        byte[] response = null;
+
+        //printState();
+        switch (m_state)
+        {
+        case STATE_INITIAL:
+            if (challenge.length == 0)
+                throw new SaslException("response = byte[0]");
+            else
+                try
+                {
+                    response = createDigestResponse(challenge).
+                                                           getBytes("UTF-8");
+                    m_state = STATE_DIGEST_RESPONSE_SENT;
+                }
+                catch (java.io.UnsupportedEncodingException e)
+                {
+                    throw new SaslException(
+                     "UTF-8 encoding not suppported by platform", e);
+                }
+            break;
+        case STATE_DIGEST_RESPONSE_SENT:
+            if (checkServerResponseAuth(challenge))
+                m_state = STATE_VALID_SERVER_RESPONSE;
+            else
+            {
+                m_state = STATE_INVALID_SERVER_RESPONSE;
+                throw new SaslException("Could not validate response-auth " +
+                                        "value from server");
+            }
+            break;
+        case STATE_VALID_SERVER_RESPONSE:
+        case STATE_INVALID_SERVER_RESPONSE:
+            throw new SaslException("Authentication sequence is complete");
+        case STATE_DISPOSED:
+            throw new SaslException("Client has been disposed");
+        default:
+            throw new SaslException("Unknown client state.");
+        }
+
+        return response;
+    }
+
+    /**
+     * This function takes a 16 byte binary md5-hash value and creates a 32
+     * character (plus    a terminating null character) hex-digit 
+     * representation of binary data.
+     *
+     * @param hash  16 byte binary md5-hash value in bytes
+     * 
+     * @return   32 character (plus    a terminating null character) hex-digit
+     *           representation of binary data.
+     */
+    char[] convertToHex(
+        byte[] hash)
+    {
+        int          i;
+        byte         j;
+        byte         fifteen = 15;
+        char[]      hex = new char[32];
+
+        for (i = 0; i < 16; i++)
+        {
+            //convert value of top 4 bits to hex char
+            hex[i*2] = getHexChar((byte)((hash[i] & 0xf0) >> 4));
+            //convert value of bottom 4 bits to hex char
+            hex[(i*2)+1] = getHexChar((byte)(hash[i] & 0x0f));
+        }
+
+        return hex;
+    }
+
+    /**
+     * Calculates the HA1 portion of the response
+     *
+     * @param  algorithm   Algorith to use.
+     * @param  userName    User being authenticated
+     * @param  realm       realm information
+     * @param  password    password of teh user
+     * @param  nonce       nonce value
+     * @param  clientNonce Clients Nonce value
+     *
+     * @return  HA1 portion of the response in a character array
+     *
+     * @exception SaslException  If an error occurs
+     */
+    char[] DigestCalcHA1(
+        String   algorithm,
+        String   userName,
+        String   realm,
+        String   password,
+        String   nonce,
+        String   clientNonce) throws SaslException
+    {
+        byte[]        hash;
+
+        try
+        {
+            MessageDigest md = MessageDigest.getInstance("MD5");
+
+            md.update(userName.getBytes("UTF-8"));
+            md.update(":".getBytes("UTF-8"));
+            md.update(realm.getBytes("UTF-8"));
+            md.update(":".getBytes("UTF-8"));
+            md.update(password.getBytes("UTF-8"));
+            hash = md.digest();
+
+            if ("md5-sess".equals(algorithm))
+            {
+                md.update(hash);
+                md.update(":".getBytes("UTF-8"));
+                md.update(nonce.getBytes("UTF-8"));
+                md.update(":".getBytes("UTF-8"));
+                md.update(clientNonce.getBytes("UTF-8"));
+                hash = md.digest();
+            }
+        }
+        catch(NoSuchAlgorithmException e)
+        {
+            throw new SaslException("No provider found for MD5 hash", e);
+        }
+        catch(UnsupportedEncodingException e)
+        {
+            throw new SaslException(
+             "UTF-8 encoding not supported by platform.", e);
+        }
+
+        return convertToHex(hash);
+    }
+
+
+    /**
+     * This function calculates the response-value of the response directive of
+     * the digest-response as documented in RFC 2831
+     *
+     * @param  HA1           H(A1)
+     * @param  serverNonce   nonce from server
+     * @param  nonceCount    8 hex digits
+     * @param  clientNonce   client nonce 
+     * @param  qop           qop-value: "", "auth", "auth-int"
+     * @param  method        method from the request
+     * @param  digestUri     requested URL
+     * @param  clientResponseFlag request-digest or response-digest
+     *
+     * @return Response-value of the response directive of the digest-response
+     *
+     * @exception SaslException  If an error occurs
+     */
+    char[] DigestCalcResponse(
+        char[]      HA1,            /* H(A1) */
+        String      serverNonce,    /* nonce from server */
+        String      nonceCount,     /* 8 hex digits */
+        String      clientNonce,    /* client nonce */
+        String      qop,            /* qop-value: "", "auth", "auth-int" */
+        String      method,         /* method from the request */
+        String      digestUri,      /* requested URL */
+        boolean     clientResponseFlag) /* request-digest or response-digest */
+            throws SaslException
+    {
+        byte[]             HA2;
+        byte[]             respHash;
+        char[]             HA2Hex;
+
+        // calculate H(A2)
+        try
+        {
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            if (clientResponseFlag)
+                  md.update(method.getBytes("UTF-8"));
+            md.update(":".getBytes("UTF-8"));
+            md.update(digestUri.getBytes("UTF-8"));
+            if ("auth-int".equals(qop))
+            {
+                md.update(":".getBytes("UTF-8"));
+                md.update("00000000000000000000000000000000".getBytes("UTF-8"));
+            }
+            HA2 = md.digest();
+            HA2Hex = convertToHex(HA2);
+
+            // calculate response
+            md.update(new String(HA1).getBytes("UTF-8"));
+            md.update(":".getBytes("UTF-8"));
+            md.update(serverNonce.getBytes("UTF-8"));
+            md.update(":".getBytes("UTF-8"));
+            if (qop.length() > 0)
+            {
+                md.update(nonceCount.getBytes("UTF-8"));
+                md.update(":".getBytes("UTF-8"));
+                md.update(clientNonce.getBytes("UTF-8"));
+                md.update(":".getBytes("UTF-8"));
+                md.update(qop.getBytes("UTF-8"));
+                md.update(":".getBytes("UTF-8"));
+            }
+            md.update(new String(HA2Hex).getBytes("UTF-8"));
+            respHash = md.digest();
+        }
+        catch(NoSuchAlgorithmException e)
+        {
+            throw new SaslException("No provider found for MD5 hash", e);
+        }
+        catch(UnsupportedEncodingException e)
+        {
+            throw new SaslException(
+             "UTF-8 encoding not supported by platform.", e);
+        }
+
+        return convertToHex(respHash);
+    }
+
+
+    /**
+     * Creates the intial response to be sent to the server.
+     *
+     * @param challenge  Challenge in bytes recived form the Server
+     *
+     * @return Initial response to be sent to the server
+     */
+    private String createDigestResponse(
+        byte[] challenge)
+            throws SaslException
+    {
+        char[]            response;
+        StringBuffer    digestResponse = new StringBuffer(512);
+        int             realmSize;
+
+        m_dc = new DigestChallenge(challenge);
+
+        m_digestURI = m_protocol + "/" + m_serverName;
+
+        if ((m_dc.getQop() & DigestChallenge.QOP_AUTH)
+            == DigestChallenge.QOP_AUTH )
+            m_qopValue = "auth";
+        else
+            throw new SaslException("Client only supports qop of 'auth'");
+
+        //get call back information
+        Callback[] callbacks = new Callback[3];
+        ArrayList realms = m_dc.getRealms();
+        realmSize = realms.size();
+        if (realmSize == 0)
+        {
+            callbacks[0] = new RealmCallback("Realm");
+        }
+        else if (realmSize == 1)
+        {
+            callbacks[0] = new RealmCallback("Realm", (String)realms.get(0));
+        }
+        else
+        {
+            callbacks[0] =
+             new RealmChoiceCallback(
+                         "Realm",
+                         (String[])realms.toArray(new String[realmSize]),
+                          0,      //the default choice index
+                          false); //no multiple selections
+        }
+
+        callbacks[1] = new PasswordCallback("Password", false); 
+        //false = no echo
+
+        if (m_authorizationId == null || m_authorizationId.length() == 0)
+            callbacks[2] = new NameCallback("Name");
+        else
+            callbacks[2] = new NameCallback("Name", m_authorizationId);
+
+        try
+        {
+            m_cbh.handle(callbacks);
+        }
+        catch(UnsupportedCallbackException e)
+        {
+            throw new SaslException("Handler does not support" +
+                                          " necessary callbacks",e);
+        }
+        catch(IOException e)
+        {
+            throw new SaslException("IO exception in CallbackHandler.", e);
+        }
+
+        if (realmSize > 1)
+        {
+            int[] selections =
+             ((RealmChoiceCallback)callbacks[0]).getSelectedIndexes();
+
+            if (selections.length > 0)
+                m_realm =
+                ((RealmChoiceCallback)callbacks[0]).getChoices()[selections[0]];
+            else
+                m_realm = ((RealmChoiceCallback)callbacks[0]).getChoices()[0];
+        }
+        else
+            m_realm = ((RealmCallback)callbacks[0]).getText();
+
+        m_clientNonce = getClientNonce();
+
+        m_name = ((NameCallback)callbacks[2]).getName();
+        if (m_name == null)
+            m_name = ((NameCallback)callbacks[2]).getDefaultName();
+        if (m_name == null)
+            throw new SaslException("No user name was specified.");
+
+        m_HA1 = DigestCalcHA1(
+                      m_dc.getAlgorithm(),
+                      m_name,
+                      m_realm,
+                      new String(((PasswordCallback)callbacks[1]).getPassword()),
+                      m_dc.getNonce(),
+                      m_clientNonce);
+
+        response = DigestCalcResponse(m_HA1,
+                                      m_dc.getNonce(),
+                                      "00000001",
+                                      m_clientNonce,
+                                      m_qopValue,
+                                      "AUTHENTICATE",
+                                      m_digestURI,
+                                      true);
+
+        digestResponse.append("username=\"");
+        digestResponse.append(m_authorizationId);
+        if (0 != m_realm.length())
+        {
+            digestResponse.append("\",realm=\"");
+            digestResponse.append(m_realm);
+        }
+        digestResponse.append("\",cnonce=\"");
+        digestResponse.append(m_clientNonce);
+        digestResponse.append("\",nc=");
+        digestResponse.append("00000001"); //nounce count
+        digestResponse.append(",qop=");
+        digestResponse.append(m_qopValue);
+        digestResponse.append(",digest-uri=\"ldap/");
+        digestResponse.append(m_serverName);
+        digestResponse.append("\",response=");
+        digestResponse.append(response);
+        digestResponse.append(",charset=utf-8,nonce=\"");
+        digestResponse.append(m_dc.getNonce());
+        digestResponse.append("\"");
+
+        return digestResponse.toString();
+     }
+     
+     
+    /**
+     * This function validates the server response. This step performs a 
+     * modicum of mutual authentication by verifying that the server knows
+     * the user's password
+     *
+     * @param  serverResponse  Response recived form Server
+     *
+     * @return  true if the mutual authentication succeeds;
+     *          else return false
+     *
+     * @exception SaslException  If an error occurs
+     */
+    boolean checkServerResponseAuth(
+            byte[]  serverResponse) throws SaslException
+    {
+        char[]           response;
+        ResponseAuth  responseAuth = null;
+        String        responseStr;
+
+        responseAuth = new ResponseAuth(serverResponse);
+
+        response = DigestCalcResponse(m_HA1,
+                                  m_dc.getNonce(),
+                                  "00000001",
+                                  m_clientNonce,
+                                  m_qopValue,
+                                  DIGEST_METHOD,
+                                  m_digestURI,
+                                  false);
+
+        responseStr = new String(response);
+
+        return responseStr.equals(responseAuth.getResponseValue());
+    }
+
+
+    /**
+     * This function returns hex character representing the value of the input
+     * 
+     * @param value Input value in byte
+     *
+     * @return Hex value of the Input byte value
+     */
+    private static char getHexChar(
+        byte    value)
+    {
+        switch (value)
+        {
+        case 0:
+            return '0';
+        case 1:
+            return '1';
+        case 2:
+            return '2';
+        case 3:
+            return '3';
+        case 4:
+            return '4';
+        case 5:
+            return '5';
+        case 6:
+            return '6';
+        case 7:
+            return '7';
+        case 8:
+            return '8';
+        case 9:
+            return '9';
+        case 10:
+            return 'a';
+        case 11:
+            return 'b';
+        case 12:
+            return 'c';
+        case 13:
+            return 'd';
+        case 14:
+            return 'e';
+        case 15:
+            return 'f';
+        default:
+            return 'Z';
+        }
+    }
+
+    /**
+     * Calculates the Nonce value of the Client
+     * 
+     * @return   Nonce value of the client
+     *
+     * @exception   SaslException If an error Occurs
+     */
+    String getClientNonce() throws SaslException
+    {
+        byte[]          nonceBytes = new byte[NONCE_BYTE_COUNT];
+        SecureRandom    prng;
+        byte            nonceByte;
+        char[]          hexNonce = new char[NONCE_HEX_COUNT];
+
+        try
+        {
+            prng = SecureRandom.getInstance("SHA1PRNG");
+            prng.nextBytes(nonceBytes);
+            for(int i=0; i<NONCE_BYTE_COUNT; i++)
+            {
+                //low nibble
+                hexNonce[i*2] = getHexChar((byte)(nonceBytes[i] & 0x0f));
+                //high nibble
+                hexNonce[(i*2)+1] = getHexChar((byte)((nonceBytes[i] & 0xf0)
+                                                                      >> 4));
+            }
+            return new String(hexNonce);
+        }
+        catch(NoSuchAlgorithmException e)
+        {
+            throw new SaslException("No random number generator available", e);
+        }
+    }
+
+    /**
+     * Returns the IANA-registered mechanism name of this SASL client.
+     *  (e.g. "CRAM-MD5", "GSSAPI")
+     *
+     * @return  "DIGEST-MD5"the IANA-registered mechanism name of this SASL
+     *          client.
+     */
+    public String getMechanismName()
+    {
+        return "DIGEST-MD5";
+    }
+
+} //end class DigestMD5SaslClient
+
diff --git a/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/DirectiveList.java b/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/DirectiveList.java
new file mode 100644
index 0000000..fc26a6b
--- /dev/null
+++ b/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/DirectiveList.java
@@ -0,0 +1,363 @@
+/* **************************************************************************
+ * $OpenLDAP: /com/novell/sasl/client/DirectiveList.java,v 1.4 2005/01/17 15:00:54 sunilk Exp $
+ *
+ * Copyright (C) 2002 Novell, Inc. All Rights Reserved.
+ *
+ * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
+ * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
+ * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
+ * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
+ * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
+ * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
+ * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
+ * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
+ ******************************************************************************/
+package com.novell.sasl.client;
+
+import java.util.*;
+import org.apache.harmony.javax.security.sasl.*;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Implements the DirectiveList class whihc will be used by the 
+ * DigestMD5SaslClient class
+ */
+class DirectiveList extends Object
+{
+    private static final int STATE_LOOKING_FOR_FIRST_DIRECTIVE  = 1;
+    private static final int STATE_LOOKING_FOR_DIRECTIVE        = 2;
+    private static final int STATE_SCANNING_NAME                = 3;
+    private static final int STATE_LOOKING_FOR_EQUALS            = 4;
+    private static final int STATE_LOOKING_FOR_VALUE            = 5;
+    private static final int STATE_LOOKING_FOR_COMMA            = 6;
+    private static final int STATE_SCANNING_QUOTED_STRING_VALUE    = 7;
+    private static final int STATE_SCANNING_TOKEN_VALUE            = 8;
+    private static final int STATE_NO_UTF8_SUPPORT              = 9;
+
+    private int        m_curPos;
+    private int        m_errorPos;
+    private String     m_directives;
+    private int        m_state;
+    private ArrayList  m_directiveList;
+    private String     m_curName;
+    private int        m_scanStart;
+
+    /**
+     *  Constructs a new DirectiveList.
+     */
+     DirectiveList(
+        byte[] directives)
+    {
+        m_curPos = 0;
+        m_state = STATE_LOOKING_FOR_FIRST_DIRECTIVE;
+        m_directiveList = new ArrayList(10);
+        m_scanStart = 0;
+        m_errorPos = -1;
+        try
+        {
+            m_directives = new String(directives, "UTF-8");
+        }
+        catch(UnsupportedEncodingException e)
+        {
+            m_state = STATE_NO_UTF8_SUPPORT;
+        }
+    }
+
+    /**
+     * This function takes a US-ASCII character string containing a list of comma
+     * separated directives, and parses the string into the individual directives
+     * and their values. A directive consists of a token specifying the directive
+     * name followed by an equal sign (=) and the directive value. The value is
+     * either a token or a quoted string
+     *
+     * @exception SaslException  If an error Occurs
+     */
+    void parseDirectives() throws SaslException
+    {
+        char        prevChar;
+        char        currChar;
+        int            rc = 0;
+        boolean        haveQuotedPair = false;
+        String      currentName = "<no name>";
+
+        if (m_state == STATE_NO_UTF8_SUPPORT)
+            throw new SaslException("No UTF-8 support on platform");
+
+        prevChar = 0;
+
+        while (m_curPos < m_directives.length())
+        {
+            currChar = m_directives.charAt(m_curPos);
+            switch (m_state)
+            {
+            case STATE_LOOKING_FOR_FIRST_DIRECTIVE:
+            case STATE_LOOKING_FOR_DIRECTIVE:
+                if (isWhiteSpace(currChar))
+                {
+                    break;
+                }
+                else if (isValidTokenChar(currChar))
+                {
+                    m_scanStart = m_curPos;
+                    m_state = STATE_SCANNING_NAME;
+                }
+                else
+                {
+                     m_errorPos = m_curPos;
+                    throw new SaslException("Parse error: Invalid name character");
+                }
+                break;
+
+            case STATE_SCANNING_NAME:
+                if (isValidTokenChar(currChar))
+                {
+                    break;
+                }
+                else if (isWhiteSpace(currChar))
+                {
+                    currentName = m_directives.substring(m_scanStart, m_curPos);
+                    m_state = STATE_LOOKING_FOR_EQUALS;
+                }
+                else if ('=' == currChar)
+                {
+                    currentName = m_directives.substring(m_scanStart, m_curPos);
+                    m_state = STATE_LOOKING_FOR_VALUE;
+                }
+                else
+                {
+                     m_errorPos = m_curPos;
+                    throw new SaslException("Parse error: Invalid name character");
+                }
+                break;
+
+            case STATE_LOOKING_FOR_EQUALS:
+                if (isWhiteSpace(currChar))
+                {
+                    break;
+                }
+                else if ('=' == currChar)
+                {
+                    m_state = STATE_LOOKING_FOR_VALUE;
+                }
+                else
+                {
+                    m_errorPos = m_curPos;
+                    throw new SaslException("Parse error: Expected equals sign '='.");
+                }
+                break;
+
+            case STATE_LOOKING_FOR_VALUE:
+                if (isWhiteSpace(currChar))
+                {
+                    break;
+                }
+                else if ('"' == currChar)
+                {
+                    m_scanStart = m_curPos+1; /* don't include the quote */
+                    m_state = STATE_SCANNING_QUOTED_STRING_VALUE;
+                }
+                else if (isValidTokenChar(currChar))
+                {
+                    m_scanStart = m_curPos;
+                    m_state = STATE_SCANNING_TOKEN_VALUE;
+                }
+                else
+                {
+                    m_errorPos = m_curPos;
+                    throw new SaslException("Parse error: Unexpected character");
+                }
+                break;
+
+            case STATE_SCANNING_TOKEN_VALUE:
+                if (isValidTokenChar(currChar))
+                {
+                    break;
+                }
+                else if (isWhiteSpace(currChar))
+                {
+                    addDirective(currentName, false);
+                    m_state = STATE_LOOKING_FOR_COMMA;
+                }
+                else if (',' == currChar)
+                {
+                    addDirective(currentName, false);
+                    m_state = STATE_LOOKING_FOR_DIRECTIVE;
+                }
+                else
+                {
+                     m_errorPos = m_curPos;
+                    throw new SaslException("Parse error: Invalid value character");
+                }
+                break;
+
+            case STATE_SCANNING_QUOTED_STRING_VALUE:
+                if ('\\' == currChar)
+                    haveQuotedPair = true;
+                if ( ('"' == currChar) &&
+                     ('\\' != prevChar) )
+                {
+                    addDirective(currentName, haveQuotedPair);
+                    haveQuotedPair = false;
+                    m_state = STATE_LOOKING_FOR_COMMA;
+                }
+                break;
+
+            case STATE_LOOKING_FOR_COMMA:
+                if (isWhiteSpace(currChar))
+                    break;
+                else if (currChar == ',')
+                    m_state = STATE_LOOKING_FOR_DIRECTIVE;
+                else
+                {
+                    m_errorPos = m_curPos;
+                    throw new SaslException("Parse error: Expected a comma.");
+                }
+                break;
+            }
+            if (0 != rc)
+                break;
+            prevChar = currChar;
+            m_curPos++;
+        } /* end while loop */
+
+
+        if (rc == 0)
+        {
+            /* check the ending state */
+            switch (m_state)
+            {
+            case STATE_SCANNING_TOKEN_VALUE:
+                addDirective(currentName, false);
+                break;
+
+            case STATE_LOOKING_FOR_FIRST_DIRECTIVE:
+            case STATE_LOOKING_FOR_COMMA:
+                break;
+
+            case STATE_LOOKING_FOR_DIRECTIVE:
+                    throw new SaslException("Parse error: Trailing comma.");
+
+            case STATE_SCANNING_NAME:
+            case STATE_LOOKING_FOR_EQUALS:
+            case STATE_LOOKING_FOR_VALUE:
+                    throw new SaslException("Parse error: Missing value.");
+
+            case STATE_SCANNING_QUOTED_STRING_VALUE:
+                    throw new SaslException("Parse error: Missing closing quote.");
+            }
+        }
+
+    }
+
+    /**
+     * This function returns TRUE if the character is a valid token character.
+     *
+     *     token          = 1*<any CHAR except CTLs or separators>
+     *
+     *      separators     = "(" | ")" | "<" | ">" | "@"
+     *                     | "," | ";" | ":" | "\" | <">
+     *                     | "/" | "[" | "]" | "?" | "="
+     *                     | "{" | "}" | SP | HT
+     *
+     *      CTL            = <any US-ASCII control character
+     *                       (octets 0 - 31) and DEL (127)>
+     *
+     *      CHAR           = <any US-ASCII character (octets 0 - 127)>
+     *
+     * @param c  character to be tested
+     *
+     * @return Returns TRUE if the character is a valid token character.
+     */
+    boolean isValidTokenChar(
+        char c)
+    {
+        if ( ( (c >= '\u0000') && (c <='\u0020') ) ||
+             ( (c >= '\u003a') && (c <= '\u0040') ) ||
+             ( (c >= '\u005b') && (c <= '\u005d') ) ||
+             ('\u002c' == c) ||
+             ('\u0025' == c) ||
+             ('\u0028' == c) ||
+             ('\u0029' == c) ||
+             ('\u007b' == c) ||
+             ('\u007d' == c) ||
+             ('\u007f' == c) )
+            return false;
+
+        return true;
+    }
+
+    /**
+     * This function returns TRUE if the character is linear white space (LWS).
+     *         LWS = [CRLF] 1*( SP | HT )
+     * @param c  Input charcter to be tested
+     *
+     * @return Returns TRUE if the character is linear white space (LWS)
+     */
+    boolean isWhiteSpace(
+        char c)
+    {
+        if ( ('\t' == c) ||  // HORIZONTAL TABULATION.
+             ('\n' == c) ||  // LINE FEED.
+             ('\r' == c) ||  // CARRIAGE RETURN.
+             ('\u0020' == c) )
+            return true;
+
+        return false;
+    }
+
+    /**
+     * This function creates a directive record and adds it to the list, the
+     * value will be added later after it is parsed.
+     *
+     * @param name  Name
+     * @param haveQuotedPair true if quoted pair is there else false
+     */
+    void addDirective(
+        String    name,
+        boolean   haveQuotedPair)
+    {
+        String value;
+        int    inputIndex;
+        int    valueIndex;
+        char   valueChar;
+        int    type;
+
+        if (!haveQuotedPair)
+        {
+            value = m_directives.substring(m_scanStart, m_curPos);
+        }
+        else
+        { //copy one character at a time skipping backslash excapes.
+            StringBuffer valueBuf = new StringBuffer(m_curPos - m_scanStart);
+            valueIndex = 0;
+            inputIndex = m_scanStart;
+            while (inputIndex < m_curPos)
+            {
+                if ('\\' == (valueChar = m_directives.charAt(inputIndex)))
+                    inputIndex++;
+                valueBuf.setCharAt(valueIndex, m_directives.charAt(inputIndex));
+                valueIndex++;
+                inputIndex++;
+            }
+            value = new String(valueBuf);
+        }
+
+        if (m_state == STATE_SCANNING_QUOTED_STRING_VALUE)
+            type = ParsedDirective.QUOTED_STRING_VALUE;
+        else
+            type = ParsedDirective.TOKEN_VALUE;
+        m_directiveList.add(new ParsedDirective(name, value, type));
+    }
+
+
+    /**
+     * Returns the List iterator.
+     *
+     * @return     Returns the Iterator Object for the List.
+     */
+    Iterator getIterator()
+    {
+        return m_directiveList.iterator();
+    }
+}
+
diff --git a/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/ParsedDirective.java b/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/ParsedDirective.java
new file mode 100644
index 0000000..17bf70e
--- /dev/null
+++ b/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/ParsedDirective.java
@@ -0,0 +1,56 @@
+/* **************************************************************************
+ * $OpenLDAP: /com/novell/sasl/client/ParsedDirective.java,v 1.1 2003/08/21 10:06:26 kkanil Exp $
+ *
+ * Copyright (C) 2002 Novell, Inc. All Rights Reserved.
+ *
+ * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
+ * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
+ * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
+ * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
+ * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
+ * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
+ * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
+ * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
+ ******************************************************************************/
+package com.novell.sasl.client;
+
+/**
+ * Implements the ParsedDirective class which will be used in the
+ * DigestMD5SaslClient mechanism.
+ */
+class ParsedDirective
+{
+    public static final int  QUOTED_STRING_VALUE = 1;
+    public static final int  TOKEN_VALUE         = 2;
+
+    private int     m_valueType;
+    private String  m_name;
+    private String  m_value;
+
+    ParsedDirective(
+        String  name,
+        String  value,
+        int     type)
+    {
+        m_name = name;
+        m_value = value;
+        m_valueType = type;
+    }
+
+    String getValue()
+    {
+        return m_value;
+    }
+
+    String getName()
+    {
+        return m_name;
+    }
+
+    int getValueType()
+    {
+        return m_valueType;
+    }
+
+}
+
diff --git a/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/ResponseAuth.java b/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/ResponseAuth.java
new file mode 100644
index 0000000..0aef955
--- /dev/null
+++ b/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/ResponseAuth.java
@@ -0,0 +1,83 @@
+/* **************************************************************************
+ * $OpenLDAP: /com/novell/sasl/client/ResponseAuth.java,v 1.3 2005/01/17 15:00:54 sunilk Exp $
+ *
+ * Copyright (C) 2002 Novell, Inc. All Rights Reserved.
+ *
+ * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
+ * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
+ * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
+ * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
+ * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
+ * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
+ * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
+ * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
+ ******************************************************************************/
+package com.novell.sasl.client;
+
+import java.util.*;
+import org.apache.harmony.javax.security.sasl.*;
+
+/**
+ * Implements the ResponseAuth class used by the DigestMD5SaslClient mechanism
+ */
+class ResponseAuth
+{
+
+    private String m_responseValue;
+
+    ResponseAuth(
+        byte[] responseAuth)
+            throws SaslException
+    {
+        m_responseValue = null;
+
+        DirectiveList dirList = new DirectiveList(responseAuth);
+        try
+        {
+            dirList.parseDirectives();
+            checkSemantics(dirList);
+        }
+        catch (SaslException e)
+        {
+        }
+    }
+
+    /**
+     * Checks the semantics of the directives in the directive list as parsed
+     * from the digest challenge byte array.
+     *
+     * @param dirList  the list of directives parsed from the digest challenge
+     *
+     * @exception SaslException   If a semantic error occurs
+     */
+    void checkSemantics(
+        DirectiveList dirList) throws SaslException
+    {
+        Iterator        directives = dirList.getIterator();
+        ParsedDirective directive;
+        String          name;
+
+        while (directives.hasNext())
+        {
+            directive = (ParsedDirective)directives.next();
+            name = directive.getName();
+            if (name.equals("rspauth"))
+                m_responseValue = directive.getValue();
+        }
+
+        /* post semantic check */
+        if (m_responseValue == null)
+            throw new SaslException("Missing response-auth directive.");
+    }
+
+    /**
+     * returns the ResponseValue
+     *
+     * @return the ResponseValue as a String.
+     */
+    public String getResponseValue()
+    {
+        return m_responseValue;
+    }
+}
+
diff --git a/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/TokenParser.java b/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/TokenParser.java
new file mode 100644
index 0000000..3d3491d
--- /dev/null
+++ b/asmack-master/static-src/novell-openldap-jldap/com/novell/sasl/client/TokenParser.java
@@ -0,0 +1,208 @@
+/* **************************************************************************
+ * $OpenLDAP: /com/novell/sasl/client/TokenParser.java,v 1.3 2005/01/17 15:00:54 sunilk Exp $
+ *
+ * Copyright (C) 2002 Novell, Inc. All Rights Reserved.
+ *
+ * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
+ * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
+ * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
+ * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
+ * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
+ * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
+ * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
+ * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
+ ******************************************************************************/
+package com.novell.sasl.client;
+
+import org.apache.harmony.javax.security.sasl.*;
+/**
+ * The TokenParser class will parse individual tokens from a list of tokens that
+ * are a directive value for a DigestMD5 authentication.The tokens are separated
+ * commas.
+ */
+class TokenParser extends Object
+{
+    private static final int STATE_LOOKING_FOR_FIRST_TOKEN = 1;
+    private static final int STATE_LOOKING_FOR_TOKEN       = 2;
+    private static final int STATE_SCANNING_TOKEN          = 3;
+    private static final int STATE_LOOKING_FOR_COMMA       = 4;
+    private static final int STATE_PARSING_ERROR           = 5;
+    private static final int STATE_DONE                    = 6;
+
+    private int        m_curPos;
+    private int     m_scanStart;
+    private int     m_state;
+    private String  m_tokens;
+
+
+    TokenParser(
+        String tokens)
+    {
+        m_tokens = tokens;
+        m_curPos = 0;
+        m_scanStart = 0;
+        m_state =  STATE_LOOKING_FOR_FIRST_TOKEN;
+    }
+
+    /**
+     * This function parses the next token from the tokens string and returns
+     * it as a string. If there are no more tokens a null reference is returned.
+     *
+     * @return  the parsed token or a null reference if there are no more
+     * tokens
+     *
+     * @exception  SASLException if an error occurs while parsing
+     */
+    String parseToken() throws SaslException
+    {
+        char    currChar;
+        String  token = null;
+
+
+        if (m_state == STATE_DONE)
+            return null;
+
+        while (m_curPos < m_tokens.length() && (token == null))
+        {
+            currChar = m_tokens.charAt(m_curPos);
+            switch (m_state)
+            {
+            case STATE_LOOKING_FOR_FIRST_TOKEN:
+            case STATE_LOOKING_FOR_TOKEN:
+                if (isWhiteSpace(currChar))
+                {
+                    break;
+                }
+                else if (isValidTokenChar(currChar))
+                {
+                    m_scanStart = m_curPos;
+                    m_state = STATE_SCANNING_TOKEN;
+                }
+                else
+                {
+                    m_state = STATE_PARSING_ERROR;
+                    throw new SaslException("Invalid token character at position " + m_curPos);
+                }
+                break;
+
+            case STATE_SCANNING_TOKEN:
+                if (isValidTokenChar(currChar))
+                {
+                    break;
+                }
+                else if (isWhiteSpace(currChar))
+                {
+                    token = m_tokens.substring(m_scanStart, m_curPos);
+                    m_state = STATE_LOOKING_FOR_COMMA;
+                }
+                else if (',' == currChar)
+                {
+                    token = m_tokens.substring(m_scanStart, m_curPos);
+                    m_state = STATE_LOOKING_FOR_TOKEN;
+                }
+                else
+                {
+                    m_state = STATE_PARSING_ERROR;
+                    throw new SaslException("Invalid token character at position " + m_curPos);
+                }
+                break;
+
+
+            case STATE_LOOKING_FOR_COMMA:
+                if (isWhiteSpace(currChar))
+                    break;
+                else if (currChar == ',')
+                    m_state = STATE_LOOKING_FOR_TOKEN;
+                else
+                {
+                    m_state = STATE_PARSING_ERROR;
+                    throw new SaslException("Expected a comma, found '" +
+                                            currChar + "' at postion " +
+                                            m_curPos);
+                }
+                break;
+            }
+            m_curPos++;
+        } /* end while loop */
+
+        if (token == null)
+        {    /* check the ending state */
+            switch (m_state)
+            {
+            case STATE_SCANNING_TOKEN:
+                token = m_tokens.substring(m_scanStart);
+                m_state = STATE_DONE;
+                break;
+
+            case STATE_LOOKING_FOR_FIRST_TOKEN:
+            case STATE_LOOKING_FOR_COMMA:
+                break;
+
+            case STATE_LOOKING_FOR_TOKEN:
+                throw new SaslException("Trialing comma");
+            }
+        }
+
+        return token;
+    }
+
+    /**
+     * This function returns TRUE if the character is a valid token character.
+     *
+     *     token          = 1*<any CHAR except CTLs or separators>
+     *
+     *      separators     = "(" | ")" | "<" | ">" | "@"
+     *                     | "," | ";" | ":" | "\" | <">
+     *                     | "/" | "[" | "]" | "?" | "="
+     *                     | "{" | "}" | SP | HT
+     *
+     *      CTL            = <any US-ASCII control character
+     *                       (octets 0 - 31) and DEL (127)>
+     *
+     *      CHAR           = <any US-ASCII character (octets 0 - 127)>
+     *
+     * @param c  character to be validated
+     *
+     * @return True if character is valid Token character else it returns 
+     * false
+     */
+    boolean isValidTokenChar(
+        char c)
+    {
+        if ( ( (c >= '\u0000') && (c <='\u0020') ) ||
+             ( (c >= '\u003a') && (c <= '\u0040') ) ||
+             ( (c >= '\u005b') && (c <= '\u005d') ) ||
+             ('\u002c' == c) ||
+             ('\u0025' == c) ||
+             ('\u0028' == c) ||
+             ('\u0029' == c) ||
+             ('\u007b' == c) ||
+             ('\u007d' == c) ||
+             ('\u007f' == c) )
+            return false;
+
+        return true;
+    }
+
+    /**
+     * This function returns TRUE if the character is linear white space (LWS).
+     *         LWS = [CRLF] 1*( SP | HT )
+     *
+     * @param c  character to be validated
+     *
+     * @return True if character is liner whitespace else it returns false
+     */
+    boolean isWhiteSpace(
+        char c)
+    {
+        if ( ('\t' == c) || // HORIZONTAL TABULATION.
+             ('\n' == c) || // LINE FEED.
+             ('\r' == c) || // CARRIAGE RETURN.
+             ('\u0020' == c) )
+            return true;
+
+        return false;
+    }
+
+}
+