diff --git a/.travis.yml b/.travis.yml
index 4c39aa61..66a62d37 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,9 +7,18 @@ php:
- 5.4
- 5.5
+env:
+ global:
+ # Defines CODE_COVERAGE_PASSPHRASE which is the passphrase for unlocking
+ # the tests/code_coverage_id_rsa RSA private key.
+ - secure: "jtQTZKQBnzUlp/jz7NlM6470ZDnLGVAs53sgvIm4tcYqf9TWSXSXjIYvFsrS\nKPR2eyZaAevYysUkIGRFTUXTlG6tC36YngMp9+6FPxASl8mnGXsTbKcm613B\n59vD3242pgIgqhhmgFQ0c8gbvnE8PuF2aS4/hluP3r+AxhWN56E="
+
before_script:
- git clone git://github.com/zenovich/runkit.git && cd runkit && phpize && ./configure && make && make install && cd ..
- echo "extension=runkit.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`
script:
- - phpunit --verbose
+ - phpunit --verbose --coverage-html code_coverage/
+
+after_success:
+ - sh -c "if $TRAVIS_SECURE_ENV_VARS; then tests/code_coverage_upload.sh; fi"
diff --git a/README.md b/README.md
index 4e1330e8..fbd58bd8 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@ AES, SSH-1, SSH-2, SFTP, and X.509
* [Browse Git](https://github.com/phpseclib/phpseclib)
* [Documentation](http://phpseclib.sourceforge.net/)
* [Support](http://www.frostjedi.com/phpbb/viewforum.php?f=46)
+* [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/latest/)
PEAR Channel: [phpseclib.sourceforge.net](http://phpseclib.sourceforge.net/pear.htm)
diff --git a/tests/code_coverage_id_rsa b/tests/code_coverage_id_rsa
new file mode 100644
index 00000000..25d4094c
--- /dev/null
+++ b/tests/code_coverage_id_rsa
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,2F15FCF0B21FCFB5A37D709322F9B9EB
+
+JpGgJqRnr0+3mHQoeYXXUzSWeA1wGwMzm6KOPnQLEmA9ztPlBQulzZRh6QJckCwy
+TC7BMo+XRnYVXF3e0rjji0k7cfEk5Gs8saNcxxOa0u0SUOCXelGnZeqzwiT0a6Fe
+qAc7NLgTEo9zul9s+MHsplkVk71Oke+1dL7kksMRT0TdXIaqSvk/+nyAeLzAot04
+wo61T3+Y7/v/8oVxlCbxI5YfYZkm/4jTy7AfbXZBvC0R+F0ZYvIDRCuBe6h6XvcH
+AiYtw5+Qek6FwIa2CFVxsefvsEnZQYaiJpEFAq2xVHlTjQHHYrfd5cgu1koUNsAt
+nX1zpsK7tIregXFa07KfDaBBPxfEBqVJQInzj0Rc8HUt0AZ+MrPldrZ28+YQ4RXk
+/qk5UyKkdHMSKBb4va3mxcpDq1As9HREfeUeOjjduRh1LnNQCJaOhydXBqCFvhFy
++Q9utDXP6q4OUxeDHCPGQ7K1I7erwiwuTeSXB3BEDZyZywHXABvJpsidkDlD/aNo
+QmM19V8y0IAxEAZvc8N0MIOO8hmd8R9U1RK4S24o9M8mgRrmuXjViJjZd5E3h6tX
+Mgxm8dpOiT77i+NsJwyp2A+MhkAHg2ruwlCIrSCC81zvdphVTfuc/vx3JpXYvhTP
+Xf9R8ppGnDUFauroN7E7odJKDhLVuAbmU1lWwue2iaNEKZ3L/o9dpRz4Td4NzzSf
+HKvKbJR35FCsqZq2krmNVd6ynF5PzWfYmz850yn/qdU8zwnW0fV+iHKS2oXuH9X1
+ZW02/MDdCylpRftNJMntR4Yxim7WEZ5Dif9ZLj8IGRQdWbbIn0WjtiVrFrcUbIfk
+TCP/3GeEcUa/XbE9hO9APw+7rO3sOehGJ84n4tXxFTFSnOJ5ZxTKpLvxRrmC8DaD
+cvqy8bbjPfn1EjZmRpCjanLZ1UJbLitFfpUT55aTrcozS4FMHmFm74X2xZGeBhxC
+CpWQe/agxhWxG+ZXdxt9ExI78ftQCQoGE0Si1KZXH5KQ/xiGmebY9wbtEHWG+q25
+sKqvjQHQsE3NZq7kne3mnyvjzMDDFYPLDlQLgcKInNrLZ3GszyemtzqcVf3YVur4
+N+nN0gu6LCx0vtw3yNRqjjmGN1V6sKMCqmIAtFDh9zRTlDTs7ZUBGPgakmmJLLVM
+ESme0JrRxCP+eEU8JNti9pKlKPGOFVpu4shLjmnmKuDpOytFNpcB/NylkGwZCxvE
+1KI+EQMZOE5VROAfkvwBLE0SsVxMq7H87zSEOtOqr+QN8RoY1V6N/woBVWda9GFk
+HI44PM2ZywQbLGthaQV/Kxwf9YZruJdunNoTfEufZgv2Vp+3VAs+gCTGIsbblTnH
+J8QGfs/lHRBqK1pMZrYy0ubFqifA+b9Xa6VJWToCgcQuWbOVWn1zKQTTXZPksVbB
+qyE8BJkQCDGgoeq4kdxm0XUR5p3UZWQv0HoykQt33U06TCzU9HOcp0z+Glhrzsvd
+rbNBhRK0zXF/BFSNBHwKEg02TNlj7gSFJXmvZqvyCAFo5D6nSDbzqm6ARuscsrF0
+6Zd3toOZTWmrVsKvTlsNPfHXyoGqP3+0NXcTY+kKXG58u4TbEtw8pVyPikuVdh/m
+-----END RSA PRIVATE KEY-----
diff --git a/tests/code_coverage_upload.sh b/tests/code_coverage_upload.sh
new file mode 100755
index 00000000..7ab9494b
--- /dev/null
+++ b/tests/code_coverage_upload.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# This file is part of the phpseclib test suite.
+#
+# (c) Andreas Fischer
+#
+# For the full copyright and license information, please view the LICENSE
+# file that was distributed with this source code.
+#
+
+USERNAME='phpseclib'
+HOSTNAME='phpseclib.bantux.org'
+HOSTRSAF='09:40:96:14:6a:cd:67:46:17:e5:b4:39:24:24:6e:9d'
+LDIRNAME='code_coverage'
+RDIRNAME='code_coverage'
+ID_RSA='tests/code_coverage_id_rsa'
+
+# Install expect if necessary
+if ! which expect > /dev/null
+then
+ sudo apt-get update -qq
+ sudo apt-get install -qq expect
+fi
+
+# Workaround for rsync not creating target directories with depth > 1
+mv "$LDIRNAME" "x$LDIRNAME"
+mkdir -p "$RDIRNAME/$TRAVIS_BUILD_NUMBER"
+mv "x$LDIRNAME" "$RDIRNAME/$TRAVIS_BUILD_NUMBER/PHP-$TRAVIS_PHP_VERSION/"
+
+# Update latest symlink
+ln -s "$TRAVIS_BUILD_NUMBER" "$RDIRNAME/latest"
+
+# Stop complaints about world-readable key file.
+chmod 600 "$ID_RSA"
+
+export RSYNC_RSH="ssh -4 -i $ID_RSA -o ConnectTimeout=5"
+RSYNC_OPT="--recursive --times --links --progress"
+
+expect << EOF
+ spawn rsync $RSYNC_OPT "$RDIRNAME/" "$USERNAME@$HOSTNAME:$RDIRNAME/"
+
+ expect "RSA key fingerprint is $HOSTRSAF."
+ send "yes\n"
+
+ expect "Enter passphrase for key '$ID_RSA':"
+ send "$CODE_COVERAGE_PASSPHRASE\n"
+
+ expect eof
+EOF