[PATCH 3/3] Import pexpect.

Jelmer Vernooij jelmer at samba.org
Thu Jan 29 14:52:46 MST 2015


Change-Id: I94ee5e9d3d91c8d72e76cbdcc4534452321dffb1
Signed-Off-By: Jelmer Vernooij <jelmer at samba.org>
---
 lib/extras/extras/__init__.py                      |    2 +
 lib/extras/extras/tests/test_extras.py             |    2 +
 lib/mimeparse/mimeparse.py                         |    0
 lib/mimeparse/setup.py                             |    5 +-
 lib/pep8/pep8.py                                   |  146 +-
 lib/subunit/INSTALL                                |    5 +-
 lib/subunit/MANIFEST.in                            |    2 +-
 lib/subunit/Makefile.am                            |   26 +-
 lib/subunit/NEWS                                   |  227 +++
 lib/subunit/README                                 |  281 ++-
 lib/subunit/configure.ac                           |    5 +-
 lib/subunit/filters/subunit-filter                 |   25 +-
 lib/subunit/filters/subunit-ls                     |   32 +-
 lib/subunit/filters/subunit-notify                 |    6 +-
 lib/subunit/filters/subunit-stats                  |   29 +-
 lib/subunit/filters/subunit-tags                   |    1 +
 lib/subunit/filters/subunit2csv                    |    5 +-
 lib/subunit/filters/subunit2gtk                    |   77 +-
 lib/subunit/filters/subunit2junitxml               |    7 +-
 lib/subunit/filters/subunit2pyunit                 |   23 +-
 lib/subunit/perl/Makefile.PL.in                    |    4 +-
 lib/subunit/python/subunit/__init__.py             |  162 +-
 lib/subunit/python/subunit/filters.py              |  111 +-
 lib/subunit/python/subunit/run.py                  |   80 +-
 lib/subunit/python/subunit/test_results.py         |   64 +-
 lib/subunit/python/subunit/tests/TestUtil.py       |   80 -
 lib/subunit/python/subunit/tests/__init__.py       |   52 +-
 lib/subunit/python/subunit/tests/test_chunked.py   |    6 -
 lib/subunit/python/subunit/tests/test_details.py   |    6 -
 .../python/subunit/tests/test_progress_model.py    |    6 -
 lib/subunit/python/subunit/tests/test_run.py       |   97 +-
 .../python/subunit/tests/test_subunit_filter.py    |  110 +-
 .../python/subunit/tests/test_subunit_stats.py     |    6 -
 .../python/subunit/tests/test_subunit_tags.py      |   90 +-
 .../python/subunit/tests/test_tap2subunit.py       |  378 ++--
 .../python/subunit/tests/test_test_protocol.py     |   75 +-
 .../python/subunit/tests/test_test_results.py      |    6 -
 lib/subunit/runtests.py                            |  138 --
 lib/subunit/setup.py                               |   22 +-
 lib/testtools/.testr.conf                          |    2 +-
 lib/testtools/LICENSE                              |    1 +
 lib/testtools/MANIFEST.in                          |    4 +-
 lib/testtools/Makefile                             |    8 +-
 lib/testtools/NEWS                                 |   64 +-
 lib/testtools/README                               |   89 -
 lib/testtools/doc/for-framework-folk.rst           |  235 ++-
 lib/testtools/doc/for-test-authors.rst             |  149 +-
 lib/testtools/doc/hacking.rst                      |   97 +-
 lib/testtools/doc/index.rst                        |    2 +-
 lib/testtools/doc/overview.rst                     |   13 +-
 lib/testtools/scripts/_lp_release.py               |    6 +-
 lib/testtools/setup.cfg                            |    3 +
 lib/testtools/setup.py                             |   57 +-
 lib/testtools/testtools/__init__.py                |  120 +-
 lib/testtools/testtools/compat.py                  |  102 +-
 lib/testtools/testtools/content.py                 |  229 ++-
 lib/testtools/testtools/content_type.py            |    2 +-
 lib/testtools/testtools/deferredruntest.py         |   18 +-
 lib/testtools/testtools/distutilscmd.py            |    2 +-
 lib/testtools/testtools/helpers.py                 |   83 +-
 lib/testtools/testtools/matchers/__init__.py       |    6 +
 lib/testtools/testtools/matchers/_basic.py         |   13 +-
 lib/testtools/testtools/matchers/_dict.py          |    2 +-
 lib/testtools/testtools/matchers/_exception.py     |   24 +-
 lib/testtools/testtools/matchers/_higherorder.py   |   79 +
 lib/testtools/testtools/matchers/_impl.py          |    4 +-
 lib/testtools/testtools/run.py                     |  352 ++--
 lib/testtools/testtools/runtest.py                 |   38 +-
 lib/testtools/testtools/testcase.py                |  332 +++-
 lib/testtools/testtools/testresult/__init__.py     |   24 +
 lib/testtools/testtools/testresult/doubles.py      |   24 +
 lib/testtools/testtools/testresult/real.py         |  800 ++++++++-
 lib/testtools/testtools/tests/__init__.py          |    7 +-
 lib/testtools/testtools/tests/helpers.py           |   13 +-
 .../testtools/tests/matchers/test_basic.py         |   24 +-
 .../testtools/tests/matchers/test_dict.py          |    7 +-
 .../testtools/tests/matchers/test_exception.py     |    7 +-
 .../testtools/tests/matchers/test_higherorder.py   |   27 +
 lib/testtools/testtools/tests/test_compat.py       |  183 +-
 lib/testtools/testtools/tests/test_content.py      |   91 +-
 lib/testtools/testtools/tests/test_content_type.py |    2 +-
 .../testtools/tests/test_deferredruntest.py        |   28 +-
 lib/testtools/testtools/tests/test_distutilscmd.py |    7 +-
 .../testtools/tests/test_fixturesupport.py         |   30 +-
 lib/testtools/testtools/tests/test_helpers.py      |  183 --
 lib/testtools/testtools/tests/test_run.py          |  258 ++-
 lib/testtools/testtools/tests/test_runtest.py      |   58 +-
 lib/testtools/testtools/tests/test_spinner.py      |   20 +-
 lib/testtools/testtools/tests/test_testcase.py     |  425 ++++-
 lib/testtools/testtools/tests/test_testresult.py   |  890 +++++++++-
 lib/testtools/testtools/tests/test_testsuite.py    |  192 +-
 lib/testtools/testtools/tests/test_with_with.py    |   20 +
 lib/testtools/testtools/testsuite.py               |  178 +-
 third_party/pexpect/.gitignore                     |    9 +
 third_party/pexpect/.travis.yml                    |   23 +
 third_party/pexpect/ANSI.py                        |    7 +
 third_party/pexpect/DEVELOPERS.rst                 |   12 +
 third_party/pexpect/FSM.py                         |    7 +
 third_party/pexpect/LICENSE                        |   19 +
 third_party/pexpect/MANIFEST.in                    |    8 +
 third_party/pexpect/README.rst                     |   53 +
 third_party/pexpect/doc/FAQ.rst                    |  136 ++
 third_party/pexpect/doc/Makefile                   |  153 ++
 third_party/pexpect/doc/api/ANSI.rst               |   14 +
 third_party/pexpect/doc/api/fdpexpect.rst          |   22 +
 third_party/pexpect/doc/api/index.rst              |   12 +
 third_party/pexpect/doc/api/pexpect.rst            |  111 ++
 third_party/pexpect/doc/api/pxssh.rst              |   34 +
 third_party/pexpect/doc/api/replwrap.rst           |   26 +
 third_party/pexpect/doc/api/screen.rst             |   10 +
 third_party/pexpect/doc/clean.css                  |  103 ++
 third_party/pexpect/doc/commonissues.rst           |  115 ++
 third_party/pexpect/doc/conf.py                    |  250 +++
 third_party/pexpect/doc/examples.rst               |   63 +
 third_party/pexpect/doc/history.rst                |  215 +++
 third_party/pexpect/doc/index.rst                  |   50 +
 third_party/pexpect/doc/install.rst                |   20 +
 third_party/pexpect/doc/make.bat                   |  190 ++
 third_party/pexpect/doc/overview.rst               |  240 +++
 third_party/pexpect/doc/requirements.txt           |    1 +
 third_party/pexpect/doc/sphinxext/github.py        |  155 ++
 third_party/pexpect/examples/README                |   89 +
 third_party/pexpect/examples/astat.py              |   99 ++
 third_party/pexpect/examples/cgishell.cgi          |  766 ++++++++
 third_party/pexpect/examples/chess.py              |  148 ++
 third_party/pexpect/examples/chess2.py             |  153 ++
 third_party/pexpect/examples/chess3.py             |  157 ++
 third_party/pexpect/examples/df.py                 |   57 +
 third_party/pexpect/examples/ftp.py                |   73 +
 third_party/pexpect/examples/hive.py               |  466 +++++
 third_party/pexpect/examples/monitor.py            |  229 +++
 third_party/pexpect/examples/passmass.py           |  116 ++
 third_party/pexpect/examples/python.py             |   49 +
 third_party/pexpect/examples/script.py             |  114 ++
 third_party/pexpect/examples/ssh_tunnel.py         |  105 ++
 third_party/pexpect/examples/table_test.html       |  106 ++
 third_party/pexpect/examples/topip.py              |  299 ++++
 third_party/pexpect/examples/uptime.py             |   81 +
 third_party/pexpect/fdpexpect.py                   |    7 +
 third_party/pexpect/notes/my_forkpty.py            |   89 +
 third_party/pexpect/notes/notes.txt                |   50 +
 third_party/pexpect/notes/posixmodule.c.diff       |  233 +++
 third_party/pexpect/pexpect/ANSI.py                |  351 ++++
 third_party/pexpect/pexpect/FSM.py                 |  334 ++++
 third_party/pexpect/pexpect/__init__.py            |  232 +++
 third_party/pexpect/pexpect/async.py               |   70 +
 third_party/pexpect/pexpect/bashrc.sh              |    5 +
 third_party/pexpect/pexpect/exceptions.py          |   35 +
 third_party/pexpect/pexpect/expect.py              |  297 ++++
 third_party/pexpect/pexpect/fdpexpect.py           |   86 +
 third_party/pexpect/pexpect/pty_spawn.py           |  819 +++++++++
 third_party/pexpect/pexpect/pxssh.py               |  403 +++++
 third_party/pexpect/pexpect/replwrap.py            |  113 ++
 third_party/pexpect/pexpect/screen.py              |  424 +++++
 third_party/pexpect/pexpect/spawnbase.py           |  484 +++++
 third_party/pexpect/pexpect/utils.py               |  112 ++
 third_party/pexpect/pxssh.py                       |    7 +
 third_party/pexpect/screen.py                      |    7 +
 third_party/pexpect/setup.cfg                      |    2 +
 third_party/pexpect/setup.py                       |   65 +
 third_party/pexpect/tests/PexpectTestCase.py       |  108 ++
 third_party/pexpect/tests/README                   |    8 +
 third_party/pexpect/tests/TESTDATA.txt             |    8 +
 third_party/pexpect/tests/__init__.py              |   25 +
 third_party/pexpect/tests/adhoc.py                 |   36 +
 third_party/pexpect/tests/alarm_die.py             |    5 +
 third_party/pexpect/tests/bambi.vt                 |  417 +++++
 .../tests/depricated_test_filedescriptor.py        |   82 +
 third_party/pexpect/tests/echo_w_prompt.py         |   15 +
 third_party/pexpect/tests/echo_wait.py             |   41 +
 third_party/pexpect/tests/exit1.py                 |   24 +
 third_party/pexpect/tests/exit667.c                |   26 +
 third_party/pexpect/tests/fakessh/ssh              |   29 +
 third_party/pexpect/tests/getch.py                 |   48 +
 third_party/pexpect/tests/globe.vt                 |  690 ++++++++
 third_party/pexpect/tests/interact.py              |   40 +
 third_party/pexpect/tests/interact_unicode.py      |   24 +
 third_party/pexpect/tests/list100.py               |    2 +
 third_party/pexpect/tests/needs_kill.py            |   13 +
 third_party/pexpect/tests/pexpectTest.py           |   69 +
 .../tests/platform_checks/CSIGNALTEST/test.c       |   90 +
 third_party/pexpect/tests/platform_checks/README   |    2 +
 third_party/pexpect/tests/platform_checks/check.py |   77 +
 .../pexpect/tests/platform_checks/check2.py        |   44 +
 .../platform_checks/check_control_terminal.py      |   19 +
 .../pexpect/tests/platform_checks/check_handler.py |   60 +
 .../pexpect/tests/platform_checks/check_read.py    |   35 +
 .../pexpect/tests/platform_checks/check_signals.py |   67 +
 third_party/pexpect/tests/qa.py                    |   26 +
 third_party/pexpect/tests/sigwinch_report.py       |   49 +
 third_party/pexpect/tests/sleep_for.py             |   41 +
 third_party/pexpect/tests/swapcase_echo.py         |   26 +
 third_party/pexpect/tests/test_FSM.py              |   34 +
 third_party/pexpect/tests/test_ansi.py             |  228 +++
 third_party/pexpect/tests/test_async.py            |   51 +
 .../pexpect/tests/test_command_list_split.py       |   40 +
 third_party/pexpect/tests/test_constructor.py      |   48 +
 third_party/pexpect/tests/test_ctrl_chars.py       |  125 ++
 third_party/pexpect/tests/test_destructor.py       |   84 +
 third_party/pexpect/tests/test_dotall.py           |   43 +
 third_party/pexpect/tests/test_expect.py           |  583 +++++++
 third_party/pexpect/tests/test_filedescriptor.py   |   72 +
 third_party/pexpect/tests/test_interact.py         |   94 +
 third_party/pexpect/tests/test_isalive.py          |  114 ++
 third_party/pexpect/tests/test_log.py              |  108 ++
 third_party/pexpect/tests/test_maxcanon.py         |  152 ++
 third_party/pexpect/tests/test_misc.py             |  351 ++++
 third_party/pexpect/tests/test_missing_command.py  |   38 +
 third_party/pexpect/tests/test_performance.py      |  107 ++
 third_party/pexpect/tests/test_pickling.py         |   14 +
 third_party/pexpect/tests/test_pxssh.py            |   53 +
 third_party/pexpect/tests/test_replwrap.py         |   84 +
 third_party/pexpect/tests/test_repr.py             |   26 +
 third_party/pexpect/tests/test_run.py              |  117 ++
 third_party/pexpect/tests/test_run_out_of_pty.py   |   51 +
 third_party/pexpect/tests/test_screen.py           |  287 +++
 third_party/pexpect/tests/test_timeout_pattern.py  |   92 +
 third_party/pexpect/tests/test_unicode.py          |  179 ++
 third_party/pexpect/tests/test_which.py            |  269 +++
 third_party/pexpect/tests/test_winsize.py          |   67 +
 third_party/pexpect/tests/tetris.data              |    3 +
 third_party/pexpect/tests/ticker.py                |   28 +
 third_party/pexpect/tests/torturet.vt              |   61 +
 third_party/pexpect/tests/utils.py                 |    7 +
 third_party/pexpect/tools/display-sighandlers.py   |   20 +
 third_party/pexpect/tools/display-terminalinfo.py  |  209 +++
 .../pexpect/tools/teamcity-coverage-report.sh      |   27 +
 third_party/pexpect/tools/teamcity-runtests.sh     |   61 +
 third_party/zlib/ChangeLog                         |  619 ++++++-
 third_party/zlib/FAQ                               |  267 +--
 third_party/zlib/INDEX                             |   41 +-
 third_party/zlib/Makefile                          |  157 +-
 third_party/zlib/Makefile.in                       |  264 ++-
 third_party/zlib/README                            |   94 +-
 third_party/zlib/adler32.c                         |   99 +-
 third_party/zlib/algorithm.txt                     |  209 ---
 third_party/zlib/amiga/Makefile.pup                |    9 +-
 third_party/zlib/amiga/Makefile.sas                |    9 +-
 third_party/zlib/as400/bndsrc                      |   83 +
 third_party/zlib/as400/compile.clp                 |   95 +-
 third_party/zlib/as400/readme.txt                  |   14 +-
 third_party/zlib/as400/zlib.inc                    |  160 +-
 third_party/zlib/compress.c                        |   10 +-
 third_party/zlib/contrib/README.contrib            |   23 +-
 third_party/zlib/contrib/ada/zlib-streams.ads      |    6 +-
 third_party/zlib/contrib/ada/zlib-thin.ads         |    2 +-
 third_party/zlib/contrib/asm586/README.586         |   43 -
 third_party/zlib/contrib/asm586/match.S            |  364 ----
 third_party/zlib/contrib/asm686/README.686         |   17 +
 third_party/zlib/contrib/asm686/match.S            |   40 +-
 third_party/zlib/contrib/blast/blast.c             |    8 +-
 third_party/zlib/contrib/blast/blast.h             |    8 +-
 third_party/zlib/contrib/delphi/ZLib.pas           |    2 +-
 third_party/zlib/contrib/delphi/zlibd32.mak        |   20 +-
 third_party/zlib/contrib/dotzlib/DotZLib.build     |    4 +-
 third_party/zlib/contrib/dotzlib/DotZLib.chm       |  Bin 72728 -> 72726 bytes
 .../zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs   |   20 +-
 .../zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs   |   10 +-
 .../zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs |    4 +-
 .../zlib/contrib/dotzlib/DotZLib/CodecBase.cs      |    8 +-
 .../zlib/contrib/dotzlib/DotZLib/Deflater.cs       |    6 +-
 .../zlib/contrib/dotzlib/DotZLib/DotZLib.cs        |   20 +-
 .../zlib/contrib/dotzlib/DotZLib/GZipStream.cs     |   18 +-
 .../zlib/contrib/dotzlib/DotZLib/Inflater.cs       |    6 +-
 .../zlib/contrib/dotzlib/DotZLib/UnitTests.cs      |   10 +-
 third_party/zlib/contrib/dotzlib/readme.txt        |   18 +-
 third_party/zlib/contrib/infback9/infback9.c       |   95 +-
 third_party/zlib/contrib/infback9/inftree9.c       |   21 +-
 third_party/zlib/contrib/infback9/inftree9.h       |   24 +-
 third_party/zlib/contrib/inflate86/inffas86.c      |    2 +-
 third_party/zlib/contrib/masm686/match.asm         |  413 -----
 third_party/zlib/contrib/masmx64/gvmat64.asm       |   52 +-
 third_party/zlib/contrib/masmx64/inffas8664.c      |    6 +-
 third_party/zlib/contrib/masmx64/inffasx64.asm     |   12 +-
 third_party/zlib/contrib/masmx64/readme.txt        |    7 +-
 third_party/zlib/contrib/masmx86/bld_ml32.bat      |    4 +-
 third_party/zlib/contrib/masmx86/gvmat32.asm       |  972 -----------
 third_party/zlib/contrib/masmx86/gvmat32c.c        |   62 -
 third_party/zlib/contrib/masmx86/inffas32.asm      |   21 +-
 third_party/zlib/contrib/masmx86/mkasm.bat         |    3 -
 third_party/zlib/contrib/masmx86/readme.txt        |   48 +-
 third_party/zlib/contrib/minizip/ChangeLogUnzip    |   67 -
 third_party/zlib/contrib/minizip/crypt.h           |   23 +-
 third_party/zlib/contrib/minizip/ioapi.c           |  228 ++-
 third_party/zlib/contrib/minizip/ioapi.h           |  189 +-
 third_party/zlib/contrib/minizip/iowin32.c         |  391 +++--
 third_party/zlib/contrib/minizip/iowin32.h         |   15 +-
 third_party/zlib/contrib/minizip/miniunz.c         |  173 +-
 third_party/zlib/contrib/minizip/minizip.c         |  158 +-
 third_party/zlib/contrib/minizip/mztools.c         |   54 +-
 third_party/zlib/contrib/minizip/mztools.h         |   14 +-
 third_party/zlib/contrib/minizip/unzip.c           | 1305 +++++++++-----
 third_party/zlib/contrib/minizip/unzip.h           |  137 +-
 third_party/zlib/contrib/minizip/zip.c             | 1844 ++++++++++++++------
 third_party/zlib/contrib/minizip/zip.h             |  175 +-
 third_party/zlib/contrib/pascal/zlibd32.mak        |   20 +-
 third_party/zlib/contrib/pascal/zlibpas.pas        |   42 +-
 third_party/zlib/contrib/puff/Makefile             |   40 +-
 third_party/zlib/contrib/puff/puff.c               |  209 +--
 third_party/zlib/contrib/puff/puff.h               |   10 +-
 third_party/zlib/contrib/puff/zeros.raw            |  Bin 1213 -> 2517 bytes
 third_party/zlib/contrib/testzlib/testzlib.c       |   10 +-
 third_party/zlib/contrib/vstudio/readme.txt        |   42 +-
 .../zlib/contrib/vstudio/vc7/miniunz.vcproj        |  126 --
 .../zlib/contrib/vstudio/vc7/minizip.vcproj        |  126 --
 .../zlib/contrib/vstudio/vc7/testzlib.vcproj       |  126 --
 third_party/zlib/contrib/vstudio/vc7/zlib.rc       |   32 -
 .../zlib/contrib/vstudio/vc7/zlibstat.vcproj       |  246 ---
 third_party/zlib/contrib/vstudio/vc7/zlibvc.def    |   92 -
 third_party/zlib/contrib/vstudio/vc7/zlibvc.sln    |   78 -
 third_party/zlib/contrib/vstudio/vc7/zlibvc.vcproj |  445 -----
 .../zlib/contrib/vstudio/vc8/miniunz.vcproj        |  566 ------
 .../zlib/contrib/vstudio/vc8/minizip.vcproj        |  563 ------
 .../zlib/contrib/vstudio/vc8/testzlib.vcproj       |  948 ----------
 .../zlib/contrib/vstudio/vc8/testzlibdll.vcproj    |  567 ------
 third_party/zlib/contrib/vstudio/vc8/zlib.rc       |   32 -
 .../zlib/contrib/vstudio/vc8/zlibstat.vcproj       |  870 ---------
 third_party/zlib/contrib/vstudio/vc8/zlibvc.def    |   92 -
 third_party/zlib/contrib/vstudio/vc8/zlibvc.sln    |  144 --
 third_party/zlib/contrib/vstudio/vc8/zlibvc.vcproj | 1219 -------------
 third_party/zlib/crc32.c                           |  116 +-
 third_party/zlib/crc32.h                           |    2 +-
 third_party/zlib/deflate.c                         |  523 ++++--
 third_party/zlib/deflate.h                         |   43 +-
 third_party/zlib/example.c                         |  565 ------
 third_party/zlib/examples/README.examples          |   15 +-
 third_party/zlib/examples/fitblk.c                 |    2 +-
 third_party/zlib/examples/gun.c                    |   51 +-
 third_party/zlib/examples/gzappend.c               |   22 +-
 third_party/zlib/examples/gzjoin.c                 |   13 +-
 third_party/zlib/examples/gzlog.c                  | 1304 ++++++++++----
 third_party/zlib/examples/gzlog.h                  |   95 +-
 third_party/zlib/examples/zlib_how.html            |   36 +-
 third_party/zlib/examples/zpipe.c                  |   24 +-
 third_party/zlib/examples/zran.c                   |   13 +-
 third_party/zlib/gzio.c                            | 1024 -----------
 third_party/zlib/infback.c                         |  153 +-
 third_party/zlib/inffast.c                         |   96 +-
 third_party/zlib/inffast.h                         |    4 +-
 third_party/zlib/inffixed.h                        |    6 +-
 third_party/zlib/inflate.c                         |  490 ++++--
 third_party/zlib/inflate.h                         |   33 +-
 third_party/zlib/inftrees.c                        |   93 +-
 third_party/zlib/inftrees.h                        |   27 +-
 third_party/zlib/make_vms.com                      |  748 ++++++--
 third_party/zlib/minigzip.c                        |  322 ----
 third_party/zlib/msdos/Makefile.bor                |   20 +-
 third_party/zlib/msdos/Makefile.dj2                |    4 +-
 third_party/zlib/msdos/Makefile.emx                |    4 +-
 third_party/zlib/msdos/Makefile.msc                |   16 +-
 third_party/zlib/msdos/Makefile.tc                 |   20 +-
 third_party/zlib/old/zlib.html                     |  971 -----------
 third_party/zlib/projects/README.projects          |   41 -
 third_party/zlib/projects/visualc6/README.txt      |   73 -
 third_party/zlib/projects/visualc6/example.dsp     |  278 ---
 third_party/zlib/projects/visualc6/minigzip.dsp    |  278 ---
 third_party/zlib/projects/visualc6/zlib.dsp        |  609 -------
 third_party/zlib/projects/visualc6/zlib.dsw        |   59 -
 third_party/zlib/qnx/package.qpg                   |   10 +-
 third_party/zlib/trees.c                           |  137 +-
 third_party/zlib/trees.h                           |    4 +-
 third_party/zlib/uncompr.c                         |    9 +-
 third_party/zlib/win32/DLL_FAQ.txt                 |    8 +-
 third_party/zlib/win32/Makefile.bor                |   25 +-
 third_party/zlib/win32/Makefile.emx                |   69 -
 third_party/zlib/win32/Makefile.gcc                |  121 +-
 third_party/zlib/win32/Makefile.msc                |  123 +-
 third_party/zlib/win32/zlib.def                    |   32 +-
 third_party/zlib/win32/zlib1.rc                    |   17 +-
 third_party/zlib/zconf.h                           |  292 +++-
 third_party/zlib/zconf.in.h                        |  332 ----
 third_party/zlib/zlib.h                            | 1392 +++++++++------
 third_party/zlib/zutil.c                           |   56 +-
 third_party/zlib/zutil.h                           |  140 +-
 374 files changed, 31279 insertions(+), 19224 deletions(-)
 mode change 100644 => 100755 lib/mimeparse/mimeparse.py
 delete mode 100644 lib/subunit/python/subunit/tests/TestUtil.py
 delete mode 100755 lib/subunit/runtests.py
 delete mode 100644 lib/testtools/README
 create mode 100644 third_party/pexpect/.gitignore
 create mode 100644 third_party/pexpect/.travis.yml
 create mode 100644 third_party/pexpect/ANSI.py
 create mode 100644 third_party/pexpect/DEVELOPERS.rst
 create mode 100644 third_party/pexpect/FSM.py
 create mode 100644 third_party/pexpect/LICENSE
 create mode 100644 third_party/pexpect/MANIFEST.in
 create mode 100644 third_party/pexpect/README.rst
 create mode 100644 third_party/pexpect/doc/FAQ.rst
 create mode 100644 third_party/pexpect/doc/Makefile
 create mode 100644 third_party/pexpect/doc/api/ANSI.rst
 create mode 100644 third_party/pexpect/doc/api/fdpexpect.rst
 create mode 100644 third_party/pexpect/doc/api/index.rst
 create mode 100644 third_party/pexpect/doc/api/pexpect.rst
 create mode 100644 third_party/pexpect/doc/api/pxssh.rst
 create mode 100644 third_party/pexpect/doc/api/replwrap.rst
 create mode 100644 third_party/pexpect/doc/api/screen.rst
 create mode 100644 third_party/pexpect/doc/clean.css
 create mode 100644 third_party/pexpect/doc/commonissues.rst
 create mode 100644 third_party/pexpect/doc/conf.py
 create mode 100644 third_party/pexpect/doc/examples.rst
 create mode 100644 third_party/pexpect/doc/history.rst
 create mode 100644 third_party/pexpect/doc/index.rst
 create mode 100644 third_party/pexpect/doc/install.rst
 create mode 100644 third_party/pexpect/doc/make.bat
 create mode 100644 third_party/pexpect/doc/overview.rst
 create mode 100644 third_party/pexpect/doc/requirements.txt
 create mode 100644 third_party/pexpect/doc/sphinxext/github.py
 create mode 100644 third_party/pexpect/examples/README
 create mode 100755 third_party/pexpect/examples/astat.py
 create mode 100755 third_party/pexpect/examples/cgishell.cgi
 create mode 100755 third_party/pexpect/examples/chess.py
 create mode 100755 third_party/pexpect/examples/chess2.py
 create mode 100755 third_party/pexpect/examples/chess3.py
 create mode 100755 third_party/pexpect/examples/df.py
 create mode 100755 third_party/pexpect/examples/ftp.py
 create mode 100755 third_party/pexpect/examples/hive.py
 create mode 100755 third_party/pexpect/examples/monitor.py
 create mode 100755 third_party/pexpect/examples/passmass.py
 create mode 100755 third_party/pexpect/examples/python.py
 create mode 100755 third_party/pexpect/examples/script.py
 create mode 100755 third_party/pexpect/examples/ssh_tunnel.py
 create mode 100644 third_party/pexpect/examples/table_test.html
 create mode 100755 third_party/pexpect/examples/topip.py
 create mode 100755 third_party/pexpect/examples/uptime.py
 create mode 100644 third_party/pexpect/fdpexpect.py
 create mode 100644 third_party/pexpect/notes/my_forkpty.py
 create mode 100644 third_party/pexpect/notes/notes.txt
 create mode 100644 third_party/pexpect/notes/posixmodule.c.diff
 create mode 100644 third_party/pexpect/pexpect/ANSI.py
 create mode 100644 third_party/pexpect/pexpect/FSM.py
 create mode 100644 third_party/pexpect/pexpect/__init__.py
 create mode 100644 third_party/pexpect/pexpect/async.py
 create mode 100644 third_party/pexpect/pexpect/bashrc.sh
 create mode 100644 third_party/pexpect/pexpect/exceptions.py
 create mode 100644 third_party/pexpect/pexpect/expect.py
 create mode 100644 third_party/pexpect/pexpect/fdpexpect.py
 create mode 100644 third_party/pexpect/pexpect/pty_spawn.py
 create mode 100644 third_party/pexpect/pexpect/pxssh.py
 create mode 100644 third_party/pexpect/pexpect/replwrap.py
 create mode 100644 third_party/pexpect/pexpect/screen.py
 create mode 100644 third_party/pexpect/pexpect/spawnbase.py
 create mode 100644 third_party/pexpect/pexpect/utils.py
 create mode 100644 third_party/pexpect/pxssh.py
 create mode 100644 third_party/pexpect/screen.py
 create mode 100644 third_party/pexpect/setup.cfg
 create mode 100644 third_party/pexpect/setup.py
 create mode 100644 third_party/pexpect/tests/PexpectTestCase.py
 create mode 100644 third_party/pexpect/tests/README
 create mode 100644 third_party/pexpect/tests/TESTDATA.txt
 create mode 100755 third_party/pexpect/tests/__init__.py
 create mode 100755 third_party/pexpect/tests/adhoc.py
 create mode 100644 third_party/pexpect/tests/alarm_die.py
 create mode 100644 third_party/pexpect/tests/bambi.vt
 create mode 100755 third_party/pexpect/tests/depricated_test_filedescriptor.py
 create mode 100644 third_party/pexpect/tests/echo_w_prompt.py
 create mode 100755 third_party/pexpect/tests/echo_wait.py
 create mode 100755 third_party/pexpect/tests/exit1.py
 create mode 100644 third_party/pexpect/tests/exit667.c
 create mode 100755 third_party/pexpect/tests/fakessh/ssh
 create mode 100755 third_party/pexpect/tests/getch.py
 create mode 100644 third_party/pexpect/tests/globe.vt
 create mode 100755 third_party/pexpect/tests/interact.py
 create mode 100644 third_party/pexpect/tests/interact_unicode.py
 create mode 100644 third_party/pexpect/tests/list100.py
 create mode 100755 third_party/pexpect/tests/needs_kill.py
 create mode 100755 third_party/pexpect/tests/pexpectTest.py
 create mode 100644 third_party/pexpect/tests/platform_checks/CSIGNALTEST/test.c
 create mode 100644 third_party/pexpect/tests/platform_checks/README
 create mode 100755 third_party/pexpect/tests/platform_checks/check.py
 create mode 100755 third_party/pexpect/tests/platform_checks/check2.py
 create mode 100755 third_party/pexpect/tests/platform_checks/check_control_terminal.py
 create mode 100755 third_party/pexpect/tests/platform_checks/check_handler.py
 create mode 100755 third_party/pexpect/tests/platform_checks/check_read.py
 create mode 100755 third_party/pexpect/tests/platform_checks/check_signals.py
 create mode 100755 third_party/pexpect/tests/qa.py
 create mode 100755 third_party/pexpect/tests/sigwinch_report.py
 create mode 100755 third_party/pexpect/tests/sleep_for.py
 create mode 100755 third_party/pexpect/tests/swapcase_echo.py
 create mode 100644 third_party/pexpect/tests/test_FSM.py
 create mode 100755 third_party/pexpect/tests/test_ansi.py
 create mode 100644 third_party/pexpect/tests/test_async.py
 create mode 100755 third_party/pexpect/tests/test_command_list_split.py
 create mode 100755 third_party/pexpect/tests/test_constructor.py
 create mode 100755 third_party/pexpect/tests/test_ctrl_chars.py
 create mode 100755 third_party/pexpect/tests/test_destructor.py
 create mode 100755 third_party/pexpect/tests/test_dotall.py
 create mode 100755 third_party/pexpect/tests/test_expect.py
 create mode 100755 third_party/pexpect/tests/test_filedescriptor.py
 create mode 100755 third_party/pexpect/tests/test_interact.py
 create mode 100755 third_party/pexpect/tests/test_isalive.py
 create mode 100755 third_party/pexpect/tests/test_log.py
 create mode 100644 third_party/pexpect/tests/test_maxcanon.py
 create mode 100755 third_party/pexpect/tests/test_misc.py
 create mode 100755 third_party/pexpect/tests/test_missing_command.py
 create mode 100755 third_party/pexpect/tests/test_performance.py
 create mode 100644 third_party/pexpect/tests/test_pickling.py
 create mode 100644 third_party/pexpect/tests/test_pxssh.py
 create mode 100644 third_party/pexpect/tests/test_replwrap.py
 create mode 100644 third_party/pexpect/tests/test_repr.py
 create mode 100755 third_party/pexpect/tests/test_run.py
 create mode 100755 third_party/pexpect/tests/test_run_out_of_pty.py
 create mode 100755 third_party/pexpect/tests/test_screen.py
 create mode 100755 third_party/pexpect/tests/test_timeout_pattern.py
 create mode 100644 third_party/pexpect/tests/test_unicode.py
 create mode 100644 third_party/pexpect/tests/test_which.py
 create mode 100755 third_party/pexpect/tests/test_winsize.py
 create mode 100644 third_party/pexpect/tests/tetris.data
 create mode 100755 third_party/pexpect/tests/ticker.py
 create mode 100644 third_party/pexpect/tests/torturet.vt
 create mode 100644 third_party/pexpect/tests/utils.py
 create mode 100755 third_party/pexpect/tools/display-sighandlers.py
 create mode 100755 third_party/pexpect/tools/display-terminalinfo.py
 create mode 100755 third_party/pexpect/tools/teamcity-coverage-report.sh
 create mode 100755 third_party/pexpect/tools/teamcity-runtests.sh
 delete mode 100644 third_party/zlib/algorithm.txt
 delete mode 100644 third_party/zlib/contrib/asm586/README.586
 delete mode 100644 third_party/zlib/contrib/asm586/match.S
 delete mode 100644 third_party/zlib/contrib/masm686/match.asm
 delete mode 100644 third_party/zlib/contrib/masmx86/gvmat32.asm
 delete mode 100644 third_party/zlib/contrib/masmx86/gvmat32c.c
 delete mode 100755 third_party/zlib/contrib/masmx86/mkasm.bat
 delete mode 100644 third_party/zlib/contrib/minizip/ChangeLogUnzip
 delete mode 100644 third_party/zlib/contrib/vstudio/vc7/miniunz.vcproj
 delete mode 100644 third_party/zlib/contrib/vstudio/vc7/minizip.vcproj
 delete mode 100644 third_party/zlib/contrib/vstudio/vc7/testzlib.vcproj
 delete mode 100644 third_party/zlib/contrib/vstudio/vc7/zlib.rc
 delete mode 100644 third_party/zlib/contrib/vstudio/vc7/zlibstat.vcproj
 delete mode 100644 third_party/zlib/contrib/vstudio/vc7/zlibvc.def
 delete mode 100644 third_party/zlib/contrib/vstudio/vc7/zlibvc.sln
 delete mode 100644 third_party/zlib/contrib/vstudio/vc7/zlibvc.vcproj
 delete mode 100644 third_party/zlib/contrib/vstudio/vc8/miniunz.vcproj
 delete mode 100644 third_party/zlib/contrib/vstudio/vc8/minizip.vcproj
 delete mode 100644 third_party/zlib/contrib/vstudio/vc8/testzlib.vcproj
 delete mode 100644 third_party/zlib/contrib/vstudio/vc8/testzlibdll.vcproj
 delete mode 100644 third_party/zlib/contrib/vstudio/vc8/zlib.rc
 delete mode 100644 third_party/zlib/contrib/vstudio/vc8/zlibstat.vcproj
 delete mode 100644 third_party/zlib/contrib/vstudio/vc8/zlibvc.def
 delete mode 100644 third_party/zlib/contrib/vstudio/vc8/zlibvc.sln
 delete mode 100644 third_party/zlib/contrib/vstudio/vc8/zlibvc.vcproj
 delete mode 100644 third_party/zlib/example.c
 delete mode 100644 third_party/zlib/gzio.c
 delete mode 100644 third_party/zlib/minigzip.c
 delete mode 100644 third_party/zlib/old/zlib.html
 delete mode 100644 third_party/zlib/projects/README.projects
 delete mode 100644 third_party/zlib/projects/visualc6/README.txt
 delete mode 100644 third_party/zlib/projects/visualc6/example.dsp
 delete mode 100644 third_party/zlib/projects/visualc6/minigzip.dsp
 delete mode 100644 third_party/zlib/projects/visualc6/zlib.dsp
 delete mode 100644 third_party/zlib/projects/visualc6/zlib.dsw
 delete mode 100644 third_party/zlib/win32/Makefile.emx
 delete mode 100644 third_party/zlib/zconf.in.h

diff --git a/lib/extras/extras/__init__.py b/lib/extras/extras/__init__.py
index 5f16625..2d34b52 100644
--- a/lib/extras/extras/__init__.py
+++ b/lib/extras/extras/__init__.py
@@ -101,3 +101,5 @@ def safe_hasattr(obj, attr, _marker=object()):
     properties.
     """
     return getattr(obj, attr, _marker) is not _marker
+
+
diff --git a/lib/extras/extras/tests/test_extras.py b/lib/extras/extras/tests/test_extras.py
index 33dc87c..be1ed1c 100644
--- a/lib/extras/extras/tests/test_extras.py
+++ b/lib/extras/extras/tests/test_extras.py
@@ -184,3 +184,5 @@ class TestTryImports(TestCase):
         check_error_callback(self, try_imports,
             ['os.path'],
             0, True)
+
+
diff --git a/lib/mimeparse/mimeparse.py b/lib/mimeparse/mimeparse.py
old mode 100644
new mode 100755
diff --git a/lib/mimeparse/setup.py b/lib/mimeparse/setup.py
index de3e81b..e559f9d 100644
--- a/lib/mimeparse/setup.py
+++ b/lib/mimeparse/setup.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 
-#old way
+#old way 
 from distutils.core import setup
 
 #new way
@@ -11,7 +11,7 @@ setup(name='mimeparse',
       description='A module provides basic functions for parsing mime-type names and matching them against a list of media-ranges.',
       long_description="""
 This module provides basic functions for handling mime-types. It can handle
-matching mime-types against a list of media-ranges. See section 14.1 of
+matching mime-types against a list of media-ranges. See section 14.1 of 
 the HTTP specification [RFC 2616] for a complete explanation.
 
    http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
@@ -48,3 +48,4 @@ Contents:
       license='MIT',
       py_modules=['mimeparse']
       )
+
diff --git a/lib/pep8/pep8.py b/lib/pep8/pep8.py
index b31a978..67b32d1 100755
--- a/lib/pep8/pep8.py
+++ b/lib/pep8/pep8.py
@@ -2,6 +2,7 @@
 # pep8.py - Check Python source code formatting, according to PEP 8
 # Copyright (C) 2006-2009 Johann C. Rocholl <johann at rocholl.net>
 # Copyright (C) 2009-2014 Florent Xicluna <florent.xicluna at gmail.com>
+# Copyright (C) 2014 Ian Lee <ianlee1521 at gmail.com>
 #
 # Permission is hereby granted, free of charge, to any person
 # obtaining a copy of this software and associated documentation files
@@ -46,8 +47,6 @@ W warnings
 """
 from __future__ import with_statement
 
-__version__ = '1.6.0a0'
-
 import os
 import sys
 import re
@@ -63,13 +62,19 @@ try:
 except ImportError:
     from ConfigParser import RawConfigParser
 
-DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__'
-DEFAULT_IGNORE = 'E123,E226,E24,E704'
-if sys.platform == 'win32':
-    DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8')
-else:
-    DEFAULT_CONFIG = os.path.join(os.getenv('XDG_CONFIG_HOME') or
-                                  os.path.expanduser('~/.config'), 'pep8')
+__version__ = '1.6.0a0'
+
+DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox'
+DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704'
+try:
+    if sys.platform == 'win32':
+        DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8')
+    else:
+        DEFAULT_CONFIG = os.path.join(os.getenv('XDG_CONFIG_HOME') or
+                                      os.path.expanduser('~/.config'), 'pep8')
+except ImportError:
+    DEFAULT_CONFIG = None
+
 PROJECT_CONFIG = ('setup.cfg', 'tox.ini', '.pep8')
 TESTSUITE_PATH = os.path.join(os.path.dirname(__file__), 'testsuite')
 MAX_LINE_LENGTH = 79
@@ -101,8 +106,9 @@ ERRORCODE_REGEX = re.compile(r'\b[A-Z]\d{3}\b')
 DOCSTRING_REGEX = re.compile(r'u?r?["\']')
 EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[[({] | []}),;:]')
 WHITESPACE_AFTER_COMMA_REGEX = re.compile(r'[,;:]\s*(?:  |\t)')
-COMPARE_SINGLETON_REGEX = re.compile(r'([=!]=)\s*(None|False|True)')
-COMPARE_NEGATIVE_REGEX = re.compile(r'\b(not)\s+[^[({ ]+\s+(in|is)\s')
+COMPARE_SINGLETON_REGEX = re.compile(r'\b(None|False|True)?\s*([=!]=)'
+                                     r'\s*(?(1)|(None|False|True))\b')
+COMPARE_NEGATIVE_REGEX = re.compile(r'\b(not)\s+[^][)(}{ ]+\s+(in|is)\s')
 COMPARE_TYPE_REGEX = re.compile(r'(?:[=!]=|is(?:\s+not)?)\s*type(?:s.\w+Type'
                                 r'|\s*\(\s*([^)]*[^ )])\s*\))')
 KEYWORD_REGEX = re.compile(r'(\s*)\b(?:%s)\b(\s*)' % r'|'.join(KEYWORDS))
@@ -680,7 +686,7 @@ def missing_whitespace_around_operator(logical_line, tokens):
                 if need_space is True or need_space[1]:
                     # A needed trailing space was not found
                     yield prev_end, "E225 missing whitespace around operator"
-                else:
+                elif prev_text != '**':
                     code, optype = 'E226', 'arithmetic'
                     if prev_text == '%':
                         code, optype = 'E228', 'modulo'
@@ -748,6 +754,7 @@ def whitespace_around_named_parameter_equals(logical_line, tokens):
     Okay: boolean(a != b)
     Okay: boolean(a <= b)
     Okay: boolean(a >= b)
+    Okay: def foo(arg: int = 42):
 
     E251: def complex(real, imag = 0.0):
     E251: return magic(r = real, i = imag)
@@ -755,6 +762,8 @@ def whitespace_around_named_parameter_equals(logical_line, tokens):
     parens = 0
     no_space = False
     prev_end = None
+    annotated_func_arg = False
+    in_def = logical_line.startswith('def')
     message = "E251 unexpected spaces around keyword / parameter equals"
     for token_type, text, start, end, line in tokens:
         if token_type == tokenize.NL:
@@ -763,15 +772,22 @@ def whitespace_around_named_parameter_equals(logical_line, tokens):
             no_space = False
             if start != prev_end:
                 yield (prev_end, message)
-        elif token_type == tokenize.OP:
+        if token_type == tokenize.OP:
             if text == '(':
                 parens += 1
             elif text == ')':
                 parens -= 1
-            elif parens and text == '=':
+            elif in_def and text == ':' and parens == 1:
+                annotated_func_arg = True
+            elif parens and text == ',' and parens == 1:
+                annotated_func_arg = False
+            elif parens and text == '=' and not annotated_func_arg:
                 no_space = True
                 if start != prev_end:
                     yield (prev_end, message)
+            if not parens:
+                annotated_func_arg = False
+
         prev_end = end
 
 
@@ -835,6 +851,56 @@ def imports_on_separate_lines(logical_line):
             yield found, "E401 multiple imports on one line"
 
 
+def module_imports_on_top_of_file(
+        logical_line, indent_level, checker_state, noqa):
+    r"""Imports are always put at the top of the file, just after any module
+    comments and docstrings, and before module globals and constants.
+
+    Okay: import os
+    Okay: # this is a comment\nimport os
+    Okay: '''this is a module docstring'''\nimport os
+    Okay: r'''this is a module docstring'''\nimport os
+    Okay: try:\n    import x\nexcept:\n    pass\nelse:\n    pass\nimport y
+    Okay: try:\n    import x\nexcept:\n    pass\nfinally:\n    pass\nimport y
+    E402: a=1\nimport os
+    E402: 'One string'\n"Two string"\nimport os
+    E402: a=1\nfrom sys import x
+
+    Okay: if x:\n    import os
+    """
+    def is_string_literal(line):
+        if line[0] in 'uUbB':
+            line = line[1:]
+        if line and line[0] in 'rR':
+            line = line[1:]
+        return line and (line[0] == '"' or line[0] == "'")
+
+    allowed_try_keywords = ('try', 'except', 'else', 'finally')
+
+    if indent_level:  # Allow imports in conditional statements or functions
+        return
+    if not logical_line:  # Allow empty lines or comments
+        return
+    if noqa:
+        return
+    line = logical_line
+    if line.startswith('import ') or line.startswith('from '):
+        if checker_state.get('seen_non_imports', False):
+            yield 0, "E402 module level import not at top of file"
+    elif any(line.startswith(kw) for kw in allowed_try_keywords):
+        # Allow try, except, else, finally keywords intermixed with imports in
+        # order to support conditional importing
+        return
+    elif is_string_literal(line):
+        # The first literal is a docstring, allow it. Otherwise, report error.
+        if checker_state.get('seen_docstring', False):
+            checker_state['seen_non_imports'] = True
+        else:
+            checker_state['seen_docstring'] = True
+    else:
+        checker_state['seen_non_imports'] = True
+
+
 def compound_statements(logical_line):
     r"""Compound statements (on the same line) are generally discouraged.
 
@@ -871,8 +937,12 @@ def compound_statements(logical_line):
         if ((before.count('{') <= before.count('}') and   # {'a': 1} (dict)
              before.count('[') <= before.count(']') and   # [1:2] (slice)
              before.count('(') <= before.count(')'))):    # (annotation)
-            if LAMBDA_REGEX.search(before):
-                yield 0, "E731 do not assign a lambda expression, use a def"
+            lambda_kw = LAMBDA_REGEX.search(before)
+            if lambda_kw:
+                before = line[:lambda_kw.start()].rstrip()
+                if before[-1:] == '=' and isidentifier(before[:-1].strip()):
+                    yield 0, ("E731 do not assign a lambda expression, use a "
+                              "def")
                 break
             if before.startswith('def '):
                 yield 0, "E704 multiple statements on one line (def)"
@@ -930,7 +1000,9 @@ def comparison_to_singleton(logical_line, noqa):
 
     Okay: if arg is not None:
     E711: if arg != None:
+    E711: if None == arg:
     E712: if arg == True:
+    E712: if False == arg:
 
     Also, beware of writing if x when you really mean if x is not None --
     e.g. when testing whether a variable or argument that defaults to None was
@@ -939,8 +1011,9 @@ def comparison_to_singleton(logical_line, noqa):
     """
     match = not noqa and COMPARE_SINGLETON_REGEX.search(logical_line)
     if match:
-        same = (match.group(1) == '==')
-        singleton = match.group(2)
+        singleton = match.group(1) or match.group(3)
+        same = (match.group(2) == '==')
+
         msg = "'if cond is %s:'" % (('' if same else 'not ') + singleton)
         if singleton in ('None',):
             code = 'E711'
@@ -949,7 +1022,7 @@ def comparison_to_singleton(logical_line, noqa):
             nonzero = ((singleton == 'True' and same) or
                        (singleton == 'False' and not same))
             msg += " or 'if %scond:'" % ('' if nonzero else 'not ')
-        yield match.start(1), ("%s comparison to %s should be %s" %
+        yield match.start(2), ("%s comparison to %s should be %s" %
                                (code, singleton, msg))
 
 
@@ -1056,7 +1129,7 @@ if '' == ''.encode():
         """Read the source code."""
         with open(filename, 'rU') as f:
             return f.readlines()
-    isidentifier = re.compile(r'[a-zA-Z_]\w*').match
+    isidentifier = re.compile(r'[a-zA-Z_]\w*$').match
     stdin_get_value = sys.stdin.read
 else:
     # Python 3
@@ -1155,10 +1228,13 @@ def normalize_paths(value, parent=os.curdir):
 
     Return a list of absolute paths.
     """
-    if not value or isinstance(value, list):
+    if not value:
+        return []
+    if isinstance(value, list):
         return value
     paths = []
     for path in value.split(','):
+        path = path.strip()
         if '/' in path:
             path = os.path.abspath(os.path.join(parent, path))
         paths.append(path.rstrip('/'))
@@ -1175,14 +1251,12 @@ def filename_match(filename, patterns, default=True):
     return any(fnmatch(filename, pattern) for pattern in patterns)
 
 
+def _is_eol_token(token):
+    return token[0] in NEWLINE or token[4][token[3][1]:].lstrip() == '\\\n'
 if COMMENT_WITH_NL:
-    def _is_eol_token(token):
-        return (token[0] in NEWLINE or
-                (token[0] == tokenize.COMMENT and token[1] == token[4]))
-else:
-    def _is_eol_token(token):
-        return token[0] in NEWLINE
-
+    def _is_eol_token(token, _eol_token=_is_eol_token):
+        return _eol_token(token) or (token[0] == tokenize.COMMENT and
+                                     token[1] == token[4])
 
 ##############################################################################
 # Framework to run all checks
@@ -1239,6 +1313,8 @@ class Checker(object):
         self.hang_closing = options.hang_closing
         self.verbose = options.verbose
         self.filename = filename
+        # Dictionary where a checker can store its custom state.
+        self._checker_states = {}
         if filename is None:
             self.filename = 'stdin'
             self.lines = lines or []
@@ -1294,10 +1370,16 @@ class Checker(object):
             arguments.append(getattr(self, name))
         return check(*arguments)
 
+    def init_checker_state(self, name, argument_names):
+        """ Prepares a custom state for the specific checker plugin."""
+        if 'checker_state' in argument_names:
+            self.checker_state = self._checker_states.setdefault(name, {})
+
     def check_physical(self, line):
         """Run all physical checks on a raw input line."""
         self.physical_line = line
         for name, check, argument_names in self._physical_checks:
+            self.init_checker_state(name, argument_names)
             result = self.run_check(check, argument_names)
             if result is not None:
                 (offset, text) = result
@@ -1342,6 +1424,10 @@ class Checker(object):
         """Build a line from tokens and run all logical checks on it."""
         self.report.increment_logical_line()
         mapping = self.build_tokens_line()
+
+        if not mapping:
+            return
+
         (start_row, start_col) = mapping[0][1]
         start_line = self.lines[start_row - 1]
         self.indent_level = expand_indent(start_line[:start_col])
@@ -1352,6 +1438,7 @@ class Checker(object):
         for name, check, argument_names in self._logical_checks:
             if self.verbose >= 4:
                 print('   ' + name)
+            self.init_checker_state(name, argument_names)
             for offset, text in self.run_check(check, argument_names) or ():
                 if not isinstance(offset, tuple):
                     for token_offset, pos in mapping:
@@ -1789,7 +1876,8 @@ def get_parser(prog='pep8', version=__version__):
     parser.add_option('--select', metavar='errors', default='',
                       help="select errors and warnings (e.g. E,W6)")
     parser.add_option('--ignore', metavar='errors', default='',
-                      help="skip errors and warnings (e.g. E4,W)")
+                      help="skip errors and warnings (e.g. E4,W) "
+                           "(default: %s)" % DEFAULT_IGNORE)
     parser.add_option('--show-source', action='store_true',
                       help="show source code for each error")
     parser.add_option('--show-pep8', action='store_true',
diff --git a/lib/subunit/INSTALL b/lib/subunit/INSTALL
index eeea734..29052eb 100644
--- a/lib/subunit/INSTALL
+++ b/lib/subunit/INSTALL
@@ -14,9 +14,12 @@ Dependencies
 * Python for the filters
 * 'testtools' (On Debian and Ubuntu systems the 'python-testtools' package,
   the testtools package on pypi, or https://launchpad.net/testtools) for
-  the extended test API which permits attachments. Version 0.9.23 or newer is 
+  the extended test API which permits attachments. Version 0.9.30 or newer is
   required. Of particular note, http://testtools.python-hosting.com/ is not
   the testtools you want.
+* 'testscenarios' (On Debian and Ubuntu systems the 'python-testscenarios'
+  package, the 'testscenarios' package on pypi, or
+  https://launchpad.net/testscenarios) for running some of the python unit tests.
 * A C compiler for the C bindings
 * Perl for the Perl tools (including subunit-diff)
 * Check to run the subunit test suite.
diff --git a/lib/subunit/MANIFEST.in b/lib/subunit/MANIFEST.in
index eb98981..4f521dc 100644
--- a/lib/subunit/MANIFEST.in
+++ b/lib/subunit/MANIFEST.in
@@ -1,4 +1,4 @@
-exclude .bzrignore
+exclude .gitignore
 exclude aclocal.m4
 prune autom4te.cache
 prune c
diff --git a/lib/subunit/Makefile.am b/lib/subunit/Makefile.am
index da16020..765ae40 100644
--- a/lib/subunit/Makefile.am
+++ b/lib/subunit/Makefile.am
@@ -1,11 +1,12 @@
 EXTRA_DIST =  \
-	.bzrignore \
+	.gitignore \
 	Apache-2.0 \
 	BSD \
 	INSTALL \
 	Makefile.am \
 	NEWS \
 	README \
+	all_tests.py \
 	c++/README \
 	c/README \
 	c/check-subunit-0.9.3.patch \
@@ -20,21 +21,22 @@ EXTRA_DIST =  \
 	python/iso8601/README.subunit \
 	python/iso8601/setup.py \
 	python/iso8601/test_iso8601.py \
-	python/subunit/tests/TestUtil.py \
 	python/subunit/tests/__init__.py \
 	python/subunit/tests/sample-script.py \
 	python/subunit/tests/sample-two-script.py \
 	python/subunit/tests/test_chunked.py \
 	python/subunit/tests/test_details.py \
+	python/subunit/tests/test_filters.py \
+	python/subunit/tests/test_output_filter.py \
 	python/subunit/tests/test_progress_model.py \
-	python/subunit/tests/test_subunit_filter.py \
 	python/subunit/tests/test_run.py \
+	python/subunit/tests/test_subunit_filter.py \
 	python/subunit/tests/test_subunit_stats.py \
 	python/subunit/tests/test_subunit_tags.py \
 	python/subunit/tests/test_tap2subunit.py \
 	python/subunit/tests/test_test_protocol.py \
+	python/subunit/tests/test_test_protocol2.py \
 	python/subunit/tests/test_test_results.py \
-	runtests.py \
 	setup.py \
 	shell/README \
 	shell/share/subunit.sh \
@@ -47,9 +49,12 @@ ACLOCAL_AMFLAGS = -I m4
 include_subunitdir = $(includedir)/subunit
 
 dist_bin_SCRIPTS = \
+	filters/subunit-1to2 \
+	filters/subunit-2to1 \
 	filters/subunit-filter \
 	filters/subunit-ls \
 	filters/subunit-notify \
+	filters/subunit-output \
 	filters/subunit-stats \
 	filters/subunit-tags \
 	filters/subunit2csv \
@@ -58,8 +63,7 @@ dist_bin_SCRIPTS = \
 	filters/subunit2pyunit \
 	filters/tap2subunit
 
-TESTS_ENVIRONMENT = SHELL_SHARE='$(top_srcdir)/shell/share/' PYTHONPATH='$(abs_top_srcdir)/python':${PYTHONPATH}
-TESTS = runtests.py $(check_PROGRAMS)
+TESTS = $(check_PROGRAMS)
 
 ## install libsubunit.pc
 pcdatadir = $(libdir)/pkgconfig
@@ -75,7 +79,9 @@ pkgpython_PYTHON = \
 	python/subunit/iso8601.py \
 	python/subunit/progress_model.py \
 	python/subunit/run.py \
-	python/subunit/test_results.py
+	python/subunit/v2.py \
+	python/subunit/test_results.py \
+	python/subunit/_output.py
 
 lib_LTLIBRARIES = libsubunit.la
 lib_LTLIBRARIES +=  libcppunit_subunit.la
@@ -87,9 +93,6 @@ include_subunit_HEADERS = \
 check_PROGRAMS = \
 	c/tests/test_child
 
-check_SCRIPTS = \
-	runtests.py
-
 libsubunit_la_SOURCES = \
 	c/lib/child.c \
 	c/include/subunit/child.h
@@ -108,6 +111,9 @@ all-local: perl/Makefile
 
 check-local: perl/Makefile
 	$(MAKE) -C perl check
+	SHELL_SHARE='$(top_srcdir)/shell/share/' \
+	PYTHONPATH='$(abs_top_srcdir)/python':'$(abs_top_srcdir)':${PYTHONPATH} \
+	$(PYTHON) -m testtools.run all_tests.test_suite
 
 clean-local:
 	find . -type f -name "*.pyc" -exec rm {} ';'
diff --git a/lib/subunit/NEWS b/lib/subunit/NEWS
index 081dc5d..f6221a8 100644
--- a/lib/subunit/NEWS
+++ b/lib/subunit/NEWS
@@ -5,6 +5,233 @@ subunit release notes
 NEXT (In development)
 ---------------------
 
+BUGFIXES
+~~~~~~~~
+
+* Unencapsulated strings and encapsulated stdout will be forwarded by
+  subunit-2to1. (Robert Collins, #1400519)
+
+* SUBUNIT_FORMATTER which has not been honoured for years is now removed from 
+  the codebase. (Jelmer Vernooij)
+
+1.0.0
+-----
+
+BUGFIXES
+~~~~~~~~
+
+* Tests have been fixed with testtools 1.2.0 and above.
+  (Robert Collins)
+
+IMPROVEMENTS
+~~~~~~~~~~~~
+
+* With testtools 1.4.0 and above import errors are now
+  shown in detail by ``subunit.run``. (Robert Collins)
+
+0.0.21
+------
+
+BUGFIXES
+~~~~~~~~
+
+* Brown bag bugfix - 0.0.20's setup.py referenced cvs not csv.
+  (Robert Collins, #1361924)
+
+0.0.20
+------
+
+BUGFIXES
+~~~~~~~~
+
+* subunit2csv is now installed when using pip.
+  (Robert Collins, #1279669)
+
+* testscenarios is now a test dependency, not an install dependency.
+  (Arfrever Frehtes Taifersar Arahesis, #1292757)
+
+* The python-subunit tarball can now have setup run from the current
+  directory. (Robert Collins, #1361857)
+
+0.0.19
+------
+
+IMPROVEMENTS
+~~~~~~~~~~~~
+
+* ``subunit.run`` in Python will now exit 0 as long as the test stream has
+  been generated correctly - this has always been the intent but API friction
+  with testtools had prevented it working.
+  (Robert Collins)
+
+0.0.18
+------
+
+IMPROVEMENTS
+~~~~~~~~~~~~
+
+* Fix compatibility with testtools 0.9.35 which dropped the 'all' compat
+  symbol. This breaks support for Python versions lower than 2.6.
+  (Robert Collins, #1274056)
+
+0.0.17
+------
+
+IMPROVEMENTS
+~~~~~~~~~~~~
+
+* Add ``subunit-output`` tool that can generate a Subunit v2 bytestream from
+  arguments passed on the command line. (Thomi Richards, #1252084)
+
+0.0.16
+------
+
+BUG FIXES
+~~~~~~~~~
+
+* Perl files should now honour perl system config.
+  (Benedikt Morbach, #1233198)
+
+* Python 3.1 and 3.2 have an inconsistent memoryview implementation which
+  required a workaround for NUL byte detection. (Robert Collins, #1216246)
+
+* The test suite was failing 6 tests due to testtools changing it's output
+  formatting of exceptions. (Robert Collins)
+
+* V2 parser errors now set appropriate mime types for the encapsulated packet
+  data and the error message. (Robert Collins)
+
+* When tests fail to import ``python subunit.run -l ...`` will now write a 
+  subunit file attachment listing the failed imports and exit 2, rather than
+  listing the stub objects from the importer and exiting 0.
+  (Robert Collins, #1245672)
+
+IMPROVEMENTS
+~~~~~~~~~~~~
+
+* Most filters will now accept a file path argument instead of only reading
+  from stdin. (Robert Collins, #409206)
+
+0.0.15
+------
+
+BUG FIXES
+~~~~~~~~~
+
+* Clients of subunit did not expect memoryview objects in StreamResult events.
+  (Robert Collins)
+
+* Memoryview and struct were mutually incompatible in 2.7.3 and 3.2.
+  (Robert Collins, #1216163)
+
+0.0.14
+------
+
+BUG FIXES
+~~~~~~~~~
+
+* Memoryview detection was broken and thus it's use was never really tested.
+  (Robert Collins, 1216101)
+
+* TestProtocol2's tag tests were set sort order dependent.
+  (Robert Collins, #1025392)
+
+* TestTestProtocols' test_tags_both was set sort order dependent.
+  (Robert Collins, #1025392)
+
+* TestTestProtocols' test_*_details were dictionary sort order dependent.
+  (Robert Collins, #1025392)
+
+* TestSubUnitTags's test_add_tag was also se sort order dependent.
+  (Robert Collins, #1025392)
+
+0.0.13
+------
+
+IMPROVEMENTS
+~~~~~~~~~~~~
+
+* subunit should now build with automake 1.11 again. (Robert Collins)
+
+* `subunit-stats` no longer outputs encapsulated stdout as subunit.
+  (Robert Collins, #1171987)
+
+* The logic for `subunit.run` is now importable via python -
+  `subunit.run.main`. (Robert Collins, #606770)
+
+BUG FIXES
+~~~~~~~~~
+
+* Removed GPL files that were (C) non Subunit Developers - they are
+  incompatible for binary distribution, which affects redistributors.
+  (Robert Collins, #1185591)
+
+0.0.12
+------
+
+BUG FIXES
+~~~~~~~~~
+
+* Subunit v2 packets with both file content and route code were not being
+  parsed correctly - they would incorrectly emit a parser error, due to trying
+  to parse the route code length from the first byes of the file content.
+  (Robert Collins, 1172815)
+
+0.0.11
+------
+
+v2 protocol draft included in this release. The v2 protocol trades off human
+readability for a massive improvement in robustness, the ability to represent
+concurrent tests in a single stream, cheaper parsing, and that provides
+significantly better in-line debugging support and structured forwarding
+of non-test data (such as stdout or stdin data).
+
+This change includes two new filters (subunit-1to2 and subunit-2to1). Use
+these filters to convert old streams to v2 and convert v2 streams to v1.
+
+All the other filters now only parse and emit v2 streams. V2 is still in
+draft format, so if you want to delay and wait for v2 to be finalised, you
+should use subunit-2to1 before any serialisation steps take place.
+With the ability to encapsulate multiple non-test streams, another significant
+cange is that filters which emit subunit now encapsulate any non-subunit they
+encounter, labelling it 'stdout'. This permits multiplexing such streams and
+detangling the stdout streams from each input.
+
+The subunit libraries (Python etc) have not changed their behaviour: they
+still emit v1 from their existing API calls. New API's are being added
+and applications should migrate once their language has those API's available.
+
+IMPROVEMENTS
+~~~~~~~~~~~~
+
+* ``subunit.run`` now replaces sys.stdout to ensure that stdout is unbuffered
+  - without this pdb output is not reliably visible when stdout is a pipe
+  as it usually is. (Robert Collins)
+
+* v2 protocol draft included in this release. (Python implementation only so
+  far). (Robert Collins)
+
+* Two new Python classes -- ``StreamResultToBytes`` and
+  ``ByteStreamToStreamResult`` handle v2 generation and parsing.
+  (Robert Collins)
+
+0.0.10
+------
+
+BUG FIXES
+~~~~~~~~~
+
+* make_stream_binary is now public for reuse. (Robert Collins)
+
+* NAME was not defined in the protocol BNF. (Robert Collins)
+
+* UnsupportedOperation is available in the Python2.6 io library, so ask
+  forgiveness rather than permission for obtaining it. (Robert Collins)
+
+* Streams with no fileno() attribute are now supported, but they are not
+  checked for being in binary mode: be sure to take care of that if using
+  the library yourself. (Robert Collins)
+
 0.0.9
 -----
 
diff --git a/lib/subunit/README b/lib/subunit/README
index 47a9734..76a7418 100644
--- a/lib/subunit/README
+++ b/lib/subunit/README
@@ -1,12 +1,12 @@
 
   subunit: A streaming protocol for test results
-  Copyright (C) 2005-2009 Robert Collins <robertc at robertcollins.net>
+  Copyright (C) 2005-2013 Robert Collins <robertc at robertcollins.net>
 
   Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
   license at the users choice. A copy of both licenses are available in the
   project source as Apache-2.0 and BSD. You may not use this file except in
   compliance with one of these two licences.
-  
+
   Unless required by applicable law or agreed to in writing, software
   distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
@@ -21,9 +21,26 @@
 Subunit
 -------
 
-Subunit is a streaming protocol for test results. The protocol is human
-readable and easily generated and parsed. By design all the components of 
-the protocol conceptually fit into the xUnit TestCase->TestResult interaction.
+Subunit is a streaming protocol for test results.
+
+There are two major revisions of the protocol. Version 1 was trivially human
+readable but had significant defects as far as highly parallel testing was
+concerned - it had no room for doing discovery and execution in parallel,
+required substantial buffering when multiplexing and was fragile - a corrupt
+byte could cause an entire stream to be misparsed. Version 1.1 added
+encapsulation of binary streams which mitigated some of the issues but the
+core remained.
+
+Version 2 shares many of the good characteristics of Version 1 - it can be
+embedded into a regular text stream (e.g. from a build system) and it still
+models xUnit style test execution. It also fixes many of the issues with
+Version 1 - Version 2 can be multiplexed without excessive buffering (in
+time or space), it has a well defined recovery mechanism for dealing with
+corrupted streams (e.g. where two processes write to the same stream
+concurrently, or where the stream generator suffers a bug).
+
+More details on both protocol version s can be found in the 'Protocol' section
+of this document.
 
 Subunit comes with command line filters to process a subunit stream and
 language bindings for python, C, C++ and shell. Bindings are easy to write
@@ -32,11 +49,12 @@ for other languages.
 A number of useful things can be done easily with subunit:
  * Test aggregation: Tests run separately can be combined and then
    reported/displayed together. For instance, tests from different languages
-   can be shown as a seamless whole.
+   can be shown as a seamless whole, and tests running on multiple machines
+   can be aggregated into a single stream through a multiplexer.
  * Test archiving: A test run may be recorded and replayed later.
  * Test isolation: Tests that may crash or otherwise interact badly with each
-   other can be run separately and then aggregated, rather than interfering
-   with each other.
+   other can be run seperately and then aggregated, rather than interfering
+   with each other or requiring an adhoc test->runner reporting protocol.
  * Grid testing: subunit can act as the necessary serialisation and
    deserialiation to get test runs on distributed machines to be reported in
    real time.
@@ -68,20 +86,20 @@ Subunit has excellent Python support: most of the filters and tools are written
 in python and there are facilities for using Subunit to increase test isolation
 seamlessly within a test suite.
 
-One simple way to run an existing python test suite and have it output subunit
-is the module ``subunit.run``::
+The most common way is to run an existing python test suite and have it output
+subunit via the ``subunit.run`` module::
 
   $ python -m subunit.run mypackage.tests.test_suite
- 
+
 For more information on the Python support Subunit offers , please see
-``pydoc subunit``, or the source in ``python/subunit/__init__.py``
+``pydoc subunit``, or the source in ``python/subunit/``
 
 C
 =
 
-Subunit has C bindings to emit the protocol, and comes with a patch for 'check'
-which has been nominally accepted by the 'check' developers. See 'c/README' for
-more details.
+Subunit has C bindings to emit the protocol. The 'check' C unit testing project
+has included subunit support in their project for some years now. See
+'c/README' for more details.
 
 C++
 ===
@@ -92,9 +110,13 @@ CPPUnit is included in the Subunit distribution. See 'c++/README' for details.
 shell
 =====
 
-Similar to C, the shell bindings consist of simple functions to output protocol
-elements, and a patch for adding subunit output to the 'ShUnit' shell test
-runner. See 'shell/README' for details.
+There are two sets of shell tools. There are filters, which accept a subunit
+stream on stdin and output processed data (or a transformed stream) on stdout.
+
+Then there are unittest facilities similar to those for C : shell bindings
+consisting of simple functions to output protocol elements, and a patch for
+adding subunit output to the 'ShUnit' shell test runner. See 'shell/README' for
+details.
 
 Filter recipes
 --------------
@@ -104,9 +126,225 @@ To ignore some failing tests whose root cause is already known::
   subunit-filter --without 'AttributeError.*flavor'
 
 
+The xUnit test model
+--------------------
+
+Subunit implements a slightly modified xUnit test model. The stock standard
+model is that there are tests, which have an id(), can be run, and when run
+start, emit an outcome (like success or failure) and then finish.
+
+Subunit extends this with the idea of test enumeration (find out about tests
+a runner has without running them), tags (allow users to describe tests in
+ways the test framework doesn't apply any semantic value to), file attachments
+(allow arbitrary data to make analysing a failure easy) and timestamps.
+
 The protocol
 ------------
 
+Version 2, or v2 is new and still under development, but is intended to
+supercede version 1 in the very near future. Subunit's bundled tools accept
+only version 2 and only emit version 2, but the new filters subunit-1to2 and
+subunit-2to1 can be used to interoperate with older third party libraries.
+
+Version 2
+=========
+
+Version 2 is a binary protocol consisting of independent packets that can be
+embedded in the output from tools like make - as long as each packet has no
+other bytes mixed in with it (which 'make -j N>1' has a tendency of doing).
+Version 2 is currently in draft form, and early adopters should be willing
+to either discard stored results (if protocol changes are made), or bulk
+convert them back to v1 and then to a newer edition of v2.
+
+The protocol synchronises at the start of the stream, after a packet, or
+after any 0x0A byte. That is, a subunit v2 packet starts after a newline or
+directly after the end of the prior packet.
+
+Subunit is intended to be transported over a reliable streaming protocol such
+as TCP. As such it does not concern itself with out of order delivery of
+packets. However, because of the possibility of corruption due to either
+bugs in the sender, or due to mixed up data from concurrent writes to the same
+fd when being embedded, subunit strives to recover reasonably gracefully from
+damaged data.
+
+A key design goal for Subunit version 2 is to allow processing and multiplexing
+without forcing buffering for semantic correctness, as buffering tends to hide
+hung or otherwise misbehaving tests. That said, limited time based buffering
+for network efficiency is a good idea - this is ultimately implementator
+choice. Line buffering is also discouraged for subunit streams, as dropping
+into a debugger or other tool may require interactive traffic even if line
+buffering would not otherwise be a problem.
+
+In version two there are two conceptual events - a test status event and a file
+attachment event. Events may have timestamps, and the path of multiplexers that
+an event is routed through is recorded to permit sending actions back to the
+source (such as new tests to run or stdin for driving debuggers and other
+interactive input). Test status events are used to enumerate tests, to report
+tests and test helpers as they run. Tests may have tags, used to allow
+tunnelling extra meanings through subunit without requiring parsing of
+arbitrary file attachments. Things that are not standalone tests get marked
+as such by setting the 'Runnable' flag to false. (For instance, individual
+assertions in TAP are not runnable tests, only the top level TAP test script
+is runnable).
+
+File attachments are used to provide rich detail about the nature of a failure.
+File attachments can also be used to encapsulate stdout and stderr both during
+and outside tests.
+
+Most numbers are stored in network byte order - Most Significant Byte first
+encoded using a variation of http://www.dlugosz.com/ZIP2/VLI.html. The first
+byte's top 2 high order bits encode the total number of octets in the number.
+This encoding can encode values from 0 to 2**30-1, enough to encode a
+nanosecond. Numbers that are not variable length encoded are still stored in
+MSB order.
+
+ prefix   octets   max       max
++-------+--------+---------+------------+
+| 00    |      1 |  2**6-1 |         63 |
+| 01    |      2 | 2**14-1 |      16383 |
+| 10    |      3 | 2**22-1 |    4194303 |
+| 11    |      4 | 2**30-1 | 1073741823 |
++-------+--------+---------+------------+
+
+All variable length elements of the packet are stored with a length prefix
+number allowing them to be skipped over for consumers that don't need to
+interpret them.
+
+UTF-8 strings are with no terminating NUL and should not have any embedded NULs
+(implementations SHOULD validate any such strings that they process and take
+some remedial action (such as discarding the packet as corrupt).
+
+In short the structure of a packet is:
+PACKET := SIGNATURE FLAGS PACKET_LENGTH TIMESTAMP? TESTID? TAGS? MIME?
+          FILECONTENT? ROUTING_CODE? CRC32
+
+In more detail...
+
+Packets are identified by a single byte signature - 0xB3, which is never legal
+in a UTF-8 stream as the first byte of a character. 0xB3 starts with the first
+bit set and the second not, which is the UTF-8 signature for a continuation
+byte. 0xB3 was chosen as 0x73 ('s' in ASCII') with the top two bits replaced by
+the 1 and 0 for a continuation byte.
+
+If subunit packets are being embedded in a non-UTF-8 text stream, where 0x73 is
+a legal character, consider either recoding the text to UTF-8, or using
+subunit's 'file' packets to embed the text stream in subunit, rather than the
+other way around.
+
+Following the signature byte comes a 16-bit flags field, which includes a
+4-bit version field - if the version is not 0x2 then the packet cannot be
+read. It is recommended to signal an error at this point (e.g. by emitting
+a synthetic error packet and returning to the top level loop to look for
+new packets, or exiting with an error). If recovery is desired, treat the
+packet signature as an opaque byte and scan for a new synchronisation point.
+NB: Subunit V1 and V2 packets may legitimately included 0xB3 internally,
+as they are an 8-bit safe container format, so recovery from this situation
+may involve an arbitrary number of false positives until an actual packet
+is encountered : and even then it may still be false, failing after passing
+the version check due to coincidence.
+
+Flags are stored in network byte order too.
++-------------------------+------------------------+
+| High byte               | Low byte               |
+| 15 14 13 12 11 10  9  8 | 7  6  5  4  3  2  1  0 |
+| VERSION    |feature bits|                        |
++------------+------------+------------------------+
+
+Valid version values are:
+0x2 - version 2
+
+Feature bits:
+Bit 11 - mask 0x0800 - Test id present.
+Bit 10 - mask 0x0400 - Routing code present.
+Bit  9 - mask 0x0200 - Timestamp present.
+Bit  8 - mask 0x0100 - Test is 'runnable'.
+Bit  7 - mask 0x0080 - Tags are present.
+Bit  6 - mask 0x0040 - File content is present.
+Bit  5 - mask 0x0020 - File MIME type is present.
+Bit  4 - mask 0x0010 - EOF marker.
+Bit  3 - mask 0x0008 - Must be zero in version 2.
+
+Test status gets three bits:
+Bit 2 | Bit 1 | Bit 0 - mask 0x0007 - A test status enum lookup:
+000 - undefined / no test
+001 - Enumeration / existence
+002 - In progress
+003 - Success
+004 - Unexpected Success
+005 - Skipped
+006 - Failed
+007 - Expected failure
+
+After the flags field is a number field giving the length in bytes for the
+entire packet including the signature and the checksum. This length must
+be less than 4MiB - 4194303 bytes. The encoding can obviously record a larger
+number but one of the goals is to avoid requiring large buffers, or causing
+large latency in the packet forward/processing pipeline. Larger file
+attachments can be communicated in multiple packets, and the overhead in such a
+4MiB packet is approximately 0.2%.
+
+The rest of the packet is a series of optional features as specified by the set
+feature bits in the flags field. When absent they are entirely absent.
+
+Forwarding and multiplexing of packets can be done without interpreting the
+remainder of the packet until the routing code and checksum (which are both at
+the end of the packet). Additionally, routers can often avoid copying or moving
+the bulk of the packet, as long as the routing code size increase doesn't force
+the length encoding to take up a new byte (which will only happen to packets
+less than or equal to 16KiB in length) - large packets are very efficient to
+route.
+
+Timestamp when present is a 32 bit unsigned integer for secnods, and a variable
+length number for nanoseconds, representing UTC time since Unix Epoch in
+seconds and nanoseconds.
+
+Test id when present is a UTF-8 string. The test id should uniquely identify
+runnable tests such that they can be selected individually. For tests and other
+actions which cannot be individually run (such as test
+fixtures/layers/subtests) uniqueness is not required (though being human
+meaningful is highly recommended).
+
+Tags when present is a length prefixed vector of UTF-8 strings, one per tag.
+There are no restrictions on tag content (other than the restrictions on UTF-8
+strings in subunit in general). Tags have no ordering.
+
+When a MIME type is present, it defines the MIME type for the file across all
+packets same file (routing code + testid + name uniquely identifies a file,
+reset when EOF is flagged). If a file never has a MIME type set, it should be
+treated as application/octet-stream.
+
+File content when present is a UTF-8 string for the name followed by the length
+in bytes of the content, and then the content octets.
+
+If present routing code is a UTF-8 string. The routing code is used to
+determine which test backend a test was running on when doing data analysis,
+and to route stdin to the test process if interaction is required.
+
+Multiplexers SHOULD add a routing code if none is present, and prefix any
+existing routing code with a routing code ('/' separated) if one is already
+present. For example, a multiplexer might label each stream it is multiplexing
+with a simple ordinal ('0', '1' etc), and given an incoming packet with route
+code '3' from stream '0' would adjust the route code when forwarding the packet
+to be '0/3'.
+
+Following the end of the packet is a CRC-32 checksum of the contents of the
+packet including the signature.
+
+Example packets
+~~~~~~~~~~~~~~~
+
+Trivial test "foo" enumeration packet, with test id, runnable set,
+status=enumeration. Spaces below are to visually break up signature / flags /
+length / testid / crc32
+
+b3 2901 0c 03666f6f 08555f1b
+
+
+Version 1 (and 1.1)
+===================
+
+Version 1 (and 1.1) are mostly human readable protocols.
+
 Sample subunit wire contents
 ----------------------------
 
@@ -163,6 +401,7 @@ tags: [-]TAG ...
 time: YYYY-MM-DD HH:MM:SSZ
 
 LABEL: UTF8*
+NAME: UTF8*
 DETAILS ::= BRACKETED | MULTIPART
 BRACKETED ::= '[' CR UTF8-lines ']' CR
 MULTIPART ::= '[ multipart' CR PART* ']' CR
@@ -223,7 +462,9 @@ Releases
 ========
 
 * Update versions in configure.ac and python/subunit/__init__.py.
-* Make PyPI and regular tarball releases. Upload the regular one to LP, the
-  PyPI one to PyPI.
+* Update NEWS.
+* Do a make distcheck, which will update Makefile etc.
+* Do a PyPI release: PYTHONPATH=../../python python ../../setup.py sdist bdist_wheel upload -s
+* Upload the regular one to LP.
 * Push a tagged commit.
 
diff --git a/lib/subunit/configure.ac b/lib/subunit/configure.ac
index cf21d55..47071c5 100644
--- a/lib/subunit/configure.ac
+++ b/lib/subunit/configure.ac
@@ -1,6 +1,6 @@
-m4_define([SUBUNIT_MAJOR_VERSION], [0])
+m4_define([SUBUNIT_MAJOR_VERSION], [1])
 m4_define([SUBUNIT_MINOR_VERSION], [0])
-m4_define([SUBUNIT_MICRO_VERSION], [9])
+m4_define([SUBUNIT_MICRO_VERSION], [0])
 m4_define([SUBUNIT_VERSION],
 m4_defn([SUBUNIT_MAJOR_VERSION]).m4_defn([SUBUNIT_MINOR_VERSION]).m4_defn([SUBUNIT_MICRO_VERSION]))
 AC_PREREQ([2.59])
@@ -19,6 +19,7 @@ AC_SUBST([SUBUNIT_VERSION])
 AC_USE_SYSTEM_EXTENSIONS
 AC_PROG_CC
 AC_PROG_CXX
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
 AM_PROG_CC_C_O
 AC_PROG_INSTALL
 AC_PROG_LN_S
diff --git a/lib/subunit/filters/subunit-filter b/lib/subunit/filters/subunit-filter
index 6a1ecc9..e9e2bb0 100755
--- a/lib/subunit/filters/subunit-filter
+++ b/lib/subunit/filters/subunit-filter
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #  subunit: extensions to python unittest to get test results from subprocesses.
-#  Copyright (C) 2008  Robert Collins <robertc at robertcollins.net>
+#  Copyright (C) 200-2013  Robert Collins <robertc at robertcollins.net>
 #            (C) 2009  Martin Pool
 #
 #  Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
@@ -30,13 +30,15 @@ from optparse import OptionParser
 import sys
 import re
 
+from testtools import ExtendedToStreamDecorator, StreamToExtendedDecorator
+
 from subunit import (
     DiscardStream,
     ProtocolTestCase,
-    TestProtocolClient,
+    StreamResultToBytes,
     read_test_list,
     )
-from subunit.filters import filter_by_result
+from subunit.filters import filter_by_result, find_stream
 from subunit.test_results import (
     and_predicates,
     make_tag_filter,
@@ -55,9 +57,11 @@ def make_options(description):
     parser.add_option("-f", "--no-failure", action="store_true",
         help="exclude failures", dest="failure")
     parser.add_option("--passthrough", action="store_false",
-        help="Show all non subunit input.", default=False, dest="no_passthrough")
+        help="Forward non-subunit input as 'stdout'.", default=False,
+        dest="no_passthrough")
     parser.add_option("--no-passthrough", action="store_true",
-        help="Hide all non subunit input.", default=False, dest="no_passthrough")
+        help="Discard all non subunit input.", default=False,
+        dest="no_passthrough")
     parser.add_option("-s", "--success", action="store_false",
         help="include successes", dest="success")
     parser.add_option("--no-success", action="store_true",
@@ -126,15 +130,16 @@ def _make_result(output, options, predicate):
     fixup_expected_failures = set()
     for path in options.fixup_expected_failures or ():
         fixup_expected_failures.update(read_test_list(path))
-    return TestResultFilter(
-        TestProtocolClient(output),
+    return StreamToExtendedDecorator(TestResultFilter(
+        ExtendedToStreamDecorator(
+        StreamResultToBytes(output)),
         filter_error=options.error,
         filter_failure=options.failure,
         filter_success=options.success,
         filter_skip=options.skip,
         filter_xfail=options.xfail,
         filter_predicate=predicate,
-        fixup_expected_failures=fixup_expected_failures)
+        fixup_expected_failures=fixup_expected_failures))
 
 
 def main():
@@ -150,7 +155,9 @@ def main():
         lambda output_to: _make_result(sys.stdout, options, filter_predicate),
         output_path=None,
         passthrough=(not options.no_passthrough),
-        forward=False)
+        forward=False,
+        protocol_version=2,
+        input_stream=find_stream(sys.stdin, args))
     sys.exit(0)
 
 
diff --git a/lib/subunit/filters/subunit-ls b/lib/subunit/filters/subunit-ls
index 82db4c3..8c6a1e7 100755
--- a/lib/subunit/filters/subunit-ls
+++ b/lib/subunit/filters/subunit-ls
@@ -19,9 +19,14 @@
 from optparse import OptionParser
 import sys
 
-from subunit import DiscardStream, ProtocolTestCase
+from testtools import (
+    CopyStreamResult, StreamToExtendedDecorator, StreamResultRouter,
+    StreamSummary)
+
+from subunit import ByteStreamToStreamResult
+from subunit.filters import find_stream, run_tests_from_stream
 from subunit.test_results import (
-    AutoTimingTestResultDecorator,
+    CatFiles,
     TestIdPrintingResult,
     )
 
@@ -30,18 +35,25 @@ parser = OptionParser(description=__doc__)
 parser.add_option("--times", action="store_true",
     help="list the time each test took (requires a timestamped stream)",
         default=False)
+parser.add_option("--exists", action="store_true",
+    help="list tests that are reported as existing (as well as ran)",
+        default=False)
 parser.add_option("--no-passthrough", action="store_true",
     help="Hide all non subunit input.", default=False, dest="no_passthrough")
 (options, args) = parser.parse_args()
-result = AutoTimingTestResultDecorator(
-    TestIdPrintingResult(sys.stdout, options.times))
-if options.no_passthrough:
-    passthrough_stream = DiscardStream()
-else:
-    passthrough_stream = None
-test = ProtocolTestCase(sys.stdin, passthrough=passthrough_stream)
+test = ByteStreamToStreamResult(
+    find_stream(sys.stdin, args), non_subunit_name="stdout")
+result = TestIdPrintingResult(sys.stdout, options.times, options.exists)
+if not options.no_passthrough:
+    result = StreamResultRouter(result)
+    cat = CatFiles(sys.stdout)
+    result.add_rule(cat, 'test_id', test_id=None)
+summary = StreamSummary()
+result = CopyStreamResult([result, summary])
+result.startTestRun()
 test.run(result)
-if result.wasSuccessful():
+result.stopTestRun()
+if summary.wasSuccessful():
     exit_code = 0
 else:
     exit_code = 1
diff --git a/lib/subunit/filters/subunit-notify b/lib/subunit/filters/subunit-notify
index 8cce2d1..bc833da 100755
--- a/lib/subunit/filters/subunit-notify
+++ b/lib/subunit/filters/subunit-notify
@@ -19,6 +19,7 @@
 import pygtk
 pygtk.require('2.0')
 import pynotify
+from testtools import StreamToExtendedDecorator
 
 from subunit import TestResultStats
 from subunit.filters import run_filter_script
@@ -28,6 +29,7 @@ if not pynotify.init("Subunit-notify"):
 
 
 def notify_of_result(result):
+    result = result.decorated
     if result.failed_tests > 0:
         summary = "Test run failed"
     else:
@@ -41,4 +43,6 @@ def notify_of_result(result):
     nw.show()
 
 
-run_filter_script(TestResultStats, __doc__, notify_of_result)
+run_filter_script(
+    lambda output:StreamToExtendedDecorator(TestResultStats(output)),
+    __doc__, notify_of_result, protocol_version=2)
diff --git a/lib/subunit/filters/subunit-stats b/lib/subunit/filters/subunit-stats
index 4734988..79733b0 100755
--- a/lib/subunit/filters/subunit-stats
+++ b/lib/subunit/filters/subunit-stats
@@ -16,26 +16,17 @@
 
 """Filter a subunit stream to get aggregate statistics."""
 
-from optparse import OptionParser
 import sys
-import unittest
 
-from subunit import DiscardStream, ProtocolTestCase, TestResultStats
+from testtools import StreamToExtendedDecorator
+
+from subunit import TestResultStats
+from subunit.filters import run_filter_script
+
 
-parser = OptionParser(description=__doc__)
-parser.add_option("--no-passthrough", action="store_true",
-    help="Hide all non subunit input.", default=False, dest="no_passthrough")
-(options, args) = parser.parse_args()
 result = TestResultStats(sys.stdout)
-if options.no_passthrough:
-    passthrough_stream = DiscardStream()
-else:
-    passthrough_stream = None
-test = ProtocolTestCase(sys.stdin, passthrough=passthrough_stream)
-test.run(result)
-result.formatStats()
-if result.wasSuccessful():
-    exit_code = 0
-else:
-    exit_code = 1
-sys.exit(exit_code)
+def show_stats(r):
+    r.decorated.formatStats()
+run_filter_script(
+    lambda output:StreamToExtendedDecorator(result),
+    __doc__, show_stats, protocol_version=2, passthrough_subunit=False)
diff --git a/lib/subunit/filters/subunit-tags b/lib/subunit/filters/subunit-tags
index edbbfce..1022492 100755
--- a/lib/subunit/filters/subunit-tags
+++ b/lib/subunit/filters/subunit-tags
@@ -23,4 +23,5 @@ subunit-tags foo -bar -> adds foo and removes bar
 import sys
 
 from subunit import tag_stream
+
 sys.exit(tag_stream(sys.stdin, sys.stdout, sys.argv[1:]))
diff --git a/lib/subunit/filters/subunit2csv b/lib/subunit/filters/subunit2csv
index 14620ff..4adf5cd 100755
--- a/lib/subunit/filters/subunit2csv
+++ b/lib/subunit/filters/subunit2csv
@@ -16,8 +16,11 @@
 
 """Turn a subunit stream into a CSV"""
 
+from testtools import StreamToExtendedDecorator
+
 from subunit.filters import run_filter_script
 from subunit.test_results import CsvResult
 
 
-run_filter_script(CsvResult, __doc__)
+run_filter_script(lambda output:StreamToExtendedDecorator(CsvResult(output)),
+    __doc__, protocol_version=2)
diff --git a/lib/subunit/filters/subunit2gtk b/lib/subunit/filters/subunit2gtk
index c2cb2de..78b4309 100755
--- a/lib/subunit/filters/subunit2gtk
+++ b/lib/subunit/filters/subunit2gtk
@@ -46,17 +46,20 @@
 """Display a subunit stream in a gtk progress window."""
 
 import sys
+import threading
 import unittest
 
 import pygtk
 pygtk.require('2.0')
 import gtk, gtk.gdk, gobject
 
+from testtools import StreamToExtendedDecorator
+
 from subunit import (
     PROGRESS_POP,
     PROGRESS_PUSH,
     PROGRESS_SET,
-    TestProtocolServer,
+    ByteStreamToStreamResult,
     )
 from subunit.progress_model import  ProgressModel
 
@@ -139,6 +142,9 @@ class GTKTestResult(unittest.TestResult):
 
     def stopTest(self, test):
         super(GTKTestResult, self).stopTest(test)
+        gobject.idle_add(self._stopTest)
+
+    def _stopTest(self):
         self.progress_model.advance()
         if self.progress_model.width() == 0:
             self.pbar.pulse()
@@ -153,26 +159,26 @@ class GTKTestResult(unittest.TestResult):
             super(GTKTestResult, self).stopTestRun()
         except AttributeError:
             pass
-        self.pbar.set_text('Finished')
+        gobject.idle_add(self.pbar.set_text, 'Finished')
 
     def addError(self, test, err):
         super(GTKTestResult, self).addError(test, err)
-        self.update_counts()
+        gobject.idle_add(self.update_counts)
 
     def addFailure(self, test, err):
         super(GTKTestResult, self).addFailure(test, err)
-        self.update_counts()
+        gobject.idle_add(self.update_counts)
 
     def addSuccess(self, test):
         super(GTKTestResult, self).addSuccess(test)
-        self.update_counts()
+        gobject.idle_add(self.update_counts)
 
     def addSkip(self, test, reason):
         # addSkip is new in Python 2.7/3.1
         addSkip = getattr(super(GTKTestResult, self), 'addSkip', None)
         if callable(addSkip):
             addSkip(test, reason)
-        self.update_counts()
+        gobject.idle_add(self.update_counts)
 
     def addExpectedFailure(self, test, err):
         # addExpectedFailure is new in Python 2.7/3.1
@@ -180,7 +186,7 @@ class GTKTestResult(unittest.TestResult):
             'addExpectedFailure', None)
         if callable(addExpectedFailure):
             addExpectedFailure(test, err)
-        self.update_counts()
+        gobject.idle_add(self.update_counts)
 
     def addUnexpectedSuccess(self, test):
         # addUnexpectedSuccess is new in Python 2.7/3.1
@@ -188,7 +194,7 @@ class GTKTestResult(unittest.TestResult):
             'addUnexpectedSuccess', None)
         if callable(addUnexpectedSuccess):
             addUnexpectedSuccess(test)
-        self.update_counts()
+        gobject.idle_add(self.update_counts)
 
     def progress(self, offset, whence):
         if whence == PROGRESS_PUSH:
@@ -212,47 +218,22 @@ class GTKTestResult(unittest.TestResult):
         self.ok_label.set_text(str(self.testsRun - bad))
         self.not_ok_label.set_text(str(bad))
 
-
-class GIOProtocolTestCase(object):
-
-    def __init__(self, stream, result, on_finish):
-        self.stream = stream
-        self.schedule_read()
-        self.hup_id = gobject.io_add_watch(stream, gobject.IO_HUP, self.hup)
-        self.protocol = TestProtocolServer(result)
-        self.on_finish = on_finish
-
-    def read(self, source, condition, all=False):
-        #NB: \o/ actually blocks
-        line = source.readline()
-        if not line:
-            self.protocol.lostConnection()
-            self.on_finish()
-            return False
-        self.protocol.lineReceived(line)
-        # schedule more IO shortly - if we say we're willing to do it
-        # immediately we starve things.
-        if not all:
-            source_id = gobject.timeout_add(1, self.schedule_read)
-            return False
-        else:
-            return True
-
-    def schedule_read(self):
-        self.read_id = gobject.io_add_watch(self.stream, gobject.IO_IN, self.read)
-
-    def hup(self, source, condition):
-        while self.read(source, condition, all=True): pass
-        self.protocol.lostConnection()
-        gobject.source_remove(self.read_id)
-        self.on_finish()
-        return False
-
-
-result = GTKTestResult()
-test = GIOProtocolTestCase(sys.stdin, result, result.stopTestRun)
+gobject.threads_init()
+result = StreamToExtendedDecorator(GTKTestResult())
+test = ByteStreamToStreamResult(sys.stdin, non_subunit_name='stdout')
+# Get setup
+while gtk.events_pending():
+  gtk.main_iteration()
+# Start IO
+def run_and_finish():
+    test.run(result)
+    result.stopTestRun()
+t = threading.Thread(target=run_and_finish)
+t.daemon = True
+result.startTestRun()
+t.start()
 gtk.main()
-if result.wasSuccessful():
+if result.decorated.wasSuccessful():
     exit_code = 0
 else:
     exit_code = 1
diff --git a/lib/subunit/filters/subunit2junitxml b/lib/subunit/filters/subunit2junitxml
index d568c71..8e827d5 100755
--- a/lib/subunit/filters/subunit2junitxml
+++ b/lib/subunit/filters/subunit2junitxml
@@ -18,6 +18,9 @@
 
 
 import sys
+
+from testtools import StreamToExtendedDecorator
+
 from subunit.filters import run_filter_script
 
 try:
@@ -28,4 +31,6 @@ except ImportError:
     raise
 
 
-run_filter_script(JUnitXmlResult, __doc__)
+run_filter_script(
+    lambda output:StreamToExtendedDecorator(JUnitXmlResult(output)), __doc__,
+    protocol_version=2)
diff --git a/lib/subunit/filters/subunit2pyunit b/lib/subunit/filters/subunit2pyunit
index 83a23d1..d10ceea 100755
--- a/lib/subunit/filters/subunit2pyunit
+++ b/lib/subunit/filters/subunit2pyunit
@@ -16,11 +16,16 @@
 
 """Display a subunit stream through python's unittest test runner."""
 
+from operator import methodcaller
 from optparse import OptionParser
 import sys
 import unittest
 
-from subunit import DiscardStream, ProtocolTestCase, TestProtocolServer
+from testtools import StreamToExtendedDecorator, DecorateTestCaseResult, StreamResultRouter
+
+from subunit import ByteStreamToStreamResult
+from subunit.filters import find_stream
+from subunit.test_results import CatFiles
 
 parser = OptionParser(description=__doc__)
 parser.add_option("--no-passthrough", action="store_true",
@@ -29,11 +34,17 @@ parser.add_option("--progress", action="store_true",
     help="Use bzrlib's test reporter (requires bzrlib)",
         default=False)
 (options, args) = parser.parse_args()
-if options.no_passthrough:
-    passthrough_stream = DiscardStream()
-else:
-    passthrough_stream = None
-test = ProtocolTestCase(sys.stdin, passthrough=passthrough_stream)
+test = ByteStreamToStreamResult(
+    find_stream(sys.stdin, args), non_subunit_name='stdout')
+def wrap_result(result):
+    result = StreamToExtendedDecorator(result)
+    if not options.no_passthrough:
+        result = StreamResultRouter(result)
+        result.add_rule(CatFiles(sys.stdout), 'test_id', test_id=None)
+    return result
+test = DecorateTestCaseResult(test, wrap_result,
+    before_run=methodcaller('startTestRun'),
+    after_run=methodcaller('stopTestRun'))
 if options.progress:
     from bzrlib.tests import TextTestRunner
     from bzrlib import ui
diff --git a/lib/subunit/perl/Makefile.PL.in b/lib/subunit/perl/Makefile.PL.in
index cf5e6c4..90a6a5e 100755
--- a/lib/subunit/perl/Makefile.PL.in
+++ b/lib/subunit/perl/Makefile.PL.in
@@ -1,6 +1,6 @@
 use ExtUtils::MakeMaker;
 WriteMakefile(
-    'INSTALL_BASE' => '@prefix@',
+    'PREFIX' => '@prefix@',
     'NAME'	=> 'Subunit',
     'VERSION' => '@SUBUNIT_VERSION@',
     'test' => { 'TESTS' => 'tests/*.pl' },
@@ -12,7 +12,7 @@ sub MY::postamble {
 check: # test
 
 uninstall_distcheck:
-	rm -fr $(DESTINSTALLARCHLIB)
+	find $(DESTDIR)$(INSTALLSITEARCH) -type f -exec rm {} \; 
 	rm MYMETA.yml
 
 VPATH = @srcdir@
diff --git a/lib/subunit/python/subunit/__init__.py b/lib/subunit/python/subunit/__init__.py
index 42dcf29..bfa27a1 100644
--- a/lib/subunit/python/subunit/__init__.py
+++ b/lib/subunit/python/subunit/__init__.py
@@ -121,31 +121,25 @@ import re
 import subprocess
 import sys
 import unittest
-if sys.version_info > (3, 0):
+try:
     from io import UnsupportedOperation as _UnsupportedOperation
-else:
+except ImportError:
     _UnsupportedOperation = AttributeError
 
-
+from extras import safe_hasattr
 from testtools import content, content_type, ExtendedToOriginalDecorator
 from testtools.content import TracebackContent
 from testtools.compat import _b, _u, BytesIO, StringIO
 try:
     from testtools.testresult.real import _StringException
     RemoteException = _StringException
-    # For testing: different pythons have different str() implementations.
-    if sys.version_info > (3, 0):
-        _remote_exception_str = "testtools.testresult.real._StringException"
-        _remote_exception_str_chunked = "34\r\n" + _remote_exception_str
-    else:
-        _remote_exception_str = "_StringException" 
-        _remote_exception_str_chunked = "1A\r\n" + _remote_exception_str
 except ImportError:
     raise ImportError ("testtools.testresult.real does not contain "
         "_StringException, check your version.")
-from testtools import testresult
+from testtools import testresult, CopyStreamResult
 
 from subunit import chunked, details, iso8601, test_results
+from subunit.v2 import ByteStreamToStreamResult, StreamResultToBytes
 
 # same format as sys.version_info: "A tuple containing the five components of
 # the version number: major, minor, micro, releaselevel, and serial. All
@@ -159,7 +153,7 @@ from subunit import chunked, details, iso8601, test_results
 # If the releaselevel is 'final', then the tarball will be major.minor.micro.
 # Otherwise it is major.minor.micro~$(revno).
 
-__version__ = (0, 0, 9, 'final', 0)
+__version__ = (1, 0, 0, 'final', 0)
 
 PROGRESS_SET = 0
 PROGRESS_CUR = 1
@@ -624,7 +618,7 @@ class TestProtocolClient(testresult.TestResult):
 
     def __init__(self, stream):
         testresult.TestResult.__init__(self)
-        stream = _make_stream_binary(stream)
+        stream = make_stream_binary(stream)
         self._stream = stream
         self._progress_fmt = _b("progress: ")
         self._bytes_eol = _b("\n")
@@ -921,7 +915,7 @@ class ExecTestCase(unittest.TestCase):
         protocol = TestProtocolServer(result)
         process = subprocess.Popen(self.script, shell=True,
             stdout=subprocess.PIPE)
-        _make_stream_binary(process.stdout)
+        make_stream_binary(process.stdout)
         output = process.communicate()[0]
         protocol.readFrom(BytesIO(output))
 
@@ -992,44 +986,51 @@ def run_isolated(klass, self, result):
     return result
 
 
-def TAP2SubUnit(tap, subunit):
+def TAP2SubUnit(tap, output_stream):
     """Filter a TAP pipe into a subunit pipe.
 
-    :param tap: A tap pipe/stream/file object.
+    This should be invoked once per TAP script, as TAP scripts get
+    mapped to a single runnable case with multiple components.
+
+    :param tap: A tap pipe/stream/file object - should emit unicode strings.
     :param subunit: A pipe/stream/file object to write subunit results to.
     :return: The exit code to exit with.
     """
+    output = StreamResultToBytes(output_stream)
+    UTF8_TEXT = 'text/plain; charset=UTF8'
     BEFORE_PLAN = 0
     AFTER_PLAN = 1
     SKIP_STREAM = 2
     state = BEFORE_PLAN
     plan_start = 1
     plan_stop = 0
-    def _skipped_test(subunit, plan_start):
-        # Some tests were skipped.
-        subunit.write('test test %d\n' % plan_start)
-        subunit.write('error test %d [\n' % plan_start)
-        subunit.write('test missing from TAP output\n')
-        subunit.write(']\n')
-        return plan_start + 1
     # Test data for the next test to emit
     test_name = None
     log = []
     result = None
+    def missing_test(plan_start):
+        output.status(test_id='test %d' % plan_start,
+            test_status='fail', runnable=False, 
+            mime_type=UTF8_TEXT, eof=True, file_name="tap meta",
+            file_bytes=b"test missing from TAP output")
     def _emit_test():
         "write out a test"
         if test_name is None:
             return
-        subunit.write("test %s\n" % test_name)
-        if not log:
-            subunit.write("%s %s\n" % (result, test_name))
-        else:
-            subunit.write("%s %s [\n" % (result, test_name))
         if log:
-            for line in log:
-                subunit.write("%s\n" % line)
-            subunit.write("]\n")
+            log_bytes = b'\n'.join(log_line.encode('utf8') for log_line in log)
+            mime_type = UTF8_TEXT
+            file_name = 'tap comment'
+            eof = True
+        else:
+            log_bytes = None
+            mime_type = None
+            file_name = None
+            eof = True
         del log[:]
+        output.status(test_id=test_name, test_status=result,
+            file_bytes=log_bytes, mime_type=mime_type, eof=eof,
+            file_name=file_name, runnable=False)
     for line in tap:
         if state == BEFORE_PLAN:
             match = re.match("(\d+)\.\.(\d+)\s*(?:\#\s+(.*))?\n", line)
@@ -1040,10 +1041,9 @@ def TAP2SubUnit(tap, subunit):
                 if plan_start > plan_stop and plan_stop == 0:
                     # skipped file
                     state = SKIP_STREAM
-                    subunit.write("test file skip\n")
-                    subunit.write("skip file skip [\n")
-                    subunit.write("%s\n" % comment)
-                    subunit.write("]\n")
+                    output.status(test_id='file skip', test_status='skip',
+                        file_bytes=comment.encode('utf8'), eof=True,
+                        file_name='tap comment')
                 continue
         # not a plan line, or have seen one before
         match = re.match("(ok|not ok)(?:\s+(\d+)?)?(?:\s+([^#]*[^#\s]+)\s*)?(?:\s+#\s+(TODO|SKIP|skip|todo)(?:\s+(.*))?)?\n", line)
@@ -1054,7 +1054,7 @@ def TAP2SubUnit(tap, subunit):
             if status == 'ok':
                 result = 'success'
             else:
-                result = "failure"
+                result = "fail"
             if description is None:
                 description = ''
             else:
@@ -1069,7 +1069,8 @@ def TAP2SubUnit(tap, subunit):
             if number is not None:
                 number = int(number)
                 while plan_start < number:
-                    plan_start = _skipped_test(subunit, plan_start)
+                    missing_test(plan_start)
+                    plan_start += 1
             test_name = "test %d%s" % (plan_start, description)
             plan_start += 1
             continue
@@ -1082,18 +1083,21 @@ def TAP2SubUnit(tap, subunit):
                 extra = ' %s' % reason
             _emit_test()
             test_name = "Bail out!%s" % extra
-            result = "error"
+            result = "fail"
             state = SKIP_STREAM
             continue
         match = re.match("\#.*\n", line)
         if match:
             log.append(line[:-1])
             continue
-        subunit.write(line)
+        # Should look at buffering status and binding this to the prior result.
+        output.status(file_bytes=line.encode('utf8'), file_name='stdout',
+            mime_type=UTF8_TEXT)
     _emit_test()
     while plan_start <= plan_stop:
         # record missed tests
-        plan_start = _skipped_test(subunit, plan_start)
+        missing_test(plan_start)
+        plan_start += 1
     return 0
 
 
@@ -1121,24 +1125,21 @@ def tag_stream(original, filtered, tags):
     :return: 0
     """
     new_tags, gone_tags = tags_to_new_gone(tags)
-    def write_tags(new_tags, gone_tags):
-        if new_tags or gone_tags:
-            filtered.write("tags: " + ' '.join(new_tags))
-            if gone_tags:
-                for tag in gone_tags:
-                    filtered.write("-" + tag)
-            filtered.write("\n")
-    write_tags(new_tags, gone_tags)
-    # TODO: use the protocol parser and thus don't mangle test comments.
-    for line in original:
-        if line.startswith("tags:"):
-            line_tags = line[5:].split()
-            line_new, line_gone = tags_to_new_gone(line_tags)
-            line_new = line_new - gone_tags
-            line_gone = line_gone - new_tags
-            write_tags(line_new, line_gone)
-        else:
-            filtered.write(line)
+    source = ByteStreamToStreamResult(original, non_subunit_name='stdout')
+    class Tagger(CopyStreamResult):
+        def status(self, **kwargs):
+            tags = kwargs.get('test_tags')
+            if not tags:
+                tags = set()
+            tags.update(new_tags)
+            tags.difference_update(gone_tags)
+            if tags:
+                kwargs['test_tags'] = tags
+            else:
+                kwargs['test_tags'] = None
+            super(Tagger, self).status(**kwargs)
+    output = Tagger([StreamResultToBytes(filtered)])
+    source.run(output)
     return 0
 
 
@@ -1177,11 +1178,11 @@ class ProtocolTestCase(object):
         :param forward: A stream to pass subunit input on to. If not supplied
             subunit input is not forwarded.
         """
-        stream = _make_stream_binary(stream)
+        stream = make_stream_binary(stream)
         self._stream = stream
         self._passthrough = passthrough
         if forward is not None:
-            forward = _make_stream_binary(forward)
+            forward = make_stream_binary(forward)
         self._forward = forward
 
     def __call__(self, result=None):
@@ -1249,21 +1250,6 @@ class TestResultStats(testresult.TestResult):
         return self.failed_tests == 0
 
 
-def get_default_formatter():
-    """Obtain the default formatter to write to.
-
-    :return: A file-like object.
-    """
-    formatter = os.getenv("SUBUNIT_FORMATTER")
-    if formatter:
-        return os.popen(formatter, "w")
-    else:
-        stream = sys.stdout
-        if sys.version_info > (3, 0):
-            stream = stream.buffer
-        return stream
-
-
 def read_test_list(path):
     """Read a list of test ids from a file on disk.
 
@@ -1277,7 +1263,7 @@ def read_test_list(path):
         f.close()
 
 
-def _make_stream_binary(stream):
+def make_stream_binary(stream):
     """Ensure that a stream will be binary safe. See _make_binary_on_windows.
     
     :return: A binary version of the same stream (some streams cannot be
@@ -1285,12 +1271,13 @@ def _make_stream_binary(stream):
     """
     try:
         fileno = stream.fileno()
-    except _UnsupportedOperation:
+    except (_UnsupportedOperation, AttributeError):
         pass
     else:
         _make_binary_on_windows(fileno)
     return _unwrap_text(stream)
 
+
 def _make_binary_on_windows(fileno):
     """Win32 mangles \r\n to \n and that breaks streams. See bug lp:505078."""
     if sys.platform == "win32":
@@ -1301,14 +1288,17 @@ def _make_binary_on_windows(fileno):
 def _unwrap_text(stream):
     """Unwrap stream if it is a text stream to get the original buffer."""
     if sys.version_info > (3, 0):
+        unicode_type = str
+    else:
+        unicode_type = unicode
+    try:
+        # Read streams
+        if type(stream.read(0)) is unicode_type:
+            return stream.buffer
+    except (_UnsupportedOperation, IOError):
+        # Cannot read from the stream: try via writes
         try:
-            # Read streams
-            if type(stream.read(0)) is str:
-                return stream.buffer
-        except (_UnsupportedOperation, IOError):
-            # Cannot read from the stream: try via writes
-            try:
-                stream.write(_b(''))
-            except TypeError:
-                return stream.buffer
+            stream.write(_b(''))
+        except TypeError:
+            return stream.buffer
     return stream
diff --git a/lib/subunit/python/subunit/filters.py b/lib/subunit/python/subunit/filters.py
index dc3fd8a..0a0a185 100644
--- a/lib/subunit/python/subunit/filters.py
+++ b/lib/subunit/python/subunit/filters.py
@@ -17,7 +17,14 @@
 from optparse import OptionParser
 import sys
 
-from subunit import DiscardStream, ProtocolTestCase
+from extras import safe_hasattr
+from testtools import CopyStreamResult, StreamResult, StreamResultRouter
+
+from subunit import (
+    DiscardStream, ProtocolTestCase, ByteStreamToStreamResult,
+    StreamResultToBytes,
+    )
+from subunit.test_results import CatFiles
 
 
 def make_options(description):
@@ -31,33 +38,76 @@ def make_options(description):
         help="Send the output to this path rather than stdout.")
     parser.add_option(
         "-f", "--forward", action="store_true", default=False,
-        help="Forward subunit stream on stdout.")
+        help="Forward subunit stream on stdout. When set, received "
+            "non-subunit output will be encapsulated in subunit.")
     return parser
 
 
 def run_tests_from_stream(input_stream, result, passthrough_stream=None,
-                          forward_stream=None):
+    forward_stream=None, protocol_version=1, passthrough_subunit=True):
     """Run tests from a subunit input stream through 'result'.
 
+    Non-test events - top level file attachments - are expected to be
+    dropped by v2 StreamResults at the present time (as all the analysis code
+    is in ExtendedTestResult API's), so to implement passthrough_stream they
+    are diverted and copied directly when that is set.
+
     :param input_stream: A stream containing subunit input.
     :param result: A TestResult that will receive the test events.
+        NB: This should be an ExtendedTestResult for v1 and a StreamResult for
+        v2.
     :param passthrough_stream: All non-subunit input received will be
         sent to this stream.  If not provided, uses the ``TestProtocolServer``
         default, which is ``sys.stdout``.
     :param forward_stream: All subunit input received will be forwarded
-        to this stream.  If not provided, uses the ``TestProtocolServer``
-        default, which is to not forward any input.
+        to this stream. If not provided, uses the ``TestProtocolServer``
+        default, which is to not forward any input. Do not set this when
+        transforming the stream - items would be double-reported.
+    :param protocol_version: What version of the subunit protocol to expect.
+    :param passthrough_subunit: If True, passthrough should be as subunit
+        otherwise unwrap it. Only has effect when forward_stream is None.
+        (when forwarding as subunit non-subunit input is always turned into
+        subunit)
     """
-    test = ProtocolTestCase(
-        input_stream, passthrough=passthrough_stream,
-        forward=forward_stream)
+    if 1==protocol_version:
+        test = ProtocolTestCase(
+            input_stream, passthrough=passthrough_stream,
+            forward=forward_stream)
+    elif 2==protocol_version:
+        # In all cases we encapsulate unknown inputs.
+        if forward_stream is not None:
+            # Send events to forward_stream as subunit.
+            forward_result = StreamResultToBytes(forward_stream)
+            # If we're passing non-subunit through, copy:
+            if passthrough_stream is None:
+                # Not passing non-test events - split them off to nothing.
+                router = StreamResultRouter(forward_result)
+                router.add_rule(StreamResult(), 'test_id', test_id=None)
+                result = CopyStreamResult([router, result])
+            else:
+                # otherwise, copy all events to forward_result
+                result = CopyStreamResult([forward_result, result])
+        elif passthrough_stream is not None:
+            if not passthrough_subunit:
+                # Route non-test events to passthrough_stream, unwrapping them for
+                # display.
+                passthrough_result = CatFiles(passthrough_stream)
+            else:
+                passthrough_result = StreamResultToBytes(passthrough_stream)
+            result = StreamResultRouter(result)
+            result.add_rule(passthrough_result, 'test_id', test_id=None)
+        test = ByteStreamToStreamResult(input_stream,
+            non_subunit_name='stdout')
+    else:
+        raise Exception("Unknown protocol version.")
     result.startTestRun()
     test.run(result)
     result.stopTestRun()
 
 
 def filter_by_result(result_factory, output_path, passthrough, forward,
-                     input_stream=sys.stdin):
+                     input_stream=sys.stdin, protocol_version=1,
+                     passthrough_subunit=True):
     """Filter an input stream using a test result.
 
     :param result_factory: A callable that when passed an output stream
@@ -71,17 +121,24 @@ def filter_by_result(result_factory, output_path, passthrough, forward,
         ``sys.stdout`` as well as to the ``TestResult``.
     :param input_stream: The source of subunit input.  Defaults to
         ``sys.stdin``.
-    :return: A test result with the resultts of the run.
+    :param protocol_version: The subunit protocol version to expect.
+    :param passthrough_subunit: If True, passthrough should be as subunit.
+    :return: A test result with the results of the run.
     """
     if passthrough:
         passthrough_stream = sys.stdout
     else:
-        passthrough_stream = DiscardStream()
+        if 1==protocol_version:
+            passthrough_stream = DiscardStream()
+        else:
+            passthrough_stream = None
 
     if forward:
         forward_stream = sys.stdout
-    else:
+    elif 1==protocol_version:
         forward_stream = DiscardStream()
+    else:
+        forward_stream = None
 
     if output_path is None:
         output_to = sys.stdout
@@ -91,14 +148,17 @@ def filter_by_result(result_factory, output_path, passthrough, forward,
     try:
         result = result_factory(output_to)
         run_tests_from_stream(
-            input_stream, result, passthrough_stream, forward_stream)
+            input_stream, result, passthrough_stream, forward_stream,
+            protocol_version=protocol_version,
+            passthrough_subunit=passthrough_subunit)
     finally:
         if output_path:
             output_to.close()
     return result
 
 
-def run_filter_script(result_factory, description, post_run_hook=None):
+def run_filter_script(result_factory, description, post_run_hook=None,
+    protocol_version=1, passthrough_subunit=True):
     """Main function for simple subunit filter scripts.
 
     Many subunit filter scripts take a stream of subunit input and use a
@@ -111,15 +171,36 @@ def run_filter_script(result_factory, description, post_run_hook=None):
     :param result_factory: A callable that takes an output stream and returns
         a test result that outputs to that stream.
     :param description: A description of the filter script.
+    :param protocol_version: What protocol version to consume/emit.
+    :param passthrough_subunit: If True, passthrough should be as subunit.
     """
     parser = make_options(description)
     (options, args) = parser.parse_args()
     result = filter_by_result(
         result_factory, options.output_to, not options.no_passthrough,
-        options.forward)
+        options.forward, protocol_version=protocol_version,
+        passthrough_subunit=passthrough_subunit,
+        input_stream=find_stream(sys.stdin, args))
     if post_run_hook:
         post_run_hook(result)
+    if not safe_hasattr(result, 'wasSuccessful'):
+        result = result.decorated
     if result.wasSuccessful():
         sys.exit(0)
     else:
         sys.exit(1)
+
+
+def find_stream(stdin, argv):
+    """Find a stream to use as input for filters.
+
+    :param stdin: Standard in - used if no files are named in argv.
+    :param argv: Command line arguments after option parsing. If one file
+        is named, that is opened in read only binary mode and returned.
+        A missing file will raise an exception, as will multiple file names.
+    """
+    assert len(argv) < 2, "Too many filenames."
+    if argv:
+        return open(argv[0], 'rb')
+    else:
+        return stdin
diff --git a/lib/subunit/python/subunit/run.py b/lib/subunit/python/subunit/run.py
index b5ccea4..8469ac9 100755
--- a/lib/subunit/python/subunit/run.py
+++ b/lib/subunit/python/subunit/run.py
@@ -20,39 +20,83 @@
   $ python -m subunit.run mylib.tests.test_suite
 """
 
+import io
+import os
 import sys
 
-from subunit import TestProtocolClient, get_default_formatter
+from testtools import ExtendedToStreamDecorator
+
+from subunit import StreamResultToBytes
 from subunit.test_results import AutoTimingTestResultDecorator
 from testtools.run import (
     BUFFEROUTPUT,
     CATCHBREAK,
     FAILFAST,
+    list_test,
     TestProgram,
     USAGE_AS_MAIN,
     )
 
 
 class SubunitTestRunner(object):
-    def __init__(self, verbosity=None, failfast=None, buffer=None, stream=None):
+    def __init__(self, verbosity=None, failfast=None, buffer=None, stream=None,
+        stdout=None):
         """Create a TestToolsTestRunner.
 
         :param verbosity: Ignored.
         :param failfast: Stop running tests at the first failure.
         :param buffer: Ignored.
+        :param stream: Upstream unittest stream parameter.
+        :param stdout: Testtools stream parameter.
+
+        Either stream or stdout can be supplied, and stream will take
+        precedence.
         """
         self.failfast = failfast
-        self.stream = stream or sys.stdout
+        self.stream = stream or stdout or sys.stdout
 
     def run(self, test):
         "Run the given test case or test suite."
-        result = TestProtocolClient(self.stream)
+        result, _ = self._list(test)
+        result = ExtendedToStreamDecorator(result)
         result = AutoTimingTestResultDecorator(result)
         if self.failfast is not None:
             result.failfast = self.failfast
-        test(result)
+        result.startTestRun()
+        try:
+            test(result)
+        finally:
+            result.stopTestRun()
         return result
 
+    def list(self, test, loader=None):
+        "List the test."
+        result, errors = self._list(test)
+        if loader is not None:
+            # We were called with the updated API by testtools.run, so look for
+            # errors on the loader, not the test list result.
+            errors = loader.errors
+        if errors:
+            failed_descr = '\n'.join(errors).encode('utf8')
+            result.status(file_name="import errors", runnable=False,
+                file_bytes=failed_descr, mime_type="text/plain;charset=utf8")
+            sys.exit(2)
+
+    def _list(self, test):
+        test_ids, errors = list_test(test)
+        try:
+            fileno = self.stream.fileno()
+        except:
+            fileno = None
+        if fileno is not None:
+            stream = os.fdopen(fileno, 'wb', 0)
+        else:
+            stream = self.stream
+        result = StreamResultToBytes(stream)
+        for test_id in test_ids:
+            result.status(test_id=test_id, test_status='exists')
+        return result, errors
+
 
 class SubunitTestProgram(TestProgram):
 
@@ -77,8 +121,26 @@ class SubunitTestProgram(TestProgram):
         sys.exit(2)
 
 
-if __name__ == '__main__':
-    stream = get_default_formatter()
+def main(argv=None, stdout=None):
+    if argv is None:
+        argv = sys.argv
     runner = SubunitTestRunner
-    SubunitTestProgram(module=None, argv=sys.argv, testRunner=runner,
-        stdout=sys.stdout)
+    # stdout is None except in unit tests.
+    if stdout is None:
+        stdout = sys.stdout
+        # Disable the default buffering, for Python 2.x where pdb doesn't do it
+        # on non-ttys.
+        if hasattr(stdout, 'fileno'):
+            # Patch stdout to be unbuffered, so that pdb works well on 2.6/2.7.
+            binstdout = io.open(stdout.fileno(), 'wb', 0)
+            if sys.version_info[0] > 2:
+                sys.stdout = io.TextIOWrapper(binstdout, encoding=sys.stdout.encoding)
+            else:
+                sys.stdout = binstdout
+            stdout = sys.stdout
+    SubunitTestProgram(module=None, argv=argv, testRunner=runner,
+        stdout=stdout, exit=False)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/lib/subunit/python/subunit/test_results.py b/lib/subunit/python/subunit/test_results.py
index 91c9bbd..b3ca968 100644
--- a/lib/subunit/python/subunit/test_results.py
+++ b/lib/subunit/python/subunit/test_results.py
@@ -20,13 +20,14 @@ import csv
 import datetime
 
 import testtools
-from testtools.compat import all
 from testtools.content import (
     text_content,
     TracebackContent,
     )
+from testtools import StreamResult
 
 from subunit import iso8601
+import subunit
 
 
 # NOT a TestResult, because we are implementing the interface, not inheriting
@@ -525,16 +526,24 @@ class TestResultFilter(TestResultDecorator):
 
 
 class TestIdPrintingResult(testtools.TestResult):
+    """Print test ids to a stream.
 
-    def __init__(self, stream, show_times=False):
+    Implements both TestResult and StreamResult, for compatibility.
+    """
+
+    def __init__(self, stream, show_times=False, show_exists=False):
         """Create a FilterResult object outputting to stream."""
         super(TestIdPrintingResult, self).__init__()
         self._stream = stream
+        self.show_exists = show_exists
+        self.show_times = show_times
+
+    def startTestRun(self):
         self.failed_tests = 0
         self.__time = None
-        self.show_times = show_times
         self._test = None
         self._test_duration = 0
+        self._active_tests = {}
 
     def addError(self, test, err):
         self.failed_tests += 1
@@ -557,21 +566,44 @@ class TestIdPrintingResult(testtools.TestResult):
     def addExpectedFailure(self, test, err=None, details=None):
         self._test = test
 
-    def reportTest(self, test, duration):
+    def reportTest(self, test_id, duration):
         if self.show_times:
             seconds = duration.seconds
             seconds += duration.days * 3600 * 24
             seconds += duration.microseconds / 1000000.0
-            self._stream.write(test.id() + ' %0.3f\n' % seconds)
+            self._stream.write(test_id + ' %0.3f\n' % seconds)
         else:
-            self._stream.write(test.id() + '\n')
+            self._stream.write(test_id + '\n')
 
     def startTest(self, test):
         self._start_time = self._time()
 
+    def status(self, test_id=None, test_status=None, test_tags=None,
+        runnable=True, file_name=None, file_bytes=None, eof=False,
+        mime_type=None, route_code=None, timestamp=None):
+        if not test_id:
+            return
+        if timestamp is not None:
+            self.time(timestamp)
+        if test_status=='exists':
+            if self.show_exists:
+                self.reportTest(test_id, 0)
+        elif test_status in ('inprogress', None):
+            self._active_tests[test_id] = self._time()
+        else:
+            self._end_test(test_id)
+
+    def _end_test(self, test_id):
+        test_start = self._active_tests.pop(test_id, None)
+        if not test_start:
+            test_duration = 0
+        else:
+            test_duration = self._time() - test_start
+        self.reportTest(test_id, test_duration)
+
     def stopTest(self, test):
         test_duration = self._time() - self._start_time
-        self.reportTest(self._test, test_duration)
+        self.reportTest(self._test.id(), test_duration)
 
     def time(self, time):
         self.__time = time
@@ -583,6 +615,10 @@ class TestIdPrintingResult(testtools.TestResult):
         "Tells whether or not this result was a success"
         return self.failed_tests == 0
 
+    def stopTestRun(self):
+        for test_id in list(self._active_tests.keys()):
+            self._end_test(test_id)
+
 
 class TestByTestResult(testtools.TestResult):
     """Call something every time a test completes."""
@@ -676,3 +712,17 @@ class CsvResult(TestByTestResult):
     def startTestRun(self):
         super(CsvResult, self).startTestRun()
         self._write_row(['test', 'status', 'start_time', 'stop_time'])
+
+
+class CatFiles(StreamResult):
+    """Cat file attachments received to a stream."""
+
+    def __init__(self, byte_stream):
+        self.stream = subunit.make_stream_binary(byte_stream)
+
+    def status(self, test_id=None, test_status=None, test_tags=None,
+        runnable=True, file_name=None, file_bytes=None, eof=False,
+        mime_type=None, route_code=None, timestamp=None):
+        if file_name is not None:
+            self.stream.write(file_bytes)
+            self.stream.flush()
diff --git a/lib/subunit/python/subunit/tests/TestUtil.py b/lib/subunit/python/subunit/tests/TestUtil.py
deleted file mode 100644
index 39d901e..0000000
--- a/lib/subunit/python/subunit/tests/TestUtil.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# Copyright (c) 2004 Canonical Limited
-#       Author: Robert Collins <robert.collins at canonical.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
-
-import sys
-import logging
-import unittest
-
-
-class LogCollector(logging.Handler):
-    def __init__(self):
-        logging.Handler.__init__(self)
-        self.records=[]
-    def emit(self, record):
-        self.records.append(record.getMessage())
-
-
-def makeCollectingLogger():
-    """I make a logger instance that collects its logs for programmatic analysis
-    -> (logger, collector)"""
-    logger=logging.Logger("collector")
-    handler=LogCollector()
-    handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
-    logger.addHandler(handler)
-    return logger, handler
-
-
-def visitTests(suite, visitor):
-    """A foreign method for visiting the tests in a test suite."""
-    for test in suite._tests:
-        #Abusing types to avoid monkey patching unittest.TestCase.
-        # Maybe that would be better?
-        try:
-            test.visit(visitor)
-        except AttributeError:
-            if isinstance(test, unittest.TestCase):
-                visitor.visitCase(test)
-            elif isinstance(test, unittest.TestSuite):
-                visitor.visitSuite(test)
-                visitTests(test, visitor)
-            else:
-                print ("unvisitable non-unittest.TestCase element %r (%r)" % (test, test.__class__))
-
-
-class TestSuite(unittest.TestSuite):
-    """I am an extended TestSuite with a visitor interface.
-    This is primarily to allow filtering of tests - and suites or
-    more in the future. An iterator of just tests wouldn't scale..."""
-
-    def visit(self, visitor):
-        """visit the composite. Visiting is depth-first.
-        current callbacks are visitSuite and visitCase."""
-        visitor.visitSuite(self)
-        visitTests(self, visitor)
-
-
-class TestLoader(unittest.TestLoader):
-    """Custome TestLoader to set the right TestSuite class."""
-    suiteClass = TestSuite
-
-class TestVisitor(object):
-    """A visitor for Tests"""
-    def visitSuite(self, aTestSuite):
-        pass
-    def visitCase(self, aTestCase):
-        pass
diff --git a/lib/subunit/python/subunit/tests/__init__.py b/lib/subunit/python/subunit/tests/__init__.py
index e0e1eb1..c1c2c64 100644
--- a/lib/subunit/python/subunit/tests/__init__.py
+++ b/lib/subunit/python/subunit/tests/__init__.py
@@ -6,7 +6,7 @@
 #  license at the users choice. A copy of both licenses are available in the
 #  project source as Apache-2.0 and BSD. You may not use this file except in
 #  compliance with one of these two licences.
-#  
+#
 #  Unless required by applicable law or agreed to in writing, software
 #  distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
 #  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
@@ -14,10 +14,29 @@
 #  limitations under that license.
 #
 
+import sys
+from unittest import TestLoader
+
+from testscenarios import generate_scenarios
+
+
+# Before the test module imports to avoid circularity.
+# For testing: different pythons have different str() implementations.
+if sys.version_info > (3, 0):
+    _remote_exception_repr = "testtools.testresult.real._StringException"
+    _remote_exception_str = "Traceback (most recent call last):\ntesttools.testresult.real._StringException"
+    _remote_exception_str_chunked = "57\r\n" + _remote_exception_str + ": boo qux\n0\r\n"
+else:
+    _remote_exception_repr = "_StringException" 
+    _remote_exception_str = "Traceback (most recent call last):\n_StringException" 
+    _remote_exception_str_chunked = "3D\r\n" + _remote_exception_str + ": boo qux\n0\r\n"
+
+
 from subunit.tests import (
-    TestUtil,
     test_chunked,
     test_details,
+    test_filters,
+    test_output_filter,
     test_progress_model,
     test_run,
     test_subunit_filter,
@@ -25,19 +44,26 @@ from subunit.tests import (
     test_subunit_tags,
     test_tap2subunit,
     test_test_protocol,
+    test_test_protocol2,
     test_test_results,
     )
 
+
 def test_suite():
-    result = TestUtil.TestSuite()
-    result.addTest(test_chunked.test_suite())
-    result.addTest(test_details.test_suite())
-    result.addTest(test_progress_model.test_suite())
-    result.addTest(test_test_results.test_suite())
-    result.addTest(test_test_protocol.test_suite())
-    result.addTest(test_tap2subunit.test_suite())
-    result.addTest(test_subunit_filter.test_suite())
-    result.addTest(test_subunit_tags.test_suite())
-    result.addTest(test_subunit_stats.test_suite())
-    result.addTest(test_run.test_suite())
+    loader = TestLoader()
+    result = loader.loadTestsFromModule(test_chunked)
+    result.addTest(loader.loadTestsFromModule(test_details))
+    result.addTest(loader.loadTestsFromModule(test_filters))
+    result.addTest(loader.loadTestsFromModule(test_progress_model))
+    result.addTest(loader.loadTestsFromModule(test_test_results))
+    result.addTest(loader.loadTestsFromModule(test_test_protocol))
+    result.addTest(loader.loadTestsFromModule(test_test_protocol2))
+    result.addTest(loader.loadTestsFromModule(test_tap2subunit))
+    result.addTest(loader.loadTestsFromModule(test_subunit_filter))
+    result.addTest(loader.loadTestsFromModule(test_subunit_tags))
+    result.addTest(loader.loadTestsFromModule(test_subunit_stats))
+    result.addTest(loader.loadTestsFromModule(test_run))
+    result.addTests(
+        generate_scenarios(loader.loadTestsFromModule(test_output_filter))
+    )
     return result
diff --git a/lib/subunit/python/subunit/tests/test_chunked.py b/lib/subunit/python/subunit/tests/test_chunked.py
index e0742f1..5100b32 100644
--- a/lib/subunit/python/subunit/tests/test_chunked.py
+++ b/lib/subunit/python/subunit/tests/test_chunked.py
@@ -22,12 +22,6 @@ from testtools.compat import _b, BytesIO
 import subunit.chunked
 
 
-def test_suite():
-    loader = subunit.tests.TestUtil.TestLoader()
-    result = loader.loadTestsFromName(__name__)
-    return result
-
-
 class TestDecode(unittest.TestCase):
 
     def setUp(self):
diff --git a/lib/subunit/python/subunit/tests/test_details.py b/lib/subunit/python/subunit/tests/test_details.py
index 746aa04..8605c5a 100644
--- a/lib/subunit/python/subunit/tests/test_details.py
+++ b/lib/subunit/python/subunit/tests/test_details.py
@@ -22,12 +22,6 @@ import subunit.tests
 from subunit import content, content_type, details
 
 
-def test_suite():
-    loader = subunit.tests.TestUtil.TestLoader()
-    result = loader.loadTestsFromName(__name__)
-    return result
-
-
 class TestSimpleDetails(unittest.TestCase):
 
     def test_lineReceived(self):
diff --git a/lib/subunit/python/subunit/tests/test_progress_model.py b/lib/subunit/python/subunit/tests/test_progress_model.py
index 76200c6..2ca0888 100644
--- a/lib/subunit/python/subunit/tests/test_progress_model.py
+++ b/lib/subunit/python/subunit/tests/test_progress_model.py
@@ -110,9 +110,3 @@ class TestProgressModel(unittest.TestCase):
         progress.advance()
         progress.pop()
         self.assertProgressSummary(1, 3, progress)
-
-
-def test_suite():
-    loader = subunit.tests.TestUtil.TestLoader()
-    result = loader.loadTestsFromName(__name__)
-    return result
diff --git a/lib/subunit/python/subunit/tests/test_run.py b/lib/subunit/python/subunit/tests/test_run.py
index 10519ed..3339a82 100644
--- a/lib/subunit/python/subunit/tests/test_run.py
+++ b/lib/subunit/python/subunit/tests/test_run.py
@@ -14,39 +14,92 @@
 #  limitations under that license.
 #
 
-from testtools.compat import BytesIO
+import io
 import unittest
 
-from testtools import PlaceHolder
+from testtools import PlaceHolder, TestCase
+from testtools.compat import _b
+from testtools.matchers import StartsWith
+from testtools.testresult.doubles import StreamResult
 
 import subunit
+from subunit import run
 from subunit.run import SubunitTestRunner
 
 
-def test_suite():
-    loader = subunit.tests.TestUtil.TestLoader()
-    result = loader.loadTestsFromName(__name__)
-    return result
+class TestSubunitTestRunner(TestCase):
 
+    def test_includes_timing_output(self):
+        bytestream = io.BytesIO()
+        runner = SubunitTestRunner(stream=bytestream)
+        test = PlaceHolder('name')
+        runner.run(test)
+        bytestream.seek(0)
+        eventstream = StreamResult()
+        subunit.ByteStreamToStreamResult(bytestream).run(eventstream)
+        timestamps = [event[-1] for event in eventstream._events
+            if event is not None]
+        self.assertNotEqual([], timestamps)
 
-class TimeCollectingTestResult(unittest.TestResult):
+    def test_enumerates_tests_before_run(self):
+        bytestream = io.BytesIO()
+        runner = SubunitTestRunner(stream=bytestream)
+        test1 = PlaceHolder('name1')
+        test2 = PlaceHolder('name2')
+        case = unittest.TestSuite([test1, test2])
+        runner.run(case)
+        bytestream.seek(0)
+        eventstream = StreamResult()
+        subunit.ByteStreamToStreamResult(bytestream).run(eventstream)
+        self.assertEqual([
+            ('status', 'name1', 'exists'),
+            ('status', 'name2', 'exists'),
+            ], [event[:3] for event in eventstream._events[:2]])
 
-    def __init__(self, *args, **kwargs):
-        super(TimeCollectingTestResult, self).__init__(*args, **kwargs)
-        self.time_called = []
+    def test_list_errors_if_errors_from_list_test(self):
+        bytestream = io.BytesIO()
+        runner = SubunitTestRunner(stream=bytestream)
+        def list_test(test):
+            return [], ['failed import']
+        self.patch(run, 'list_test', list_test)
+        exc = self.assertRaises(SystemExit, runner.list, None)
+        self.assertEqual((2,), exc.args)
 
-    def time(self, a_time):
-        self.time_called.append(a_time)
+    def test_list_includes_loader_errors(self):
+        bytestream = io.BytesIO()
+        runner = SubunitTestRunner(stream=bytestream)
+        def list_test(test):
+            return [], []
+        class Loader(object):
+            errors = ['failed import']
+        loader = Loader()
+        self.patch(run, 'list_test', list_test)
+        exc = self.assertRaises(SystemExit, runner.list, None, loader=loader)
+        self.assertEqual((2,), exc.args)
 
+    class FailingTest(TestCase):
+        def test_fail(self):
+            1/0
 
-class TestSubunitTestRunner(unittest.TestCase):
+    def test_exits_zero_when_tests_fail(self):
+        bytestream = io.BytesIO()
+        stream = io.TextIOWrapper(bytestream, encoding="utf8")
+        try:
+            self.assertEqual(None, run.main(
+                argv=["progName", "subunit.tests.test_run.TestSubunitTestRunner.FailingTest"],
+                stdout=stream))
+        except SystemExit:
+            self.fail("SystemExit raised")
+        self.assertThat(bytestream.getvalue(), StartsWith(_b('\xb3')))
 
-    def test_includes_timing_output(self):
-        io = BytesIO()
-        runner = SubunitTestRunner(stream=io)
-        test = PlaceHolder('name')
-        runner.run(test)
-        client = TimeCollectingTestResult()
-        io.seek(0)
-        subunit.TestProtocolServer(client).readFrom(io)
-        self.assertTrue(len(client.time_called) > 0)
+    class ExitingTest(TestCase):
+        def test_exit(self):
+            raise SystemExit(0)
+
+    def test_exits_nonzero_when_execution_errors(self):
+        bytestream = io.BytesIO()
+        stream = io.TextIOWrapper(bytestream, encoding="utf8")
+        exc = self.assertRaises(SystemExit, run.main,
+                argv=["progName", "subunit.tests.test_run.TestSubunitTestRunner.ExitingTest"],
+                stdout=stream)
+        self.assertEqual(0, exc.args[0])
diff --git a/lib/subunit/python/subunit/tests/test_subunit_filter.py b/lib/subunit/python/subunit/tests/test_subunit_filter.py
index 33b9248..5f34b3b 100644
--- a/lib/subunit/python/subunit/tests/test_subunit_filter.py
+++ b/lib/subunit/python/subunit/tests/test_subunit_filter.py
@@ -25,10 +25,11 @@ import unittest
 
 from testtools import TestCase
 from testtools.compat import _b, BytesIO
-from testtools.testresult.doubles import ExtendedTestResult
+from testtools.testresult.doubles import ExtendedTestResult, StreamResult
 
 import subunit
 from subunit.test_results import make_tag_filter, TestResultFilter
+from subunit import ByteStreamToStreamResult, StreamResultToBytes
 
 
 class TestTestResultFilter(TestCase):
@@ -286,23 +287,6 @@ xfail todo
 
 class TestFilterCommand(TestCase):
 
-    example_subunit_stream = _b("""\
-tags: global
-test passed
-success passed
-test failed
-tags: local
-failure failed
-test error
-error error [
-error details
-]
-test skipped
-skip skipped
-test todo
-xfail todo
-""")
-
     def run_command(self, args, stream):
         root = os.path.dirname(
             os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
@@ -316,55 +300,47 @@ xfail todo
             raise RuntimeError("%s failed: %s" % (command, err))
         return out
 
-    def to_events(self, stream):
-        test = subunit.ProtocolTestCase(BytesIO(stream))
-        result = ExtendedTestResult()
-        test.run(result)
-        return result._events
-
     def test_default(self):
-        output = self.run_command([], _b(
-                "test: foo\n"
-                "skip: foo\n"
-                ))
-        events = self.to_events(output)
-        foo = subunit.RemotedTestCase('foo')
-        self.assertEqual(
-            [('startTest', foo),
-             ('addSkip', foo, {}),
-             ('stopTest', foo)],
-            events)
+        byte_stream = BytesIO()
+        stream = StreamResultToBytes(byte_stream)
+        stream.status(test_id="foo", test_status="inprogress")
+        stream.status(test_id="foo", test_status="skip")
+        output = self.run_command([], byte_stream.getvalue())
+        events = StreamResult()
+        ByteStreamToStreamResult(BytesIO(output)).run(events)
+        ids = set(event[1] for event in events._events)
+        self.assertEqual([
+            ('status', 'foo', 'inprogress'),
+            ('status', 'foo', 'skip'),
+            ], [event[:3] for event in events._events])
 
     def test_tags(self):
-        output = self.run_command(['-s', '--with-tag', 'a'], _b(
-                "tags: a\n"
-                "test: foo\n"
-                "success: foo\n"
-                "tags: -a\n"
-                "test: bar\n"
-                "success: bar\n"
-                "test: baz\n"
-                "tags: a\n"
-                "success: baz\n"
-                ))
-        events = self.to_events(output)
-        foo = subunit.RemotedTestCase('foo')
-        baz = subunit.RemotedTestCase('baz')
-        self.assertEqual(
-            [('tags', set(['a']), set()),
-             ('startTest', foo),
-             ('addSuccess', foo),
-             ('stopTest', foo),
-             ('tags', set(), set(['a'])),
-             ('startTest', baz),
-             ('tags', set(['a']), set()),
-             ('addSuccess', baz),
-             ('stopTest', baz),
-             ],
-            events)
-
-
-def test_suite():
-    loader = subunit.tests.TestUtil.TestLoader()
-    result = loader.loadTestsFromName(__name__)
-    return result
+        byte_stream = BytesIO()
+        stream = StreamResultToBytes(byte_stream)
+        stream.status(
+            test_id="foo", test_status="inprogress", test_tags=set(["a"]))
+        stream.status(
+            test_id="foo", test_status="success", test_tags=set(["a"]))
+        stream.status(test_id="bar", test_status="inprogress")
+        stream.status(test_id="bar", test_status="inprogress")
+        stream.status(
+            test_id="baz", test_status="inprogress", test_tags=set(["a"]))
+        stream.status(
+            test_id="baz", test_status="success", test_tags=set(["a"]))
+        output = self.run_command(
+            ['-s', '--with-tag', 'a'], byte_stream.getvalue())
+        events = StreamResult()
+        ByteStreamToStreamResult(BytesIO(output)).run(events)
+        ids = set(event[1] for event in events._events)
+        self.assertEqual(set(['foo', 'baz']), ids)
+
+    def test_no_passthrough(self):
+        output = self.run_command(['--no-passthrough'], b'hi thar')
+        self.assertEqual(b'', output)
+
+    def test_passthrough(self):
+        output = self.run_command([], b'hi thar')
+        byte_stream = BytesIO()
+        stream = StreamResultToBytes(byte_stream)
+        stream.status(file_name="stdout", file_bytes=b'hi thar')
+        self.assertEqual(byte_stream.getvalue(), output)
diff --git a/lib/subunit/python/subunit/tests/test_subunit_stats.py b/lib/subunit/python/subunit/tests/test_subunit_stats.py
index 6fd3301..7c5e42d 100644
--- a/lib/subunit/python/subunit/tests/test_subunit_stats.py
+++ b/lib/subunit/python/subunit/tests/test_subunit_stats.py
@@ -76,9 +76,3 @@ Seen tags: global, local
         self.setUpUsedStream()
         self.result.formatStats()
         self.assertEqual(expected, self.output.getvalue())
-
-
-def test_suite():
-    loader = subunit.tests.TestUtil.TestLoader()
-    result = loader.loadTestsFromName(__name__)
-    return result
diff --git a/lib/subunit/python/subunit/tests/test_subunit_tags.py b/lib/subunit/python/subunit/tests/test_subunit_tags.py
index c98506a..a16edc1 100644
--- a/lib/subunit/python/subunit/tests/test_subunit_tags.py
+++ b/lib/subunit/python/subunit/tests/test_subunit_tags.py
@@ -16,54 +16,70 @@
 
 """Tests for subunit.tag_stream."""
 
-import unittest
+from io import BytesIO
 
-from testtools.compat import StringIO
+import testtools
+from testtools.matchers import Contains
 
 import subunit
 import subunit.test_results
 
 
-class TestSubUnitTags(unittest.TestCase):
+class TestSubUnitTags(testtools.TestCase):
 
     def setUp(self):
-        self.original = StringIO()
-        self.filtered = StringIO()
+        super(TestSubUnitTags, self).setUp()
+        self.original = BytesIO()
+        self.filtered = BytesIO()
 
     def test_add_tag(self):
-        self.original.write("tags: foo\n")
-        self.original.write("test: test\n")
-        self.original.write("tags: bar -quux\n")
-        self.original.write("success: test\n")
+        # Literal values to avoid set sort-order dependencies. Python code show
+        # derivation.
+        # reference = BytesIO()
+        # stream = subunit.StreamResultToBytes(reference)
+        # stream.status(
+        #     test_id='test', test_status='inprogress', test_tags=set(['quux', 'foo']))
+        # stream.status(
+        #     test_id='test', test_status='success', test_tags=set(['bar', 'quux', 'foo']))
+        reference = [
+            b'\xb3)\x82\x17\x04test\x02\x04quux\x03foo\x05\x97n\x86\xb3)'
+                b'\x83\x1b\x04test\x03\x03bar\x04quux\x03fooqn\xab)',
+            b'\xb3)\x82\x17\x04test\x02\x04quux\x03foo\x05\x97n\x86\xb3)'
+                b'\x83\x1b\x04test\x03\x04quux\x03foo\x03bar\xaf\xbd\x9d\xd6',
+            b'\xb3)\x82\x17\x04test\x02\x04quux\x03foo\x05\x97n\x86\xb3)'
+                b'\x83\x1b\x04test\x03\x04quux\x03bar\x03foo\x03\x04b\r',
+            b'\xb3)\x82\x17\x04test\x02\x04quux\x03foo\x05\x97n\x86\xb3)'
+                b'\x83\x1b\x04test\x03\x03bar\x03foo\x04quux\xd2\x18\x1bC',
+            b'\xb3)\x82\x17\x04test\x02\x03foo\x04quux\xa6\xe1\xde\xec\xb3)'
+                b'\x83\x1b\x04test\x03\x03foo\x04quux\x03bar\x08\xc2X\x83',
+            b'\xb3)\x82\x17\x04test\x02\x03foo\x04quux\xa6\xe1\xde\xec\xb3)'
+                b'\x83\x1b\x04test\x03\x03bar\x03foo\x04quux\xd2\x18\x1bC',
+            b'\xb3)\x82\x17\x04test\x02\x03foo\x04quux\xa6\xe1\xde\xec\xb3)'
+                b'\x83\x1b\x04test\x03\x03foo\x03bar\x04quux:\x05e\x80',
+            ]
+        stream = subunit.StreamResultToBytes(self.original)
+        stream.status(
+            test_id='test', test_status='inprogress', test_tags=set(['foo']))
+        stream.status(
+            test_id='test', test_status='success', test_tags=set(['foo', 'bar']))
         self.original.seek(0)
-        result = subunit.tag_stream(self.original, self.filtered, ["quux"])
-        self.assertEqual([
-            "tags: quux",
-            "tags: foo",
-            "test: test",
-            "tags: bar",
-            "success: test",
-            ],
-            self.filtered.getvalue().splitlines())
+        self.assertEqual(
+            0, subunit.tag_stream(self.original, self.filtered, ["quux"]))
+        self.assertThat(reference, Contains(self.filtered.getvalue()))
 
     def test_remove_tag(self):
-        self.original.write("tags: foo\n")
-        self.original.write("test: test\n")
-        self.original.write("tags: bar -quux\n")
-        self.original.write("success: test\n")
+        reference = BytesIO()
+        stream = subunit.StreamResultToBytes(reference)
+        stream.status(
+            test_id='test', test_status='inprogress', test_tags=set(['foo']))
+        stream.status(
+            test_id='test', test_status='success', test_tags=set(['foo']))
+        stream = subunit.StreamResultToBytes(self.original)
+        stream.status(
+            test_id='test', test_status='inprogress', test_tags=set(['foo']))
+        stream.status(
+            test_id='test', test_status='success', test_tags=set(['foo', 'bar']))
         self.original.seek(0)
-        result = subunit.tag_stream(self.original, self.filtered, ["-bar"])
-        self.assertEqual([
-            "tags: -bar",
-            "tags: foo",
-            "test: test",
-            "tags: -quux",
-            "success: test",
-            ],
-            self.filtered.getvalue().splitlines())
-
-
-def test_suite():
-    loader = subunit.tests.TestUtil.TestLoader()
-    result = loader.loadTestsFromName(__name__)
-    return result
+        self.assertEqual(
+            0, subunit.tag_stream(self.original, self.filtered, ["-bar"]))
+        self.assertEqual(reference.getvalue(), self.filtered.getvalue())
diff --git a/lib/subunit/python/subunit/tests/test_tap2subunit.py b/lib/subunit/python/subunit/tests/test_tap2subunit.py
index 11bc191..5b7c07a 100644
--- a/lib/subunit/python/subunit/tests/test_tap2subunit.py
+++ b/lib/subunit/python/subunit/tests/test_tap2subunit.py
@@ -16,14 +16,19 @@
 
 """Tests for TAP2SubUnit."""
 
+from io import BytesIO, StringIO
 import unittest
 
-from testtools.compat import StringIO
+from testtools import TestCase
+from testtools.compat import _u
+from testtools.testresult.doubles import StreamResult
 
 import subunit
 
+UTF8_TEXT = 'text/plain; charset=UTF8'
 
-class TestTAP2SubUnit(unittest.TestCase):
+
+class TestTAP2SubUnit(TestCase):
     """Tests for TAP2SubUnit.
 
     These tests test TAP string data in, and subunit string data out.
@@ -34,24 +39,21 @@ class TestTAP2SubUnit(unittest.TestCase):
     """
 
     def setUp(self):
+        super(TestTAP2SubUnit, self).setUp()
         self.tap = StringIO()
-        self.subunit = StringIO()
+        self.subunit = BytesIO()
 
     def test_skip_entire_file(self):
         # A file
         # 1..- # Skipped: comment
         # results in a single skipped test.
-        self.tap.write("1..0 # Skipped: entire file skipped\n")
+        self.tap.write(_u("1..0 # Skipped: entire file skipped\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            "test file skip",
-            "skip file skip [",
-            "Skipped: entire file skipped",
-            "]",
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([('status', 'file skip', 'skip', None, True,
+            'tap comment', b'Skipped: entire file skipped', True, None, None,
+            None)])
 
     def test_ok_test_pass(self):
         # A file
@@ -59,164 +61,128 @@ class TestTAP2SubUnit(unittest.TestCase):
         # results in a passed test with name 'test 1' (a synthetic name as tap
         # does not require named fixtures - it is the first test in the tap
         # stream).
-        self.tap.write("ok\n")
+        self.tap.write(_u("ok\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            "test test 1",
-            "success test 1",
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([('status', 'test 1', 'success', None, False, None,
+            None, True, None, None, None)])
 
     def test_ok_test_number_pass(self):
         # A file
         # ok 1
         # results in a passed test with name 'test 1'
-        self.tap.write("ok 1\n")
+        self.tap.write(_u("ok 1\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            "test test 1",
-            "success test 1",
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([('status', 'test 1', 'success', None, False, None,
+            None, True, None, None, None)])
 
     def test_ok_test_number_description_pass(self):
         # A file
         # ok 1 - There is a description
         # results in a passed test with name 'test 1 - There is a description'
-        self.tap.write("ok 1 - There is a description\n")
+        self.tap.write(_u("ok 1 - There is a description\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            "test test 1 - There is a description",
-            "success test 1 - There is a description",
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([('status', 'test 1 - There is a description',
+            'success', None, False, None, None, True, None, None, None)])
 
     def test_ok_test_description_pass(self):
         # A file
         # ok There is a description
         # results in a passed test with name 'test 1 There is a description'
-        self.tap.write("ok There is a description\n")
+        self.tap.write(_u("ok There is a description\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            "test test 1 There is a description",
-            "success test 1 There is a description",
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([('status', 'test 1 There is a description',
+            'success', None, False, None, None, True, None, None, None)])
 
     def test_ok_SKIP_skip(self):
         # A file
         # ok # SKIP
         # results in a skkip test with name 'test 1'
-        self.tap.write("ok # SKIP\n")
+        self.tap.write(_u("ok # SKIP\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            "test test 1",
-            "skip test 1",
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([('status', 'test 1', 'skip', None, False, None,
+            None, True, None, None, None)])
 
     def test_ok_skip_number_comment_lowercase(self):
-        self.tap.write("ok 1 # skip no samba environment available, skipping compilation\n")
+        self.tap.write(_u("ok 1 # skip no samba environment available, skipping compilation\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            "test test 1",
-            "skip test 1 [", 
-            "no samba environment available, skipping compilation",
-            "]"
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([('status', 'test 1', 'skip', None, False, 'tap comment',
+            b'no samba environment available, skipping compilation', True,
+            'text/plain; charset=UTF8', None, None)])
 
     def test_ok_number_description_SKIP_skip_comment(self):
         # A file
         # ok 1 foo  # SKIP Not done yet
         # results in a skip test with name 'test 1 foo' and a log of
         # Not done yet
-        self.tap.write("ok 1 foo  # SKIP Not done yet\n")
+        self.tap.write(_u("ok 1 foo  # SKIP Not done yet\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            "test test 1 foo",
-            "skip test 1 foo [",
-            "Not done yet",
-            "]",
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([('status', 'test 1 foo', 'skip', None, False,
+            'tap comment', b'Not done yet', True, 'text/plain; charset=UTF8',
+            None, None)])
 
     def test_ok_SKIP_skip_comment(self):
         # A file
         # ok # SKIP Not done yet
         # results in a skip test with name 'test 1' and a log of Not done yet
-        self.tap.write("ok # SKIP Not done yet\n")
+        self.tap.write(_u("ok # SKIP Not done yet\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            "test test 1",
-            "skip test 1 [",
-            "Not done yet",
-            "]",
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([('status', 'test 1', 'skip', None, False,
+            'tap comment', b'Not done yet', True, 'text/plain; charset=UTF8',
+            None, None)])
 
     def test_ok_TODO_xfail(self):
         # A file
         # ok # TODO
         # results in a xfail test with name 'test 1'
-        self.tap.write("ok # TODO\n")
+        self.tap.write(_u("ok # TODO\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            "test test 1",
-            "xfail test 1",
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([('status', 'test 1', 'xfail', None, False, None,
+            None, True, None, None, None)])
 
     def test_ok_TODO_xfail_comment(self):
         # A file
         # ok # TODO Not done yet
         # results in a xfail test with name 'test 1' and a log of Not done yet
-        self.tap.write("ok # TODO Not done yet\n")
+        self.tap.write(_u("ok # TODO Not done yet\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            "test test 1",
-            "xfail test 1 [",
-            "Not done yet",
-            "]",
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([('status', 'test 1', 'xfail', None, False,
+            'tap comment', b'Not done yet', True, 'text/plain; charset=UTF8',
+            None, None)])
 
     def test_bail_out_errors(self):
         # A file with line in it
         # Bail out! COMMENT
         # is treated as an error
-        self.tap.write("ok 1 foo\n")
-        self.tap.write("Bail out! Lifejacket engaged\n")
+        self.tap.write(_u("ok 1 foo\n"))
+        self.tap.write(_u("Bail out! Lifejacket engaged\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            "test test 1 foo",
-            "success test 1 foo",
-            "test Bail out! Lifejacket engaged",
-            "error Bail out! Lifejacket engaged",
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([
+            ('status', 'test 1 foo', 'success', None, False, None, None, True,
+             None, None, None),
+            ('status', 'Bail out! Lifejacket engaged', 'fail', None, False,
+             None, None, True, None, None, None)])
 
     def test_missing_test_at_end_with_plan_adds_error(self):
         # A file
@@ -224,23 +190,20 @@ class TestTAP2SubUnit(unittest.TestCase):
         # ok first test
         # not ok third test
         # results in three tests, with the third being created
-        self.tap.write('1..3\n')
-        self.tap.write('ok first test\n')
-        self.tap.write('not ok second test\n')
+        self.tap.write(_u('1..3\n'))
+        self.tap.write(_u('ok first test\n'))
+        self.tap.write(_u('not ok second test\n'))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            'test test 1 first test',
-            'success test 1 first test',
-            'test test 2 second test',
-            'failure test 2 second test',
-            'test test 3',
-            'error test 3 [',
-            'test missing from TAP output',
-            ']',
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([
+            ('status', 'test 1 first test', 'success', None, False, None,
+             None, True, None, None, None),
+            ('status', 'test 2 second test', 'fail', None, False, None, None,
+             True, None, None, None),
+            ('status', 'test 3', 'fail', None, False, 'tap meta',
+             b'test missing from TAP output', True, 'text/plain; charset=UTF8',
+             None, None)])
 
     def test_missing_test_with_plan_adds_error(self):
         # A file
@@ -248,45 +211,39 @@ class TestTAP2SubUnit(unittest.TestCase):
         # ok first test
         # not ok 3 third test
         # results in three tests, with the second being created
-        self.tap.write('1..3\n')
-        self.tap.write('ok first test\n')
-        self.tap.write('not ok 3 third test\n')
+        self.tap.write(_u('1..3\n'))
+        self.tap.write(_u('ok first test\n'))
+        self.tap.write(_u('not ok 3 third test\n'))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            'test test 1 first test',
-            'success test 1 first test',
-            'test test 2',
-            'error test 2 [',
-            'test missing from TAP output',
-            ']',
-            'test test 3 third test',
-            'failure test 3 third test',
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([
+            ('status', 'test 1 first test', 'success', None, False, None, None,
+             True, None, None, None),
+            ('status', 'test 2', 'fail', None, False, 'tap meta',
+             b'test missing from TAP output', True, 'text/plain; charset=UTF8',
+             None, None),
+            ('status', 'test 3 third test', 'fail', None, False, None, None,
+             True, None, None, None)])
 
     def test_missing_test_no_plan_adds_error(self):
         # A file
         # ok first test
         # not ok 3 third test
         # results in three tests, with the second being created
-        self.tap.write('ok first test\n')
-        self.tap.write('not ok 3 third test\n')
+        self.tap.write(_u('ok first test\n'))
+        self.tap.write(_u('not ok 3 third test\n'))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            'test test 1 first test',
-            'success test 1 first test',
-            'test test 2',
-            'error test 2 [',
-            'test missing from TAP output',
-            ']',
-            'test test 3 third test',
-            'failure test 3 third test',
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([
+            ('status', 'test 1 first test', 'success', None, False, None, None,
+             True, None, None, None),
+            ('status', 'test 2', 'fail', None, False, 'tap meta',
+             b'test missing from TAP output', True, 'text/plain; charset=UTF8',
+             None, None),
+            ('status', 'test 3 third test', 'fail', None, False, None, None,
+             True, None, None, None)])
 
     def test_four_tests_in_a_row_trailing_plan(self):
         # A file
@@ -296,25 +253,23 @@ class TestTAP2SubUnit(unittest.TestCase):
         # not ok 4 - fourth
         # 1..4
         # results in four tests numbered and named
-        self.tap.write('ok 1 - first test in a script with trailing plan\n')
-        self.tap.write('not ok 2 - second\n')
-        self.tap.write('ok 3 - third\n')
-        self.tap.write('not ok 4 - fourth\n')
-        self.tap.write('1..4\n')
+        self.tap.write(_u('ok 1 - first test in a script with trailing plan\n'))
+        self.tap.write(_u('not ok 2 - second\n'))
+        self.tap.write(_u('ok 3 - third\n'))
+        self.tap.write(_u('not ok 4 - fourth\n'))
+        self.tap.write(_u('1..4\n'))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            'test test 1 - first test in a script with trailing plan',
-            'success test 1 - first test in a script with trailing plan',
-            'test test 2 - second',
-            'failure test 2 - second',
-            'test test 3 - third',
-            'success test 3 - third',
-            'test test 4 - fourth',
-            'failure test 4 - fourth'
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([
+            ('status', 'test 1 - first test in a script with trailing plan',
+             'success', None, False, None, None, True, None, None, None),
+            ('status', 'test 2 - second', 'fail', None, False, None, None,
+             True, None, None, None),
+            ('status', 'test 3 - third', 'success', None, False, None, None,
+             True, None, None, None),
+            ('status', 'test 4 - fourth', 'fail', None, False, None, None,
+             True, None, None, None)])
 
     def test_four_tests_in_a_row_with_plan(self):
         # A file
@@ -324,25 +279,23 @@ class TestTAP2SubUnit(unittest.TestCase):
         # ok 3 - third
         # not ok 4 - fourth
         # results in four tests numbered and named
-        self.tap.write('1..4\n')
-        self.tap.write('ok 1 - first test in a script with a plan\n')
-        self.tap.write('not ok 2 - second\n')
-        self.tap.write('ok 3 - third\n')
-        self.tap.write('not ok 4 - fourth\n')
+        self.tap.write(_u('1..4\n'))
+        self.tap.write(_u('ok 1 - first test in a script with a plan\n'))
+        self.tap.write(_u('not ok 2 - second\n'))
+        self.tap.write(_u('ok 3 - third\n'))
+        self.tap.write(_u('not ok 4 - fourth\n'))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            'test test 1 - first test in a script with a plan',
-            'success test 1 - first test in a script with a plan',
-            'test test 2 - second',
-            'failure test 2 - second',
-            'test test 3 - third',
-            'success test 3 - third',
-            'test test 4 - fourth',
-            'failure test 4 - fourth'
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([
+            ('status', 'test 1 - first test in a script with a plan',
+             'success', None, False, None, None, True, None, None, None),
+            ('status', 'test 2 - second', 'fail', None, False, None, None,
+             True, None, None, None),
+            ('status', 'test 3 - third', 'success', None, False, None, None,
+             True, None, None, None),
+            ('status', 'test 4 - fourth', 'fail', None, False, None, None,
+             True, None, None, None)])
 
     def test_four_tests_in_a_row_no_plan(self):
         # A file
@@ -351,46 +304,43 @@ class TestTAP2SubUnit(unittest.TestCase):
         # ok 3 - third
         # not ok 4 - fourth
         # results in four tests numbered and named
-        self.tap.write('ok 1 - first test in a script with no plan at all\n')
-        self.tap.write('not ok 2 - second\n')
-        self.tap.write('ok 3 - third\n')
-        self.tap.write('not ok 4 - fourth\n')
+        self.tap.write(_u('ok 1 - first test in a script with no plan at all\n'))
+        self.tap.write(_u('not ok 2 - second\n'))
+        self.tap.write(_u('ok 3 - third\n'))
+        self.tap.write(_u('not ok 4 - fourth\n'))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            'test test 1 - first test in a script with no plan at all',
-            'success test 1 - first test in a script with no plan at all',
-            'test test 2 - second',
-            'failure test 2 - second',
-            'test test 3 - third',
-            'success test 3 - third',
-            'test test 4 - fourth',
-            'failure test 4 - fourth'
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([
+            ('status', 'test 1 - first test in a script with no plan at all',
+             'success', None, False, None, None, True, None, None, None),
+            ('status', 'test 2 - second', 'fail', None, False, None, None,
+             True, None, None, None),
+            ('status', 'test 3 - third', 'success', None, False, None, None,
+             True, None, None, None),
+            ('status', 'test 4 - fourth', 'fail', None, False, None, None,
+             True, None, None, None)])
 
     def test_todo_and_skip(self):
         # A file
         # not ok 1 - a fail but # TODO but is TODO
         # not ok 2 - another fail # SKIP instead
         # results in two tests, numbered and commented.
-        self.tap.write("not ok 1 - a fail but # TODO but is TODO\n")
-        self.tap.write("not ok 2 - another fail # SKIP instead\n")
+        self.tap.write(_u("not ok 1 - a fail but # TODO but is TODO\n"))
+        self.tap.write(_u("not ok 2 - another fail # SKIP instead\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            'test test 1 - a fail but',
-            'xfail test 1 - a fail but [',
-            'but is TODO',
-            ']',
-            'test test 2 - another fail',
-            'skip test 2 - another fail [',
-            'instead',
-            ']',
-            ],
-            self.subunit.getvalue().splitlines())
+        self.subunit.seek(0)
+        events = StreamResult()
+        subunit.ByteStreamToStreamResult(self.subunit).run(events)
+        self.check_events([
+            ('status', 'test 1 - a fail but', 'xfail', None, False,
+             'tap comment', b'but is TODO', True, 'text/plain; charset=UTF8',
+             None, None),
+            ('status', 'test 2 - another fail', 'skip', None, False,
+             'tap comment', b'instead', True, 'text/plain; charset=UTF8',
+             None, None)])
 
     def test_leading_comments_add_to_next_test_log(self):
         # A file
@@ -399,21 +349,17 @@ class TestTAP2SubUnit(unittest.TestCase):
         # ok
         # results in a single test with the comment included
         # in the first test and not the second.
-        self.tap.write("# comment\n")
-        self.tap.write("ok\n")
-        self.tap.write("ok\n")
+        self.tap.write(_u("# comment\n"))
+        self.tap.write(_u("ok\n"))
+        self.tap.write(_u("ok\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            'test test 1',
-            'success test 1 [',
-            '# comment',
-            ']',
-            'test test 2',
-            'success test 2',
-            ],
-            self.subunit.getvalue().splitlines())
+        self.check_events([
+            ('status', 'test 1', 'success', None, False, 'tap comment',
+             b'# comment', True, 'text/plain; charset=UTF8', None, None),
+            ('status', 'test 2', 'success', None, False, None, None, True,
+             None, None, None)])
     
     def test_trailing_comments_are_included_in_last_test_log(self):
         # A file
@@ -422,24 +368,20 @@ class TestTAP2SubUnit(unittest.TestCase):
         # # comment
         # results in a two tests, with the second having the comment
         # attached to its log.
-        self.tap.write("ok\n")
-        self.tap.write("ok\n")
-        self.tap.write("# comment\n")
+        self.tap.write(_u("ok\n"))
+        self.tap.write(_u("ok\n"))
+        self.tap.write(_u("# comment\n"))
         self.tap.seek(0)
         result = subunit.TAP2SubUnit(self.tap, self.subunit)
         self.assertEqual(0, result)
-        self.assertEqual([
-            'test test 1',
-            'success test 1',
-            'test test 2',
-            'success test 2 [',
-            '# comment',
-            ']',
-            ],
-            self.subunit.getvalue().splitlines())
-
+        self.check_events([
+            ('status', 'test 1', 'success', None, False, None, None, True,
+             None, None, None),
+            ('status', 'test 2', 'success', None, False, 'tap comment',
+             b'# comment', True, 'text/plain; charset=UTF8', None, None)])
 
-def test_suite():
-    loader = subunit.tests.TestUtil.TestLoader()
-    result = loader.loadTestsFromName(__name__)
-    return result
+    def check_events(self, events):
+        self.subunit.seek(0)
+        eventstream = StreamResult()
+        subunit.ByteStreamToStreamResult(self.subunit).run(eventstream)
+        self.assertEqual(events, eventstream._events)
diff --git a/lib/subunit/python/subunit/tests/test_test_protocol.py b/lib/subunit/python/subunit/tests/test_test_protocol.py
index 7831ba1..c6008f4 100644
--- a/lib/subunit/python/subunit/tests/test_test_protocol.py
+++ b/lib/subunit/python/subunit/tests/test_test_protocol.py
@@ -34,9 +34,14 @@ except ImportError:
         Python27TestResult,
         ExtendedTestResult,
         )
+from testtools.matchers import Contains
 
 import subunit
-from subunit import _remote_exception_str, _remote_exception_str_chunked
+from subunit.tests import (
+    _remote_exception_repr,
+    _remote_exception_str,
+    _remote_exception_str_chunked,
+    )
 import subunit.iso8601 as iso8601
 
 
@@ -104,10 +109,10 @@ class TestTestProtocolServerPipe(unittest.TestCase):
         bing = subunit.RemotedTestCase("bing crosby")
         an_error = subunit.RemotedTestCase("an error")
         self.assertEqual(client.errors,
-                         [(an_error, _remote_exception_str + '\n')])
+                         [(an_error, _remote_exception_repr + '\n')])
         self.assertEqual(
             client.failures,
-            [(bing, _remote_exception_str + ": "
+            [(bing, _remote_exception_repr + ": "
               + details_to_str({'traceback': text_content(traceback)}) + "\n")])
         self.assertEqual(client.testsRun, 3)
 
@@ -962,7 +967,7 @@ class TestRemotedTestCase(unittest.TestCase):
                          "'A test description'>", "%r" % test)
         result = unittest.TestResult()
         test.run(result)
-        self.assertEqual([(test, _remote_exception_str + ": "
+        self.assertEqual([(test, _remote_exception_repr + ": "
                                  "Cannot run RemotedTestCases.\n\n")],
                          result.errors)
         self.assertEqual(1, result.testsRun)
@@ -1128,9 +1133,10 @@ class TestIsolatedTestSuite(TestCase):
         self.assertEqual(self.SampleTestToIsolate.TEST, False)
 
 
-class TestTestProtocolClient(unittest.TestCase):
+class TestTestProtocolClient(TestCase):
 
     def setUp(self):
+        super(TestTestProtocolClient, self).setUp()
         self.io = BytesIO()
         self.protocol = subunit.TestProtocolClient(self.io)
         self.unicode_test = PlaceHolder(_u('\u2603'))
@@ -1191,15 +1197,23 @@ class TestTestProtocolClient(unittest.TestCase):
         """Test addFailure on a TestProtocolClient with details."""
         self.protocol.addFailure(
             self.test, details=self.sample_tb_details)
-        self.assertEqual(
-            self.io.getvalue(),
+        self.assertThat([
             _b(("failure: %s [ multipart\n"
             "Content-Type: text/plain\n"
             "something\n"
             "F\r\nserialised\nform0\r\n"
             "Content-Type: text/x-traceback;charset=utf8,language=python\n"
-            "traceback\n" + _remote_exception_str_chunked + ": boo qux\n0\r\n"
-            "]\n") % self.test.id()))
+            "traceback\n" + _remote_exception_str_chunked +
+            "]\n") % self.test.id()),
+            _b(("failure: %s [ multipart\n"
+            "Content-Type: text/plain\n"
+            "something\n"
+            "F\r\nserialised\nform0\r\n"
+            "Content-Type: text/x-traceback;language=python,charset=utf8\n"
+            "traceback\n" + _remote_exception_str_chunked +
+            "]\n") % self.test.id()),
+            ],
+            Contains(self.io.getvalue())),
 
     def test_add_error(self):
         """Test stopTest on a TestProtocolClient."""
@@ -1215,15 +1229,23 @@ class TestTestProtocolClient(unittest.TestCase):
         """Test stopTest on a TestProtocolClient with details."""
         self.protocol.addError(
             self.test, details=self.sample_tb_details)
-        self.assertEqual(
-            self.io.getvalue(),
+        self.assertThat([
             _b(("error: %s [ multipart\n"
             "Content-Type: text/plain\n"
             "something\n"
             "F\r\nserialised\nform0\r\n"
             "Content-Type: text/x-traceback;charset=utf8,language=python\n"
-            "traceback\n" + _remote_exception_str_chunked + ": boo qux\n0\r\n"
-            "]\n") % self.test.id()))
+            "traceback\n" + _remote_exception_str_chunked +
+            "]\n") % self.test.id()),
+            _b(("error: %s [ multipart\n"
+            "Content-Type: text/plain\n"
+            "something\n"
+            "F\r\nserialised\nform0\r\n"
+            "Content-Type: text/x-traceback;language=python,charset=utf8\n"
+            "traceback\n" + _remote_exception_str_chunked +
+            "]\n") % self.test.id()),
+            ],
+            Contains(self.io.getvalue())),
 
     def test_add_expected_failure(self):
         """Test addExpectedFailure on a TestProtocolClient."""
@@ -1239,16 +1261,23 @@ class TestTestProtocolClient(unittest.TestCase):
         """Test addExpectedFailure on a TestProtocolClient with details."""
         self.protocol.addExpectedFailure(
             self.test, details=self.sample_tb_details)
-        self.assertEqual(
-            self.io.getvalue(),
+        self.assertThat([
             _b(("xfail: %s [ multipart\n"
             "Content-Type: text/plain\n"
             "something\n"
             "F\r\nserialised\nform0\r\n"
             "Content-Type: text/x-traceback;charset=utf8,language=python\n"
-            "traceback\n" + _remote_exception_str_chunked + ": boo qux\n0\r\n"
-            "]\n") % self.test.id()))
-
+            "traceback\n" + _remote_exception_str_chunked +
+            "]\n") % self.test.id()),
+            _b(("xfail: %s [ multipart\n"
+            "Content-Type: text/plain\n"
+            "something\n"
+            "F\r\nserialised\nform0\r\n"
+            "Content-Type: text/x-traceback;language=python,charset=utf8\n"
+            "traceback\n" + _remote_exception_str_chunked +
+            "]\n") % self.test.id()),
+            ],
+            Contains(self.io.getvalue())),
 
     def test_add_skip(self):
         """Test addSkip on a TestProtocolClient."""
@@ -1324,14 +1353,10 @@ class TestTestProtocolClient(unittest.TestCase):
 
     def test_tags_both(self):
         self.protocol.tags(set(['quux']), set(['bar']))
-        self.assertEqual(_b("tags: quux -bar\n"), self.io.getvalue())
+        self.assertThat(
+            [b"tags: quux -bar\n", b"tags: -bar quux\n"],
+            Contains(self.io.getvalue()))
 
     def test_tags_gone(self):
         self.protocol.tags(set(), set(['bar']))
         self.assertEqual(_b("tags: -bar\n"), self.io.getvalue())
-
-
-def test_suite():
-    loader = subunit.tests.TestUtil.TestLoader()
-    result = loader.loadTestsFromName(__name__)
-    return result
diff --git a/lib/subunit/python/subunit/tests/test_test_results.py b/lib/subunit/python/subunit/tests/test_test_results.py
index ff74b9a..44f95b3 100644
--- a/lib/subunit/python/subunit/tests/test_test_results.py
+++ b/lib/subunit/python/subunit/tests/test_test_results.py
@@ -564,9 +564,3 @@ class TestCsvResult(testtools.TestCase):
         stream = StringIO()
         subunit.test_results.CsvResult(stream)
         self.assertEqual([], self.parse_stream(stream))
-
-
-def test_suite():
-    loader = subunit.tests.TestUtil.TestLoader()
-    result = loader.loadTestsFromName(__name__)
-    return result
diff --git a/lib/subunit/runtests.py b/lib/subunit/runtests.py
deleted file mode 100755
index 8ecc6cd..0000000
--- a/lib/subunit/runtests.py
+++ /dev/null
@@ -1,138 +0,0 @@
-#!/usr/bin/env python
-# -*- Mode: python -*-
-#
-# Copyright (C) 2004 Canonical.com
-#       Author:      Robert Collins <robert.collins at canonical.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
-
-import unittest
-from subunit.tests.TestUtil import TestVisitor, TestSuite
-import subunit
-import sys
-import os
-import shutil
-import logging
-
-class ParameterisableTextTestRunner(unittest.TextTestRunner):
-    """I am a TextTestRunner whose result class is
-    parameterisable without further subclassing"""
-    def __init__(self, **args):
-        unittest.TextTestRunner.__init__(self, **args)
-        self._resultFactory=None
-    def resultFactory(self, *args):
-        """set or retrieve the result factory"""
-        if args:
-            self._resultFactory=args[0]
-            return self
-        if self._resultFactory is None:
-            self._resultFactory=unittest._TextTestResult
-        return self._resultFactory
-
-    def _makeResult(self):
-        return self.resultFactory()(self.stream, self.descriptions, self.verbosity)
-
-
-class EarlyStoppingTextTestResult(unittest._TextTestResult):
-    """I am a TextTestResult that can optionally stop at the first failure
-    or error"""
-
-    def addError(self, test, err):
-        unittest._TextTestResult.addError(self, test, err)
-        if self.stopOnError():
-            self.stop()
-
-    def addFailure(self, test, err):
-        unittest._TextTestResult.addError(self, test, err)
-        if self.stopOnFailure():
-            self.stop()
-
-    def stopOnError(self, *args):
-        """should this result indicate an abort when an error occurs?
-        TODO parameterise this"""
-        return True
-
-    def stopOnFailure(self, *args):
-        """should this result indicate an abort when a failure error occurs?
-        TODO parameterise this"""
-        return True
-
-
-def earlyStopFactory(*args, **kwargs):
-    """return a an early stopping text test result"""
-    result=EarlyStoppingTextTestResult(*args, **kwargs)
-    return result
-
-
-class ShellTests(subunit.ExecTestCase):
-
-    def test_sourcing(self):
-        """./shell/tests/test_source_library.sh"""
-
-    def test_functions(self):
-        """./shell/tests/test_function_output.sh"""
-
-
-def test_suite():
-    result = TestSuite()
-    result.addTest(subunit.test_suite())
-    result.addTest(ShellTests('test_sourcing'))
-    result.addTest(ShellTests('test_functions'))
-    return result
-
-
-class filteringVisitor(TestVisitor):
-    """I accrue all the testCases I visit that pass a regexp filter on id
-    into my suite
-    """
-
-    def __init__(self, filter):
-        import re
-        TestVisitor.__init__(self)
-        self._suite=None
-        self.filter=re.compile(filter)
-
-    def suite(self):
-        """answer the suite we are building"""
-        if self._suite is None:
-            self._suite=TestSuite()
-        return self._suite
-
-    def visitCase(self, aCase):
-        if self.filter.match(aCase.id()):
-            self.suite().addTest(aCase)
-
-
-def main(argv):
-    """To parameterise what tests are run, run this script like so:
-    python test_all.py REGEX
-    i.e.
-    python test_all.py .*Protocol.*
-    to run all tests with Protocol in their id."""
-    if len(argv) > 1:
-        pattern = argv[1]
-    else:
-        pattern = ".*"
-    visitor = filteringVisitor(pattern)
-    test_suite().visit(visitor)
-    runner = ParameterisableTextTestRunner(verbosity=2)
-    runner.resultFactory(unittest._TextTestResult)
-    if not runner.run(visitor.suite()).wasSuccessful():
-        return 1
-    return 0
-
-if __name__ == '__main__':
-    sys.exit(main(sys.argv))
diff --git a/lib/subunit/setup.py b/lib/subunit/setup.py
index 1a0b192..d42d3d7 100755
--- a/lib/subunit/setup.py
+++ b/lib/subunit/setup.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+import os.path
 try:
     # If the user has setuptools / distribute installed, use it
     from setuptools import setup
@@ -9,8 +10,12 @@ except ImportError:
 else:
     extra = {
         'install_requires': [
-            'testtools>=0.9.23',
-        ]
+            'extras',
+            'testtools>=0.9.34',
+        ],
+        'tests_require': [
+            'testscenarios',
+        ],
     }
 
 
@@ -31,6 +36,9 @@ VERSION = (
     or "0.0")
 
 
+relpath = os.path.dirname(__file__)
+if relpath:
+    os.chdir(relpath)
 setup(
     name='python-subunit',
     version=VERSION,
@@ -49,14 +57,18 @@ setup(
     packages=['subunit', 'subunit.tests'],
     package_dir={'subunit': 'python/subunit'},
     scripts = [
-        'filters/subunit2gtk',
-        'filters/subunit2junitxml',
-        'filters/subunit2pyunit',
+        'filters/subunit-1to2',
+        'filters/subunit-2to1',
         'filters/subunit-filter',
         'filters/subunit-ls',
         'filters/subunit-notify',
+        'filters/subunit-output',
         'filters/subunit-stats',
         'filters/subunit-tags',
+        'filters/subunit2csv',
+        'filters/subunit2gtk',
+        'filters/subunit2junitxml',
+        'filters/subunit2pyunit',
         'filters/tap2subunit',
     ],
     **extra
diff --git a/lib/testtools/.testr.conf b/lib/testtools/.testr.conf
index 8a65628..e695109 100644
--- a/lib/testtools/.testr.conf
+++ b/lib/testtools/.testr.conf
@@ -1,4 +1,4 @@
 [DEFAULT]
-test_command=${PYTHON:-python} -m subunit.run discover . $LISTOPT $IDOPTION
+test_command=${PYTHON:-python} -m subunit.run $LISTOPT $IDOPTION testtools.tests.test_suite
 test_id_option=--load-list $IDFILE
 test_list_option=--list
diff --git a/lib/testtools/LICENSE b/lib/testtools/LICENSE
index d59dc7c..21010cc 100644
--- a/lib/testtools/LICENSE
+++ b/lib/testtools/LICENSE
@@ -17,6 +17,7 @@ The testtools authors are:
  * Gavin Panella
  * Martin Pool
  * Vincent Ladeuil
+ * Nikola Đipanov
 
 and are collectively referred to as "testtools developers".
 
diff --git a/lib/testtools/MANIFEST.in b/lib/testtools/MANIFEST.in
index 7da191a..4619349 100644
--- a/lib/testtools/MANIFEST.in
+++ b/lib/testtools/MANIFEST.in
@@ -2,8 +2,8 @@ include LICENSE
 include Makefile
 include MANIFEST.in
 include NEWS
-include README
-include .bzrignore
+include README.rst
+include .gitignore
 graft doc
 graft doc/_static
 graft doc/_templates
diff --git a/lib/testtools/Makefile b/lib/testtools/Makefile
index b3e40ec..c637123 100644
--- a/lib/testtools/Makefile
+++ b/lib/testtools/Makefile
@@ -1,4 +1,4 @@
-# See README for copyright and licensing details.
+# Copyright (c) 2008-2013 testtools developers. See LICENSE for details.
 
 PYTHON=python
 SOURCES=$(shell find testtools -name "*.py")
@@ -21,11 +21,11 @@ prerelease:
 	-rm MANIFEST
 
 release:
-	./setup.py sdist upload --sign
+	./setup.py sdist bdist_wheel upload --sign
 	$(PYTHON) scripts/_lp_release.py
 
 snapshot: prerelease
-	./setup.py sdist
+	./setup.py sdist bdist_wheel
 
 ### Documentation ###
 
@@ -34,7 +34,7 @@ apidocs:
 	PYTHONWARNINGS='ignore::DeprecationWarning' \
 		pydoctor --make-html --add-package testtools \
 		--docformat=restructuredtext --project-name=testtools \
-		--project-url=https://launchpad.net/testtools
+		--project-url=https://github.com/testing-cabal/testtools
 
 doc/news.rst:
 	ln -s ../NEWS doc/news.rst
diff --git a/lib/testtools/NEWS b/lib/testtools/NEWS
index ac88fc1..5176486 100644
--- a/lib/testtools/NEWS
+++ b/lib/testtools/NEWS
@@ -3,15 +3,75 @@ testtools NEWS
 
 Changes and improvements to testtools_, grouped by release.
 
+
 NEXT
 ~~~~
 
+1.5.0
+~~~~~
+
+Improvements
+------------
+
+* When an import error happens ``testtools.run`` will now show the full
+  error rather than just the name of the module that failed to import.
+  (Robert Collins)
+
+1.4.0
+~~~~~
+
+Changes
+-------
+
+* ``testtools.TestCase`` now inherits from unittest2.TestCase, which
+  provides a ``setUpClass`` for upcalls on Python 2.6.
+  (Robert Collins, #1393283)
+
+1.3.0
+~~~~~
+
 Changes
 -------
 
+* Fixed our setup.py to use setup_requires to ensure the import dependencies
+  for testtools are present before setup.py runs (as setup.py imports testtools
+  to read out the version number). (Robert Collins)
+
+* Support setUpClass skipping with self.skipException. Previously this worked
+  with unittest from 2.7 and above but was not supported by testtools - it was
+  a happy accident. Since we now hard depend on unittest2, we need to invert
+  our exception lookup priorities to support it. Regular skips done through
+  raise self.skipException will continue to work, since they were always caught
+  in our code - its because the suite type being used to implement setUpClass
+  has changed that an issue occured.
+  (Robert Collins, #1393068)
+
+1.2.1
+~~~~~
+
+Changes
+-------
+
+* Correctly express our unittest2 dependency: we don't work with old releases.
+  (Robert Collins)
+
+1.2.0
+~~~~~
+
+Changes
+-------
+
+* Depends on unittest2 for discovery functionality and the ``TestProgram`` base
+  class. This brings in many fixes made to discovery where previously we were
+  only using the discovery package or the version in the release of Python
+  that the test execution was occuring on. (Robert Collins, #1271133)
+
 * Fixed unit tests which were failing under pypy due to a change in the way
   pypy formats tracebacks. (Thomi Richards)
 
+* Fixed the testtools test suite to run correctly when run via ``unit2``
+  or ``testtools.run discover``.
+
 * Make `testtools.content.text_content` error if anything other than text
   is given as content. (Thomi Richards)
 
@@ -235,7 +295,7 @@ experimental and we might need to break it if it turns out to be unsuitable.
 
 Improvements
 ------------
-* ``assertRaises`` works properly for exception classes that have custom
+* ``assertRaises`` works properly for exception classes that have custom 
   metaclasses
 
 * ``ConcurrentTestSuite`` was silently eating exceptions that propagate from
@@ -616,7 +676,7 @@ Improvements
 * API documentation corrections. (Raphaël Badin)
 
 * ``ConcurrentTestSuite`` now takes an optional ``wrap_result`` parameter
-  that can be used to wrap the ``ThreadsafeForwardingResult``s created by
+  that can be used to wrap the ``ThreadsafeForwardingResults`` created by
   the suite.  (Jonathan Lange)
 
 * ``Tagger`` added.  It's a new ``TestResult`` that tags all tests sent to
diff --git a/lib/testtools/README b/lib/testtools/README
deleted file mode 100644
index dbc685b..0000000
--- a/lib/testtools/README
+++ /dev/null
@@ -1,89 +0,0 @@
-=========
-testtools
-=========
-
-testtools is a set of extensions to the Python standard library's unit testing
-framework.
-
-These extensions have been derived from years of experience with unit testing
-in Python and come from many different sources.
-
-
-Documentation
--------------
-
-If you would like to learn more about testtools, consult our documentation in
-the 'doc/' directory.  You might like to start at 'doc/overview.rst' or
-'doc/for-test-authors.rst'.
-
-
-Licensing
----------
-
-This project is distributed under the MIT license and copyright is owned by
-Jonathan M. Lange and the testtools authors. See LICENSE for details.
-
-Some code in 'testtools/run.py' is taken from Python's unittest module, and is
-copyright Steve Purcell and the Python Software Foundation, it is distributed
-under the same license as Python, see LICENSE for details.
-
-
-Required Dependencies
----------------------
-
- * Python 2.6+ or 3.0+
-
-If you would like to use testtools for earlier Python's, please use testtools
-0.9.15.
-
-
-Optional Dependencies
----------------------
-
-If you would like to use our undocumented, unsupported Twisted support, then
-you will need Twisted.
-
-If you want to use ``fixtures`` then you can either install fixtures (e.g. from
-https://launchpad.net/python-fixtures or http://pypi.python.org/pypi/fixtures)
-or alternatively just make sure your fixture objects obey the same protocol.
-
-
-Bug reports and patches
------------------------
-
-Please report bugs using Launchpad at <https://bugs.launchpad.net/testtools>.
-Patches can also be submitted via Launchpad, or mailed to the author.  You can
-mail the author directly at jml at mumak.net.
-
-There's no mailing list for this project yet, however the testing-in-python
-mailing list may be a useful resource:
-
- * Address: testing-in-python at lists.idyll.org
- * Subscription link: http://lists.idyll.org/listinfo/testing-in-python
-
-
-History
--------
-
-testtools used to be called 'pyunit3k'.  The name was changed to avoid
-conflating the library with the Python 3.0 release (commonly referred to as
-'py3k').
-
-
-Thanks
-------
-
- * Canonical Ltd
- * Bazaar
- * Twisted Matrix Labs
- * Robert Collins
- * Andrew Bennetts
- * Benjamin Peterson
- * Jamu Kakar
- * James Westby
- * Martin [gz]
- * Michael Hudson-Doyle
- * Aaron Bentley
- * Christian Kampka
- * Gavin Panella
- * Martin Pool
diff --git a/lib/testtools/doc/for-framework-folk.rst b/lib/testtools/doc/for-framework-folk.rst
index ecc11f3..5c83ab1 100644
--- a/lib/testtools/doc/for-framework-folk.rst
+++ b/lib/testtools/doc/for-framework-folk.rst
@@ -14,13 +14,17 @@ unit-tested project, are trying to get one testing framework to play nicely
 with another or are hacking away at getting your test suite to run in parallel
 over a heterogenous cluster of machines, this guide is for you.
 
-This manual is a summary.  You can get details by consulting the `testtools
-API docs`_.
+This manual is a summary. You can get details by consulting the
+:doc:`testtools API docs </api>`.
 
 
 Extensions to TestCase
 ======================
 
+In addition to the ``TestCase`` specific methods, we have extensions for
+``TestSuite`` that also apply to ``TestCase`` (because ``TestCase`` and
+``TestSuite`` follow the Composite pattern).
+
 Custom exception handling
 -------------------------
 
@@ -46,9 +50,9 @@ provide a custom ``RunTest`` to a ``TestCase``.  The ``RunTest`` object can
 change everything about how the test executes.
 
 To work with ``testtools.TestCase``, a ``RunTest`` must have a factory that
-takes a test and an optional list of exception handlers.  Instances returned
-by the factory must have a ``run()`` method that takes an optional ``TestResult``
-object.
+takes a test and an optional list of exception handlers and an optional
+last_resort handler.  Instances returned by the factory must have a ``run()``
+method that takes an optional ``TestResult`` object.
 
 The default is ``testtools.runtest.RunTest``, which calls ``setUp``, the test
 method, ``tearDown`` and clean ups (see :ref:`addCleanup`) in the normal, vanilla
@@ -78,6 +82,15 @@ Test renaming
 instance to one with a new name.  This is helpful for implementing test
 parameterization.
 
+.. _force_failure:
+
+Delayed Test Failure
+--------------------
+
+Setting the ``testtools.TestCase.force_failure`` instance variable to True will
+cause ``testtools.RunTest`` to fail the test case after the test has finished.
+This is useful when you want to cause a test to fail, but don't want to
+prevent the remainder of the test code from being executed.
 
 Test placeholders
 =================
@@ -104,9 +117,174 @@ e.g.::
   I record an event                                                   [OK]
 
 
+Test instance decorators
+========================
+
+DecorateTestCaseResult
+----------------------
+
+This object calls out to your code when ``run`` / ``__call__`` are called and
+allows the result object that will be used to run the test to be altered. This
+is very useful when working with a test runner that doesn't know your test case
+requirements. For instance, it can be used to inject a ``unittest2`` compatible
+adapter when someone attempts to run your test suite with a ``TestResult`` that
+does not support ``addSkip`` or other ``unittest2`` methods. Similarly it can
+aid the migration to ``StreamResult``.
+
+e.g.::
+
+ >>> suite = TestSuite()
+ >>> suite = DecorateTestCaseResult(suite, ExtendedToOriginalDecorator)
+
 Extensions to TestResult
 ========================
 
+StreamResult
+------------
+
+``StreamResult`` is a new API for dealing with test case progress that supports
+concurrent and distributed testing without the various issues that
+``TestResult`` has such as buffering in multiplexers.
+
+The design has several key principles:
+
+* Nothing that requires up-front knowledge of all tests.
+
+* Deal with tests running in concurrent environments, potentially distributed
+  across multiple processes (or even machines). This implies allowing multiple
+  tests to be active at once, supplying time explicitly, being able to
+  differentiate between tests running in different contexts and removing any
+  assumption that tests are necessarily in the same process.
+
+* Make the API as simple as possible - each aspect should do one thing well.
+
+The ``TestResult`` API this is intended to replace has three different clients.
+
+* Each executing ``TestCase`` notifies the ``TestResult`` about activity.
+
+* The testrunner running tests uses the API to find out whether the test run
+  had errors, how many tests ran and so on.
+
+* Finally, each ``TestCase`` queries the ``TestResult`` to see whether the test
+  run should be aborted.
+
+With ``StreamResult`` we need to be able to provide a ``TestResult`` compatible
+adapter (``StreamToExtendedDecorator``) to allow incremental migration.
+However, we don't need to conflate things long term. So - we define three
+separate APIs, and merely mix them together to provide the
+``StreamToExtendedDecorator``. ``StreamResult`` is the first of these APIs -
+meeting the needs of ``TestCase`` clients. It handles events generated by
+running tests. See the API documentation for ``testtools.StreamResult`` for
+details.
+
+StreamSummary
+-------------
+
+Secondly we define the ``StreamSummary`` API which takes responsibility for
+collating errors, detecting incomplete tests and counting tests. This provides
+a compatible API with those aspects of ``TestResult``. Again, see the API
+documentation for ``testtools.StreamSummary``.
+
+TestControl
+-----------
+
+Lastly we define the ``TestControl`` API which is used to provide the
+``shouldStop`` and ``stop`` elements from ``TestResult``. Again, see the API
+documentation for ``testtools.TestControl``. ``TestControl`` can be paired with
+a ``StreamFailFast`` to trigger aborting a test run when a failure is observed.
+Aborting multiple workers in a distributed environment requires hooking
+whatever signalling mechanism the distributed environment has up to a
+``TestControl`` in each worker process.
+
+StreamTagger
+------------
+
+A ``StreamResult`` filter that adds or removes tags from events::
+
+    >>> from testtools import StreamTagger
+    >>> sink = StreamResult()
+    >>> result = StreamTagger([sink], set(['add']), set(['discard']))
+    >>> result.startTestRun()
+    >>> # Run tests against result here.
+    >>> result.stopTestRun()
+
+StreamToDict
+------------
+
+A simplified API for dealing with ``StreamResult`` streams. Each test is
+buffered until it completes and then reported as a trivial dict. This makes
+writing analysers very easy - you can ignore all the plumbing and just work
+with the result. e.g.::
+
+    >>> from testtools import StreamToDict
+    >>> def handle_test(test_dict):
+    ...     print(test_dict['id'])
+    >>> result = StreamToDict(handle_test)
+    >>> result.startTestRun()
+    >>> # Run tests against result here.
+    >>> # At stopTestRun() any incomplete buffered tests are announced.
+    >>> result.stopTestRun()
+
+ExtendedToStreamDecorator
+-------------------------
+
+This is a hybrid object that combines both the ``Extended`` and ``Stream``
+``TestResult`` APIs into one class, but only emits ``StreamResult`` events.
+This is useful when a ``StreamResult`` stream is desired, but you cannot
+be sure that the tests which will run have been updated to the ``StreamResult``
+API.
+
+StreamToExtendedDecorator
+-------------------------
+
+This is a simple converter that emits the ``ExtendedTestResult`` API in
+response to events from the ``StreamResult`` API. Useful when outputting
+``StreamResult`` events from a ``TestCase`` but the supplied ``TestResult``
+does not support the ``status`` and ``file`` methods.
+
+StreamToQueue
+-------------
+
+This is a ``StreamResult`` decorator for reporting tests from multiple threads
+at once. Each method submits an event to a supplied Queue object as a simple
+dict. See ``ConcurrentStreamTestSuite`` for a convenient way to use this.
+
+TimestampingStreamResult
+------------------------
+
+This is a ``StreamResult`` decorator for adding timestamps to events that lack
+them. This allows writing the simplest possible generators of events and
+passing the events via this decorator to get timestamped data. As long as
+no buffering/queueing or blocking happen before the timestamper sees the event
+the timestamp will be as accurate as if the original event had it.
+
+StreamResultRouter
+------------------
+
+This is a ``StreamResult`` which forwards events to an arbitrary set of target
+``StreamResult`` objects. Events that have no forwarding rule are passed onto
+an fallback ``StreamResult`` for processing. The mapping can be changed at
+runtime, allowing great flexibility and responsiveness to changes. Because
+The mapping can change dynamically and there could be the same recipient for
+two different maps, ``startTestRun`` and ``stopTestRun`` handling is fine
+grained and up to the user.
+
+If no fallback has been supplied, an unroutable event will raise an exception.
+
+For instance::
+
+    >>> router = StreamResultRouter()
+    >>> sink = doubles.StreamResult()
+    >>> router.add_rule(sink, 'route_code_prefix', route_prefix='0',
+    ...     consume_route=True)
+    >>> router.status(test_id='foo', route_code='0/1', test_status='uxsuccess')
+
+Would remove the ``0/`` from the route_code and forward the event like so::
+
+    >>> sink.status('test_id=foo', route_code='1', test_status='uxsuccess')
+
+See ``pydoc testtools.StreamResultRouter`` for details.
+
 TestResult.addSkip
 ------------------
 
@@ -215,12 +393,29 @@ ConcurrentTestSuite uses the helper to get a number of separate runnable
 objects with a run(result), runs them all in threads using the
 ThreadsafeForwardingResult to coalesce their activity.
 
+ConcurrentStreamTestSuite
+-------------------------
+
+A variant of ConcurrentTestSuite that uses the new StreamResult API instead of
+the TestResult API. ConcurrentStreamTestSuite coordinates running some number
+of test/suites concurrently, with one StreamToQueue per test/suite.
+
+Each test/suite gets given its own ExtendedToStreamDecorator +
+TimestampingStreamResult wrapped StreamToQueue instance, forwarding onto the
+StreamResult that ConcurrentStreamTestSuite.run was called with.
+
+ConcurrentStreamTestSuite is a thin shim and it is easy to implement your own
+specialised form if that is needed.
+
 FixtureSuite
 ------------
 
 A test suite that sets up a fixture_ before running any tests, and then tears
 it down after all of the tests are run. The fixture is *not* made available to
-any of the tests.
+any of the tests due to there being no standard channel for suites to pass
+information to the tests they contain (and we don't have enough data on what
+such a channel would need to achieve to design a good one yet - or even decide
+if it is a good idea).
 
 sorted_tests
 ------------
@@ -229,10 +424,30 @@ Given the composite structure of TestSuite / TestCase, sorting tests is
 problematic - you can't tell what functionality is embedded into custom Suite
 implementations. In order to deliver consistent test orders when using test
 discovery (see http://bugs.python.org/issue16709), testtools flattens and
-sorts tests that have the standard TestSuite, defines a new method sort_tests,
-which can be used by non-standard TestSuites to know when they should sort
-their tests.
+sorts tests that have the standard TestSuite, and defines a new method
+sort_tests, which can be used by non-standard TestSuites to know when they
+should sort their tests. An example implementation can be seen at
+``FixtureSuite.sorted_tests``.
+
+If there are duplicate test ids in a suite, ValueError will be raised.
+
+filter_by_ids
+-------------
+
+Similarly to ``sorted_tests`` running a subset of tests is problematic - the
+standard run interface provides no way to limit what runs. Rather than
+confounding the two problems (selection and execution) we defined a method
+that filters the tests in a suite (or a case) by their unique test id.
+If you a writing custom wrapping suites, consider implementing filter_by_ids
+to support this (though most wrappers that subclass ``unittest.TestSuite`` will
+work just fine [see ``testtools.testsuite.filter_by_ids`` for details.]
+
+Extensions to TestRunner
+========================
+
+To facilitate custom listing of tests, ``testtools.run.TestProgram`` attempts
+to call ``list`` on the ``TestRunner``, falling back to a generic
+implementation if it is not present.
 
-.. _`testtools API docs`: http://mumak.net/testtools/apidocs/
 .. _unittest: http://docs.python.org/library/unittest.html
 .. _fixture: http://pypi.python.org/pypi/fixtures
diff --git a/lib/testtools/doc/for-test-authors.rst b/lib/testtools/doc/for-test-authors.rst
index c9e6c6a..5deb7ce 100644
--- a/lib/testtools/doc/for-test-authors.rst
+++ b/lib/testtools/doc/for-test-authors.rst
@@ -11,7 +11,7 @@ automated testing already.
 If you are a test author of an unusually large or unusually unusual test
 suite, you might be interested in :doc:`for-framework-folk`.
 
-You might also be interested in the `testtools API docs`_.
+You might also be interested in the :doc:`testtools API docs </api>`.
 
 
 Introduction
@@ -163,7 +163,8 @@ The first argument to ``ExpectedException`` is the type of exception you
 expect to see raised.  The second argument is optional, and can be either a
 regular expression or a matcher. If it is a regular expression, the ``str()``
 of the raised exception must match the regular expression. If it is a matcher,
-then the raised exception object must match it.
+then the raised exception object must match it. The optional third argument
+``msg`` will cause the raised error to be annotated with that message.
 
 
 assertIn, assertNotIn
@@ -287,6 +288,60 @@ Which is roughly equivalent to::
       self.assertNotEqual(result, 50)
 
 
+``assert_that`` Function
+------------------------
+
+In addition to ``self.assertThat``, testtools also provides the ``assert_that``
+function in ``testtools.assertions`` This behaves like the method version does::
+
+    class TestSquare(TestCase):
+
+        def test_square():
+            result = square(7)
+            assert_that(result, Equals(49))
+
+        def test_square_silly():
+            result = square(7)
+            assert_that(result, Not(Equals(50)))
+
+
+Delayed Assertions
+~~~~~~~~~~~~~~~~~~
+
+A failure in the ``self.assertThat`` method will immediately fail the test: No
+more test code will be run after the assertion failure.
+
+The ``expectThat`` method behaves the same as ``assertThat`` with one
+exception: when failing the test it does so at the end of the test code rather
+than when the mismatch is detected. For example::
+
+  import subprocess
+
+  from testtools import TestCase
+  from testtools.matchers import Equals
+
+
+  class SomeProcessTests(TestCase):
+
+      def test_process_output(self):
+          process = subprocess.Popen(
+            ["my-app", "/some/path"],
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE
+          )
+
+          stdout, stderrr = process.communicate()
+
+          self.expectThat(process.returncode, Equals(0))
+          self.expectThat(stdout, Equals("Expected Output"))
+          self.expectThat(stderr, Equals(""))
+
+In this example, should the ``expectThat`` call fail, the failure will be
+recorded in the test result, but the test will continue as normal. If all
+three assertions fail, the test result will have three failures recorded, and
+the failure details for each failed assertion will be attached to the test
+result.
+
 Stock matchers
 --------------
 
@@ -407,7 +462,7 @@ example::
       except RuntimeError:
           exc_info = sys.exc_info()
       self.assertThat(exc_info, MatchesException(RuntimeError))
-      self.assertThat(exc_info, MatchesException(RuntimeError('bar'))
+      self.assertThat(exc_info, MatchesException(RuntimeError('bar')))
 
 Most of the time, you will want to uses `The raises helper`_ instead.
 
@@ -445,6 +500,18 @@ be able to do, if you think about it::
       self.assertThat('foo', MatchesRegex('fo+'))
 
 
+HasLength
+~~~~~~~~~
+
+Check the length of a collection.  The following assertion will fail::
+
+  self.assertThat([1, 2, 3], HasLength(2))
+
+But this one won't::
+
+  self.assertThat([1, 2, 3], HasLength(3))
+
+
 File- and path-related matchers
 -------------------------------
 
@@ -585,7 +652,7 @@ Used to add custom notes to a matcher.  For example::
   def test_annotate_example(self):
       result = 43
       self.assertThat(
-          result, Annotate("Not the answer to the Question!", Equals(42))
+          result, Annotate("Not the answer to the Question!", Equals(42)))
 
 Since the annotation is only ever displayed when there is a mismatch
 (e.g. when ``result`` does not equal 42), it's a good idea to phrase the note
@@ -613,7 +680,7 @@ matching. This can be used to aid in creating trivial matchers as functions, for
 example::
 
   def test_after_preprocessing_example(self):
-      def HasFileContent(content):
+      def PathHasFileContent(content):
           def _read(path):
               return open(path).read()
           return AfterPreprocessing(_read, Equals(content))
@@ -780,6 +847,35 @@ Which will produce the error message::
   MismatchError: 42 is not prime.
 
 
+MatchesPredicateWithParams
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sometimes you can't use a trivial predicate and instead need to pass in some
+parameters each time. In that case, MatchesPredicateWithParams is your go-to
+tool for creating ad hoc matchers. MatchesPredicateWithParams takes a predicate
+function and message and returns a factory to produce matchers from that. The
+predicate needs to return a boolean (or any truthy object), and accept the
+object to match + whatever was passed into the factory.
+
+For example, you might have an ``divisible`` function and want to make a
+matcher based on it::
+
+  def test_divisible_numbers(self):
+      IsDivisibleBy = MatchesPredicateWithParams(
+          divisible, '{0} is not divisible by {1}')
+      self.assertThat(7, IsDivisibleBy(1))
+      self.assertThat(7, IsDivisibleBy(7))
+      self.assertThat(7, IsDivisibleBy(2))
+      # This will fail.
+
+Which will produce the error message::
+
+  Traceback (most recent call last):
+    File "...", line ..., in test_divisible
+      self.assertThat(7, IsDivisibleBy(2))
+  MismatchError: 7 is not divisible by 2.
+
+
 Raises
 ~~~~~~
 
@@ -838,9 +934,9 @@ returns a non-None value.  For example::
 
   def test_is_divisible_by_example(self):
       # This succeeds, since IsDivisibleBy(5).match(10) returns None.
-      self.assertThat(10, IsDivisbleBy(5))
+      self.assertThat(10, IsDivisibleBy(5))
       # This fails, since IsDivisibleBy(7).match(10) returns a mismatch.
-      self.assertThat(10, IsDivisbleBy(7))
+      self.assertThat(10, IsDivisibleBy(7))
 
 The mismatch is responsible for what sort of error message the failing test
 generates.  Here's an example mismatch::
@@ -1201,6 +1297,13 @@ Here are some tips for converting your Trial tests into testtools tests.
   ``AsynchronousDeferredRunTest`` does not.  If you rely on this behavior, use
   ``AsynchronousDeferredRunTestForBrokenTwisted``.
 
+force_failure
+-------------
+
+Setting the ``testtools.TestCase.force_failure`` instance variable to ``True``
+will cause the test to be marked as a failure, but won't stop the test code
+from running (see :ref:`force_failure`).
+
 
 Test helpers
 ============
@@ -1280,6 +1383,29 @@ details of certain variables don't actually matter.
 See pages 419-423 of `xUnit Test Patterns`_ by Gerard Meszaros for a detailed
 discussion of creation methods.
 
+Test attributes
+---------------
+
+Inspired by the ``nosetests`` ``attr`` plugin, testtools provides support for
+marking up test methods with attributes, which are then exposed in the test
+id and can be used when filtering tests by id. (e.g. via ``--load-list``)::
+
+  from testtools.testcase import attr, WithAttributes
+
+  class AnnotatedTests(WithAttributes, TestCase):
+
+      @attr('simple')
+      def test_one(self):
+          pass
+
+      @attr('more', 'than', 'one')
+      def test_two(self):
+          pass
+
+      @attr('or')
+      @attr('stacked')
+      def test_three(self):
+          pass
 
 General helpers
 ===============
@@ -1288,7 +1414,7 @@ Conditional imports
 -------------------
 
 Lots of the time we would like to conditionally import modules.  testtools
-needs to do this itself, and graciously extends the ability to its users.
+uses the small library extras to do this. This used to be part of testtools.
 
 Instead of::
 
@@ -1317,9 +1443,9 @@ You can do::
 Safe attribute testing
 ----------------------
 
-``hasattr`` is broken_ on many versions of Python.  testtools provides
-``safe_hasattr``, which can be used to safely test whether an object has a
-particular attribute.
+``hasattr`` is broken_ on many versions of Python. The helper ``safe_hasattr``
+can be used to safely test whether an object has a particular attribute. Like
+``try_import`` this used to be in testtools but is now in extras.
 
 
 Nullary callables
@@ -1354,7 +1480,6 @@ Here, ``repr(nullary)`` will be the same as ``repr(f)``.
 .. _doctest: http://docs.python.org/library/doctest.html
 .. _Deferred: http://twistedmatrix.com/documents/current/core/howto/defer.html
 .. _discover: http://pypi.python.org/pypi/discover
-.. _`testtools API docs`: http://mumak.net/testtools/apidocs/
 .. _Distutils: http://docs.python.org/library/distutils.html
 .. _`setup configuration`: http://docs.python.org/distutils/configfile.html
 .. _broken: http://chipaca.com/post/3210673069/hasattr-17-less-harmful
diff --git a/lib/testtools/doc/hacking.rst b/lib/testtools/doc/hacking.rst
index 663eeac..ccfc155 100644
--- a/lib/testtools/doc/hacking.rst
+++ b/lib/testtools/doc/hacking.rst
@@ -2,6 +2,13 @@
 Contributing to testtools
 =========================
 
+Bugs and patches
+----------------
+
+`File bugs <https://bugs.launchpad.net/testtools/+filebug>` on Launchpad, and
+`send patches <https://github.com/testing-cabal/testtools/>` on Github.
+
+
 Coding style
 ------------
 
@@ -49,6 +56,21 @@ is often useful to see all levels of the stack. To do this, add
 ``run_tests_with = FullStackRunTest`` to the top of a test's class definition.
 
 
+Discussion
+----------
+
+When submitting a patch, it will help the review process a lot if there's a
+clear explanation of what the change does and why you think the change is a
+good idea.  For crasher bugs, this is generally a no-brainer, but for UI bugs
+& API tweaks, the reason something is an improvement might not be obvious, so
+it's worth spelling out.
+
+If you are thinking of implementing a new feature, you might want to have that
+discussion on the [mailing list](testtools-dev at lists.launchpad.net) before the
+patch goes up for review.  This is not at all mandatory, but getting feedback
+early can help avoid dead ends.
+
+
 Documentation
 -------------
 
@@ -63,7 +85,7 @@ Source layout
 -------------
 
 The top-level directory contains the ``testtools/`` package directory, and
-miscellaneous files like ``README`` and ``setup.py``.
+miscellaneous files like ``README.rst`` and ``setup.py``.
 
 The ``testtools/`` directory is the Python package itself.  It is separated
 into submodules for internal clarity, but all public APIs should be “promoted”
@@ -78,13 +100,13 @@ Tests belong in ``testtools/tests/``.
 Committing to trunk
 -------------------
 
-Testtools is maintained using bzr, with its trunk at lp:testtools. This gives
-every contributor the ability to commit their work to their own branches.
-However permission must be granted to allow contributors to commit to the trunk
-branch.
+Testtools is maintained using git, with its master repo at
+https://github.com/testing-cabal/testtools. This gives every contributor the
+ability to commit their work to their own branches. However permission must be
+granted to allow contributors to commit to the trunk branch.
 
-Commit access to trunk is obtained by joining the testtools-committers
-Launchpad team. Membership in this team is contingent on obeying the testtools
+Commit access to trunk is obtained by joining the `testing-cabal`_, either as an
+Owner or a Committer. Commit access is contingent on obeying the testtools
 contribution policy, see `Copyright Assignment`_ above.
 
 
@@ -92,22 +114,34 @@ Code Review
 -----------
 
 All code must be reviewed before landing on trunk. The process is to create a
-branch in launchpad, and submit it for merging to lp:testtools. It will then
-be reviewed before it can be merged to trunk. It will be reviewed by someone:
+branch on Github, and make a pull request into trunk. It will then be reviewed
+before it can be merged to trunk. It will be reviewed by someone:
 
 * not the author
-* a committer (member of the `~testtools-committers`_ team)
+* a committer
 
-As a special exception, while the testtools committers team is small and prone
-to blocking, a merge request from a committer that has not been reviewed after
-24 hours may be merged by that committer. When the team is larger this policy
-will be revisited.
+As a special exception, since there are few testtools committers and thus
+reviews are prone to blocking, a pull request from a committer that has not been
+reviewed after 24 hours may be merged by that committer. When the team is larger
+this policy will be revisited.
 
 Code reviewers should look for the quality of what is being submitted,
 including conformance with this HACKING file.
 
 Changes which all users should be made aware of should be documented in NEWS.
 
+We are now in full backwards compatibility mode - no more releases < 1.0.0, and 
+breaking compatibility will require consensus on the testtools-dev mailing list.
+Exactly what constitutes a backwards incompatible change is vague, but coarsely:
+
+* adding required arguments or required calls to something that used to work
+* removing keyword or position arguments, removing methods, functions or modules
+* changing behaviour someone may have reasonably depended on
+
+Some things are not compatibility issues:
+
+* changes to _ prefixed methods, functions, modules, packages.
+
 
 NEWS management
 ---------------
@@ -119,35 +153,42 @@ branches, the bullet points are kept alphabetically sorted. The release NEXT is
 permanently present at the top of the list.
 
 
-Release tasks
--------------
+Releasing
+---------
+
+Prerequisites
++++++++++++++
+
+Membership in the testing-cabal org on github as committer.
+
+Membership in the pypi testtools project as maintainer.
+
+Membership in the https://launchpad.net/~testtools-committers.
+
+Tasks
++++++
 
 #. Choose a version number, say X.Y.Z
-#. Branch from trunk to testtools-X.Y.Z
-#. In testtools-X.Y.Z, ensure __init__ has version ``(X, Y, Z, 'final', 0)``
-#. Replace NEXT in NEWS with the version number X.Y.Z, adjusting the reST.
+#. In trunk, ensure __init__ has version ``(X, Y, Z, 'final', 0)``
+#. Under NEXT in NEWS add a heading with the version number X.Y.Z.
 #. Possibly write a blurb into NEWS.
-#. Replace any additional references to NEXT with the version being
-   released. (There should be none other than the ones in these release tasks
-   which should not be replaced).
 #. Commit the changes.
-#. Tag the release, bzr tag testtools-X.Y.Z
+#. Tag the release, ``git tag -s testtools-X.Y.Z``
 #. Run 'make release', this:
    #. Creates a source distribution and uploads to PyPI
    #. Ensures all Fix Committed bugs are in the release milestone
    #. Makes a release on Launchpad and uploads the tarball
    #. Marks all the Fix Committed bugs as Fix Released
    #. Creates a new milestone
-#. Merge the release branch testtools-X.Y.Z into trunk. Before the commit,
-   add a NEXT heading to the top of NEWS and bump the version in __init__.py
+#. Change __version__ in __init__.py to the probable next version.
    e.g. to ``(X, Y, Z+1, 'dev', 0)``.
-#. Push trunk to Launchpad
+#. Commit 'Opening X.Y.Z+1 for development.'
 #. If a new series has been created (e.g. 0.10.0), make the series on Launchpad.
+#. Push trunk to Github, ``git push --tags origin master``
 
 .. _PEP 8: http://www.python.org/dev/peps/pep-0008/
 .. _unittest: http://docs.python.org/library/unittest.html
-.. _~testtools-committers: https://launchpad.net/~testtools-committers
 .. _MIT license: http://www.opensource.org/licenses/mit-license.php
 .. _Sphinx: http://sphinx.pocoo.org/
 .. _restructuredtext: http://docutils.sourceforge.net/rst.html
-
+.. _testing-cabal: https://github.com/organizations/testing-cabal/
diff --git a/lib/testtools/doc/index.rst b/lib/testtools/doc/index.rst
index bac47e4..a6c05a9 100644
--- a/lib/testtools/doc/index.rst
+++ b/lib/testtools/doc/index.rst
@@ -25,7 +25,7 @@ Contents:
    for-framework-folk
    hacking
    Changes to testtools <news>
-   API reference documentation <http://mumak.net/testtools/apidocs/>
+   API reference documentation <api>
 
 Indices and tables
 ==================
diff --git a/lib/testtools/doc/overview.rst b/lib/testtools/doc/overview.rst
index cb72893..a01dc3d 100644
--- a/lib/testtools/doc/overview.rst
+++ b/lib/testtools/doc/overview.rst
@@ -5,10 +5,7 @@ testtools: tasteful testing for Python
 testtools is a set of extensions to the Python standard library's unit testing
 framework. These extensions have been derived from many years of experience
 with unit testing in Python and come from many different sources. testtools
-supports Python versions all the way back to Python 2.4. The next release of
-testtools will change that to support versions that are maintained by the
-Python community instead, to allow the use of modern language features within
-testtools.
+supports Python versions all the way back to Python 2.6.
 
 What better way to start than with a contrived code snippet?::
 
@@ -29,7 +26,7 @@ What better way to start than with a contrived code snippet?::
       def attach_log_file(self):
           self.addDetail(
               'log-file',
-              Content(UTF8_TEXT
+              Content(UTF8_TEXT,
                       lambda: open(self.server.logfile, 'r').readlines()))
 
       def test_server_is_cool(self):
@@ -96,7 +93,9 @@ Cross-Python compatibility
 --------------------------
 
 testtools gives you the very latest in unit testing technology in a way that
-will work with Python 2.6, 2.7 and 3.1.
+will work with Python 2.6, 2.7, 3.1 and 3.2.
 
 If you wish to use testtools with Python 2.4 or 2.5, then please use testtools
-0.9.15.
+0.9.15. Up to then we supported Python 2.4 and 2.5, but we found the
+constraints involved in not using the newer language features onerous as we
+added more support for versions post Python 3.
diff --git a/lib/testtools/scripts/_lp_release.py b/lib/testtools/scripts/_lp_release.py
index 20afd01..ac27e47 100644
--- a/lib/testtools/scripts/_lp_release.py
+++ b/lib/testtools/scripts/_lp_release.py
@@ -108,7 +108,8 @@ def get_release_notes_and_changelog(news_path):
         for line in news:
             line = line.strip()
             if state is None:
-                if is_heading_marker(line, '~'):
+                if (is_heading_marker(line, '~') and
+                    not last_line.startswith('NEXT')):
                     milestone_name = last_line
                     state = 'release-notes'
                 else:
@@ -222,7 +223,8 @@ def release_project(launchpad, project_name, next_milestone_name):
 
 
 def main(args):
-    launchpad = Launchpad.login_with(APP_NAME, SERVICE_ROOT, CACHE_DIR)
+    launchpad = Launchpad.login_with(
+        APP_NAME, SERVICE_ROOT, CACHE_DIR, credentials_file='.lp_creds')
     return release_project(launchpad, PROJECT_NAME, NEXT_MILESTONE_NAME)
 
 
diff --git a/lib/testtools/setup.cfg b/lib/testtools/setup.cfg
index 9f95add..3e210fa 100644
--- a/lib/testtools/setup.cfg
+++ b/lib/testtools/setup.cfg
@@ -2,3 +2,6 @@
 test_module = testtools.tests
 buffer=1
 catch=1
+
+[bdist_wheel]
+universal = 1
diff --git a/lib/testtools/setup.py b/lib/testtools/setup.py
index 7ecd6d2..95c3b67 100755
--- a/lib/testtools/setup.py
+++ b/lib/testtools/setup.py
@@ -1,22 +1,24 @@
 #!/usr/bin/env python
 """Distutils installer for testtools."""
 
-from distutils.core import setup
+from setuptools import setup
+from distutils.command.build_py import build_py
 import email
 import os
+import sys
 
 import testtools
+cmd_class = {}
+if getattr(testtools, 'TestCommand', None) is not None:
+    cmd_class['test'] = testtools.TestCommand
 
 
-def get_revno():
-    import bzrlib.errors
-    import bzrlib.workingtree
-    try:
-        t = bzrlib.workingtree.WorkingTree.open_containing(__file__)[0]
-    except (bzrlib.errors.NotBranchError, bzrlib.errors.NoWorkingTree):
-        return None
-    else:
-        return t.branch.revno()
+class testtools_build_py(build_py):
+    def build_module(self, module, module_file, package):
+        if sys.version_info >= (3,) and module == '_compat2x':
+            return
+        return build_py.build_module(self, module, module_file, package)
+cmd_class['build_py'] = testtools_build_py
 
 
 def get_version_from_pkg_info():
@@ -43,18 +45,10 @@ def get_version():
     pkg_info_version = get_version_from_pkg_info()
     if pkg_info_version:
         return pkg_info_version
-    revno = get_revno()
-    if revno is None:
-        # Apparently if we just say "snapshot" then distribute won't accept it
-        # as satisfying versioned dependencies. This is a problem for the
-        # daily build version.
-        return "snapshot-%s" % (version,)
-    if phase == 'alpha':
-        # No idea what the next version will be
-        return 'next-r%s' % revno
-    else:
-        # Preserve the version number but give it a revno prefix
-        return version + '-r%s' % revno
+    # Apparently if we just say "snapshot" then distribute won't accept it
+    # as satisfying versioned dependencies. This is a problem for the
+    # daily build version.
+    return "%s.0dev0" % (version,)
 
 
 def get_long_description():
@@ -62,11 +56,21 @@ def get_long_description():
         os.path.dirname(__file__), 'doc/overview.rst')
     return open(manual_path).read()
 
+# Since we import testtools in setup.py, our setup requirements are our install
+# requirements.
+deps = [
+    'extras',
+    # 'mimeparse' has not been uploaded by the maintainer with Python3 compat
+    # but someone kindly uploaded a fixed version as 'python-mimeparse'.
+    'python-mimeparse',
+    'unittest2>=0.8.0',
+    ]
+
 
 setup(name='testtools',
       author='Jonathan M. Lange',
       author_email='jml+testtools at mumak.net',
-      url='https://launchpad.net/testtools',
+      url='https://github.com/testing-cabal/testtools',
       description=('Extensions to the Python standard library unit testing '
                    'framework'),
       long_description=get_long_description(),
@@ -81,5 +85,8 @@ setup(name='testtools',
         'testtools.tests',
         'testtools.tests.matchers',
         ],
-      cmdclass={'test': testtools.TestCommand},
-      zip_safe=False)
+      cmdclass=cmd_class,
+      zip_safe=False,
+      install_requires=deps,
+      setup_requires=deps,
+      )
diff --git a/lib/testtools/testtools/__init__.py b/lib/testtools/testtools/__init__.py
index d722ce5..6e2df87 100644
--- a/lib/testtools/testtools/__init__.py
+++ b/lib/testtools/testtools/__init__.py
@@ -4,10 +4,14 @@
 
 __all__ = [
     'clone_test_with_new_id',
+    'CopyStreamResult',
     'ConcurrentTestSuite',
+    'ConcurrentStreamTestSuite',
+    'DecorateTestCaseResult',
     'ErrorHolder',
     'ExpectedException',
     'ExtendedToOriginalDecorator',
+    'ExtendedToStreamDecorator',
     'FixtureSuite',
     'iterate_tests',
     'MultipleExceptions',
@@ -25,54 +29,86 @@ __all__ = [
     'skip',
     'skipIf',
     'skipUnless',
+    'StreamFailFast',
+    'StreamResult',
+    'StreamResultRouter',
+    'StreamSummary',
+    'StreamTagger',
+    'StreamToDict',
+    'StreamToExtendedDecorator',
+    'StreamToQueue',
+    'TestControl',
     'ThreadsafeForwardingResult',
+    'TimestampingStreamResult',
     'try_import',
     'try_imports',
     ]
 
-from testtools.helpers import (
-    try_import,
-    try_imports,
-    )
-from testtools.matchers._impl import (
-    Matcher,
-    )
+# Compat - removal announced in 0.9.25.
+try:
+    from extras import (
+        try_import,
+        try_imports,
+        )
+except ImportError:
+    # Support reading __init__ for __version__ without extras, because pip does
+    # not support setup_requires.
+    pass
+else:
+
+    from testtools.matchers._impl import (
+        Matcher,
+        )
 # Shut up, pyflakes. We are importing for documentation, not for namespacing.
-Matcher
+    Matcher
 
-from testtools.runtest import (
-    MultipleExceptions,
-    RunTest,
-    )
-from testtools.testcase import (
-    ErrorHolder,
-    ExpectedException,
-    PlaceHolder,
-    TestCase,
-    clone_test_with_new_id,
-    run_test_with,
-    skip,
-    skipIf,
-    skipUnless,
-    )
-from testtools.testresult import (
-    ExtendedToOriginalDecorator,
-    MultiTestResult,
-    Tagger,
-    TestByTestResult,
-    TestResult,
-    TestResultDecorator,
-    TextTestResult,
-    ThreadsafeForwardingResult,
-    )
-from testtools.testsuite import (
-    ConcurrentTestSuite,
-    FixtureSuite,
-    iterate_tests,
-    )
-from testtools.distutilscmd import (
-    TestCommand,
-)
+    from testtools.runtest import (
+        MultipleExceptions,
+        RunTest,
+        )
+    from testtools.testcase import (
+        DecorateTestCaseResult,
+        ErrorHolder,
+        ExpectedException,
+        PlaceHolder,
+        TestCase,
+        clone_test_with_new_id,
+        run_test_with,
+        skip,
+        skipIf,
+        skipUnless,
+        )
+    from testtools.testresult import (
+        CopyStreamResult,
+        ExtendedToOriginalDecorator,
+        ExtendedToStreamDecorator,
+        MultiTestResult,
+        StreamFailFast,
+        StreamResult,
+        StreamResultRouter,
+        StreamSummary,
+        StreamTagger,
+        StreamToDict,
+        StreamToExtendedDecorator,
+        StreamToQueue,
+        Tagger,
+        TestByTestResult,
+        TestControl,
+        TestResult,
+        TestResultDecorator,
+        TextTestResult,
+        ThreadsafeForwardingResult,
+        TimestampingStreamResult,
+        )
+    from testtools.testsuite import (
+        ConcurrentTestSuite,
+        ConcurrentStreamTestSuite,
+        FixtureSuite,
+        iterate_tests,
+        )
+    from testtools.distutilscmd import (
+        TestCommand,
+        )
 
 # same format as sys.version_info: "A tuple containing the five components of
 # the version number: major, minor, micro, releaselevel, and serial. All
@@ -86,4 +122,4 @@ from testtools.distutilscmd import (
 # If the releaselevel is 'final', then the tarball will be major.minor.micro.
 # Otherwise it is major.minor.micro~$(revno).
 
-__version__ = (0, 9, 25, 'dev', 0)
+__version__ = (1, 5, 0, 'final', 0)
diff --git a/lib/testtools/testtools/compat.py b/lib/testtools/testtools/compat.py
index 375eca2..684c8b3 100644
--- a/lib/testtools/testtools/compat.py
+++ b/lib/testtools/testtools/compat.py
@@ -7,10 +7,8 @@ __all__ = [
     '_b',
     '_u',
     'advance_iterator',
-    'all',
     'BytesIO',
     'classtypes',
-    'isbaseexception',
     'istext',
     'str_is_unicode',
     'StringIO',
@@ -19,6 +17,7 @@ __all__ = [
     ]
 
 import codecs
+import io
 import linecache
 import locale
 import os
@@ -27,14 +26,14 @@ import sys
 import traceback
 import unicodedata
 
-from testtools.helpers import try_imports
+from extras import try_imports
 
 BytesIO = try_imports(['StringIO.StringIO', 'io.BytesIO'])
 StringIO = try_imports(['StringIO.StringIO', 'io.StringIO'])
 
 try:
     from testtools import _compat2x as _compat
-except SyntaxError:
+except (SyntaxError, ImportError):
     from testtools import _compat3x as _compat
 
 reraise = _compat.reraise
@@ -87,34 +86,6 @@ else:
 _u.__doc__ = __u_doc
 
 
-if sys.version_info > (2, 5):
-    all = all
-    _error_repr = BaseException.__repr__
-    def isbaseexception(exception):
-        """Return whether exception inherits from BaseException only"""
-        return (isinstance(exception, BaseException)
-            and not isinstance(exception, Exception))
-else:
-    def all(iterable):
-        """If contents of iterable all evaluate as boolean True"""
-        for obj in iterable:
-            if not obj:
-                return False
-        return True
-    def _error_repr(exception):
-        """Format an exception instance as Python 2.5 and later do"""
-        return exception.__class__.__name__ + repr(exception.args)
-    def isbaseexception(exception):
-        """Return whether exception would inherit from BaseException only
-
-        This approximates the hierarchy in Python 2.5 and later, compare the
-        difference between the diagrams at the bottom of the pages:
-        <http://docs.python.org/release/2.4.4/lib/module-exceptions.html>
-        <http://docs.python.org/release/2.5.4/lib/module-exceptions.html>
-        """
-        return isinstance(exception, (KeyboardInterrupt, SystemExit))
-
-
 # GZ 2011-08-24: Using isinstance checks like this encourages bad interfaces,
 #                there should be better ways to write code needing this.
 if not issubclass(getattr(builtins, "bytes", str), str):
@@ -169,7 +140,7 @@ def text_repr(text, multiline=None):
     prefix = repr(text[:0])[:-2]
     if multiline:
         # To escape multiline strings, split and process each line in turn,
-        # making sure that quotes are not escaped. 
+        # making sure that quotes are not escaped.
         if is_py3k:
             offset = len(prefix) + 1
             lines = []
@@ -215,14 +186,15 @@ def unicode_output_stream(stream):
     The wrapper only allows unicode to be written, not non-ascii bytestrings,
     which is a good thing to ensure sanity and sanitation.
     """
-    if sys.platform == "cli":
-        # Best to never encode before writing in IronPython
+    if (sys.platform == "cli" or
+        isinstance(stream, (io.TextIOWrapper, io.StringIO))):
+        # Best to never encode before writing in IronPython, or if it is
+        # already a TextIO [which in the io library has no encoding
+        # attribute).
         return stream
     try:
         writer = codecs.getwriter(stream.encoding or "")
     except (AttributeError, LookupError):
-        # GZ 2010-06-16: Python 3 StringIO ends up here, but probably needs
-        #                different handling as it doesn't want bytestrings
         return codecs.getwriter("ascii")(stream, "replace")
     if writer.__module__.rsplit(".", 1)[1].startswith("utf"):
         # The current stream has a unicode encoding so no error handler is needed
@@ -324,31 +296,33 @@ def _exception_to_text(evalue):
     return None
 
 
-# GZ 2010-05-23: This function is huge and horrible and I welcome suggestions
-#                on the best way to break it up
-_TB_HEADER = _u('Traceback (most recent call last):\n')
-def _format_exc_info(eclass, evalue, tb, limit=None):
-    """Format a stack trace and the exception information as unicode
+def _format_stack_list(stack_lines):
+    """Format 'stack_lines' and return a list of unicode strings.
 
-    Compatibility function for Python 2 which ensures each component of a
-    traceback is correctly decoded according to its origins.
-
-    Based on traceback.format_exception and related functions.
+    :param stack_lines: A list of filename, lineno, name, and line variables,
+        probably obtained by calling traceback.extract_tb or
+        traceback.extract_stack.
     """
     fs_enc = sys.getfilesystemencoding()
-    if tb:
-        list = [_TB_HEADER]
-        extracted_list = []
-        for filename, lineno, name, line in traceback.extract_tb(tb, limit):
+    extracted_list = []
+    for filename, lineno, name, line in stack_lines:
             extracted_list.append((
                 filename.decode(fs_enc, "replace"),
                 lineno,
                 name.decode("ascii", "replace"),
                 line and line.decode(
                     _get_source_encoding(filename), "replace")))
-        list.extend(traceback.format_list(extracted_list))
-    else:
-        list = []
+    return traceback.format_list(extracted_list)
+
+
+def _format_exception_only(eclass, evalue):
+    """Format the excption part of a traceback.
+
+    :param eclass: The type of the exception being formatted.
+    :param evalue: The exception instance.
+    :returns: A list of unicode strings.
+    """
+    list = []
     if evalue is None:
         # Is a (deprecated) string exception
         list.append((eclass + "\n").decode("ascii", "replace"))
@@ -377,6 +351,7 @@ def _format_exc_info(eclass, evalue, tb, limit=None):
                 else:
                     line = line.decode("ascii", "replace")
             if filename:
+                fs_enc = sys.getfilesystemencoding()
                 filename = filename.decode(fs_enc, "replace")
             evalue = eclass(msg, (filename, lineno, offset, line))
             list.extend(traceback.format_exception_only(eclass, evalue))
@@ -387,7 +362,24 @@ def _format_exc_info(eclass, evalue, tb, limit=None):
         list.append("%s: %s\n" % (sclass, svalue))
     elif svalue is None:
         # GZ 2010-05-24: Not a great fallback message, but keep for the moment
-        list.append("%s: <unprintable %s object>\n" % (sclass, sclass))
+        list.append(_u("%s: <unprintable %s object>\n" % (sclass, sclass)))
     else:
-        list.append("%s\n" % sclass)
+        list.append(_u("%s\n" % sclass))
     return list
+
+
+_TB_HEADER = _u('Traceback (most recent call last):\n')
+
+
+def _format_exc_info(eclass, evalue, tb, limit=None):
+    """Format a stack trace and the exception information as unicode
+
+    Compatibility function for Python 2 which ensures each component of a
+    traceback is correctly decoded according to its origins.
+
+    Based on traceback.format_exception and related functions.
+    """
+    return [_TB_HEADER] \
+        + _format_stack_list(traceback.extract_tb(tb, limit)) \
+        + _format_exception_only(eclass, evalue)
+
diff --git a/lib/testtools/testtools/content.py b/lib/testtools/testtools/content.py
index 8bd4a22..101b631 100644
--- a/lib/testtools/testtools/content.py
+++ b/lib/testtools/testtools/content.py
@@ -7,18 +7,29 @@ __all__ = [
     'Content',
     'content_from_file',
     'content_from_stream',
+    'json_content',
     'text_content',
     'TracebackContent',
     ]
 
 import codecs
+import inspect
 import json
 import os
 import sys
 import traceback
 
-from testtools import try_import
-from testtools.compat import _b, _format_exc_info, str_is_unicode, _u
+from extras import try_import
+
+from testtools.compat import (
+    _b,
+    _format_exception_only,
+    _format_stack_list,
+    _TB_HEADER,
+    _u,
+    istext,
+    str_is_unicode,
+)
 from testtools.content_type import ContentType, JSON, UTF8_TEXT
 
 
@@ -52,11 +63,11 @@ def _iter_chunks(stream, chunk_size, seek_offset=None, seek_whence=0):
 class Content(object):
     """A MIME-like Content object.
 
-    Content objects can be serialised to bytes using the iter_bytes method.
-    If the Content-Type is recognised by other code, they are welcome to
+    'Content' objects can be serialised to bytes using the iter_bytes method.
+    If the 'Content-Type' is recognised by other code, they are welcome to
     look for richer contents that mere byte serialisation - for example in
     memory object graphs etc. However, such code MUST be prepared to receive
-    a generic Content object that has been reconstructed from a byte stream.
+    a generic 'Content' object that has been reconstructed from a byte stream.
 
     :ivar content_type: The content type of this Content.
     """
@@ -102,28 +113,25 @@ class Content(object):
     def _iter_text(self):
         """Worker for iter_text - does the decoding."""
         encoding = self.content_type.parameters.get('charset', 'ISO-8859-1')
-        try:
-            # 2.5+
-            decoder = codecs.getincrementaldecoder(encoding)()
-            for bytes in self.iter_bytes():
-                yield decoder.decode(bytes)
-            final = decoder.decode(_b(''), True)
-            if final:
-                yield final
-        except AttributeError:
-            # < 2.5
-            bytes = ''.join(self.iter_bytes())
-            yield bytes.decode(encoding)
+        decoder = codecs.getincrementaldecoder(encoding)()
+        for bytes in self.iter_bytes():
+            yield decoder.decode(bytes)
+        final = decoder.decode(_b(''), True)
+        if final:
+            yield final
 
     def __repr__(self):
         return "<Content type=%r, value=%r>" % (
             self.content_type, _join_b(self.iter_bytes()))
 
 
-class TracebackContent(Content):
-    """Content object for tracebacks.
+class StackLinesContent(Content):
+    """Content object for stack lines.
+
+    This adapts a list of "preprocessed" stack lines into a 'Content' object.
+    The stack lines are most likely produced from ``traceback.extract_stack``
+    or ``traceback.extract_tb``.
 
-    This adapts an exc_info tuple to the Content interface.
     text/x-traceback;language=python is used for the mime type, in order to
     provide room for other languages to format their tracebacks differently.
     """
@@ -133,69 +141,117 @@ class TracebackContent(Content):
     # system-under-test is rarely unittest or testtools.
     HIDE_INTERNAL_STACK = True
 
-    def __init__(self, err, test):
-        """Create a TracebackContent for err."""
-        if err is None:
-            raise ValueError("err may not be None")
+    def __init__(self, stack_lines, prefix_content="", postfix_content=""):
+        """Create a StackLinesContent for ``stack_lines``.
+
+        :param stack_lines: A list of preprocessed stack lines, probably
+            obtained by calling ``traceback.extract_stack`` or
+            ``traceback.extract_tb``.
+        :param prefix_content: If specified, a unicode string to prepend to the
+            text content.
+        :param postfix_content: If specified, a unicode string to append to the
+            text content.
+        """
         content_type = ContentType('text', 'x-traceback',
             {"language": "python", "charset": "utf8"})
-        value = self._exc_info_to_unicode(err, test)
-        super(TracebackContent, self).__init__(
+        value = prefix_content + \
+            self._stack_lines_to_unicode(stack_lines) + \
+            postfix_content
+        super(StackLinesContent, self).__init__(
             content_type, lambda: [value.encode("utf8")])
 
-    def _exc_info_to_unicode(self, err, test):
-        """Converts a sys.exc_info()-style tuple of values into a string.
-
-        Copied from Python 2.7's unittest.TestResult._exc_info_to_string.
+    def _stack_lines_to_unicode(self, stack_lines):
+        """Converts a list of pre-processed stack lines into a unicode string.
         """
-        exctype, value, tb = err
-        # Skip test runner traceback levels
-        if self.HIDE_INTERNAL_STACK:
-            while tb and self._is_relevant_tb_level(tb):
-                tb = tb.tb_next
 
         # testtools customization. When str is unicode (e.g. IronPython,
         # Python 3), traceback.format_exception returns unicode. For Python 2,
         # it returns bytes. We need to guarantee unicode.
         if str_is_unicode:
-            format_exception = traceback.format_exception
+            format_stack_lines = traceback.format_list
         else:
-            format_exception = _format_exc_info
+            format_stack_lines = _format_stack_list
 
-        if (self.HIDE_INTERNAL_STACK and test.failureException
-            and isinstance(value, test.failureException)):
-            # Skip assert*() traceback levels
-            length = self._count_relevant_tb_levels(tb)
-            msgLines = format_exception(exctype, value, tb, length)
-        else:
-            msgLines = format_exception(exctype, value, tb)
-
-        if getattr(self, 'buffer', None):
-            output = sys.stdout.getvalue()
-            error = sys.stderr.getvalue()
-            if output:
-                if not output.endswith('\n'):
-                    output += '\n'
-                msgLines.append(STDOUT_LINE % output)
-            if error:
-                if not error.endswith('\n'):
-                    error += '\n'
-                msgLines.append(STDERR_LINE % error)
-        return ''.join(msgLines)
-
-    def _is_relevant_tb_level(self, tb):
-        return '__unittest' in tb.tb_frame.f_globals
-
-    def _count_relevant_tb_levels(self, tb):
-        length = 0
+        msg_lines = format_stack_lines(stack_lines)
+
+        return ''.join(msg_lines)
+
+
+def TracebackContent(err, test):
+    """Content object for tracebacks.
+
+    This adapts an exc_info tuple to the 'Content' interface.
+    'text/x-traceback;language=python' is used for the mime type, in order to
+    provide room for other languages to format their tracebacks differently.
+    """
+    if err is None:
+        raise ValueError("err may not be None")
+
+    exctype, value, tb = err
+    # Skip test runner traceback levels
+    if StackLinesContent.HIDE_INTERNAL_STACK:
+        while tb and '__unittest' in tb.tb_frame.f_globals:
+            tb = tb.tb_next
+
+    # testtools customization. When str is unicode (e.g. IronPython,
+    # Python 3), traceback.format_exception_only returns unicode. For Python 2,
+    # it returns bytes. We need to guarantee unicode.
+    if str_is_unicode:
+        format_exception_only = traceback.format_exception_only
+    else:
+        format_exception_only = _format_exception_only
+
+    limit = None
+    # Disabled due to https://bugs.launchpad.net/testtools/+bug/1188420
+    if (False
+        and StackLinesContent.HIDE_INTERNAL_STACK
+        and test.failureException
+        and isinstance(value, test.failureException)):
+        # Skip assert*() traceback levels
+        limit = 0
         while tb and not self._is_relevant_tb_level(tb):
-            length += 1
+            limit += 1
             tb = tb.tb_next
-        return length
+
+    prefix = _TB_HEADER
+    stack_lines = traceback.extract_tb(tb, limit)
+    postfix = ''.join(format_exception_only(exctype, value))
+
+    return StackLinesContent(stack_lines, prefix, postfix)
+
+
+def StacktraceContent(prefix_content="", postfix_content=""):
+    """Content object for stack traces.
+
+    This function will create and return a 'Content' object that contains a
+    stack trace.
+
+    The mime type is set to 'text/x-traceback;language=python', so other
+    languages can format their stack traces differently.
+
+    :param prefix_content: A unicode string to add before the stack lines.
+    :param postfix_content: A unicode string to add after the stack lines.
+    """
+    stack = inspect.stack()[1:]
+
+    if StackLinesContent.HIDE_INTERNAL_STACK:
+        limit = 1
+        while limit < len(stack) and '__unittest' not in stack[limit][0].f_globals:
+            limit += 1
+    else:
+        limit = -1
+
+    frames_only = [line[0] for line in stack[:limit]]
+    processed_stack = [ ]
+    for frame in reversed(frames_only):
+        filename, line, function, context, _ = inspect.getframeinfo(frame)
+        context = ''.join(context)
+        processed_stack.append((filename, line, function, context))
+    return StackLinesContent(processed_stack, prefix_content, postfix_content)
 
 
 def json_content(json_data):
-    """Create a JSON `Content` object from JSON-encodeable data."""
+    """Create a JSON Content object from JSON-encodeable data."""
     data = json.dumps(json_data)
     if str_is_unicode:
         # The json module perversely returns native str not bytes
@@ -204,10 +260,14 @@ def json_content(json_data):
 
 
 def text_content(text):
-    """Create a `Content` object from some text.
+    """Create a Content object from some text.
 
     This is useful for adding details which are short strings.
     """
+    if not istext(text):
+        raise TypeError(
+            "text_content must be given text, not '%s'." % type(text).__name__
+        )
     return Content(UTF8_TEXT, lambda: [text.encode('utf8')])
 
 
@@ -220,9 +280,9 @@ def maybe_wrap(wrapper, func):
 
 def content_from_file(path, content_type=None, chunk_size=DEFAULT_CHUNK_SIZE,
                       buffer_now=False, seek_offset=None, seek_whence=0):
-    """Create a `Content` object from a file on disk.
+    """Create a Content object from a file on disk.
 
-    Note that unless 'read_now' is explicitly passed in as True, the file
+    Note that unless ``buffer_now`` is explicitly passed in as True, the file
     will only be read from when ``iter_bytes`` is called.
 
     :param path: The path to the file to be used as content.
@@ -233,31 +293,30 @@ def content_from_file(path, content_type=None, chunk_size=DEFAULT_CHUNK_SIZE,
     :param buffer_now: If True, read the file from disk now and keep it in
         memory. Otherwise, only read when the content is serialized.
     :param seek_offset: If non-None, seek within the stream before reading it.
-    :param seek_whence: If supplied, pass to stream.seek() when seeking.
+    :param seek_whence: If supplied, pass to ``stream.seek()`` when seeking.
     """
     if content_type is None:
         content_type = UTF8_TEXT
     def reader():
-        # This should be try:finally:, but python2.4 makes that hard. When
-        # We drop older python support we can make this use a context manager
-        # for maximum simplicity.
-        stream = open(path, 'rb')
-        for chunk in _iter_chunks(stream, chunk_size, seek_offset, seek_whence):
-            yield chunk
-        stream.close()
+        with open(path, 'rb') as stream:
+            for chunk in _iter_chunks(stream,
+                                      chunk_size,
+                                      seek_offset,
+                                      seek_whence):
+                yield chunk
     return content_from_reader(reader, content_type, buffer_now)
 
 
 def content_from_stream(stream, content_type=None,
                         chunk_size=DEFAULT_CHUNK_SIZE, buffer_now=False,
                         seek_offset=None, seek_whence=0):
-    """Create a `Content` object from a file-like stream.
+    """Create a Content object from a file-like stream.
 
-    Note that the stream will only be read from when ``iter_bytes`` is
-    called.
+    Note that unless ``buffer_now`` is explicitly passed in as True, the stream
+    will only be read from when ``iter_bytes`` is called.
 
     :param stream: A file-like object to read the content from. The stream
-        is not closed by this function or the content object it returns.
+        is not closed by this function or the 'Content' object it returns.
     :param content_type: The type of content. If not specified, defaults
         to UTF8-encoded text/plain.
     :param chunk_size: The size of chunks to read from the file.
@@ -265,7 +324,7 @@ def content_from_stream(stream, content_type=None,
     :param buffer_now: If True, reads from the stream right now. Otherwise,
         only reads when the content is serialized. Defaults to False.
     :param seek_offset: If non-None, seek within the stream before reading it.
-    :param seek_whence: If supplied, pass to stream.seek() when seeking.
+    :param seek_whence: If supplied, pass to ``stream.seek()`` when seeking.
     """
     if content_type is None:
         content_type = UTF8_TEXT
@@ -296,9 +355,9 @@ def attach_file(detailed, path, name=None, content_type=None,
 
     This is a convenience method wrapping around ``addDetail``.
 
-    Note that unless 'read_now' is explicitly passed in as True, the file
-    *must* exist when the test result is called with the results of this
-    test, after the test has been torn down.
+    Note that by default the contents of the file will be read immediately. If
+    ``buffer_now`` is False, then the file *must* exist when the test result is
+    called with the results of this test, after the test has been torn down.
 
     :param detailed: An object with details
     :param path: The path to the file to attach.
diff --git a/lib/testtools/testtools/content_type.py b/lib/testtools/testtools/content_type.py
index c491408..bbf314b 100644
--- a/lib/testtools/testtools/content_type.py
+++ b/lib/testtools/testtools/content_type.py
@@ -29,7 +29,7 @@ class ContentType(object):
     def __repr__(self):
         if self.parameters:
             params = '; '
-            params += ', '.join(
+            params += '; '.join(
                 sorted('%s="%s"' % (k, v) for k, v in self.parameters.items()))
         else:
             params = ''
diff --git a/lib/testtools/testtools/deferredruntest.py b/lib/testtools/testtools/deferredruntest.py
index cf33c06..d22c79f 100644
--- a/lib/testtools/testtools/deferredruntest.py
+++ b/lib/testtools/testtools/deferredruntest.py
@@ -89,14 +89,21 @@ class AsynchronousDeferredRunTest(_DeferredRunTest):
     This is highly experimental code.  Use at your own risk.
     """
 
-    def __init__(self, case, handlers=None, reactor=None, timeout=0.005,
-                 debug=False):
+    def __init__(self, case, handlers=None, last_resort=None, reactor=None,
+                 timeout=0.005, debug=False):
         """Construct an `AsynchronousDeferredRunTest`.
 
+        Please be sure to always use keyword syntax, not positional, as the
+        base class may add arguments in future - and for core code
+        compatibility with that we have to insert them before the local
+        parameters.
+
         :param case: The `TestCase` to run.
         :param handlers: A list of exception handlers (ExceptionType, handler)
             where 'handler' is a callable that takes a `TestCase`, a
             ``testtools.TestResult`` and the exception raised.
+        :param last_resort: Handler to call before re-raising uncatchable
+            exceptions (those for which there is no handler).
         :param reactor: The Twisted reactor to use.  If not given, we use the
             default reactor.
         :param timeout: The maximum time allowed for running a test.  The
@@ -105,7 +112,8 @@ class AsynchronousDeferredRunTest(_DeferredRunTest):
             to get information about unhandled Deferreds and left-over
             DelayedCalls.  Defaults to False.
         """
-        super(AsynchronousDeferredRunTest, self).__init__(case, handlers)
+        super(AsynchronousDeferredRunTest, self).__init__(
+            case, handlers, last_resort)
         if reactor is None:
             from twisted.internet import reactor
         self._reactor = reactor
@@ -119,8 +127,8 @@ class AsynchronousDeferredRunTest(_DeferredRunTest):
         # will be able to be assigned to a class variable *and* also be
         # invoked directly.
         class AsynchronousDeferredRunTestFactory:
-            def __call__(self, case, handlers=None):
-                return cls(case, handlers, reactor, timeout, debug)
+            def __call__(self, case, handlers=None, last_resort=None):
+                return cls(case, handlers, last_resort, reactor, timeout, debug)
         return AsynchronousDeferredRunTestFactory()
 
     @defer.deferredGenerator
diff --git a/lib/testtools/testtools/distutilscmd.py b/lib/testtools/testtools/distutilscmd.py
index 91e14ca..a4d79dc 100644
--- a/lib/testtools/testtools/distutilscmd.py
+++ b/lib/testtools/testtools/distutilscmd.py
@@ -26,7 +26,7 @@ class TestCommand(Command):
 
     def __init__(self, dist):
         Command.__init__(self, dist)
-        self.runner = TestToolsTestRunner(sys.stdout)
+        self.runner = TestToolsTestRunner(stdout=sys.stdout)
 
 
     def initialize_options(self):
diff --git a/lib/testtools/testtools/helpers.py b/lib/testtools/testtools/helpers.py
index 2595c1d..401d2cc 100644
--- a/lib/testtools/testtools/helpers.py
+++ b/lib/testtools/testtools/helpers.py
@@ -8,83 +8,12 @@ __all__ = [
 
 import sys
 
-
-def try_import(name, alternative=None, error_callback=None):
-    """Attempt to import ``name``.  If it fails, return ``alternative``.
-
-    When supporting multiple versions of Python or optional dependencies, it
-    is useful to be able to try to import a module.
-
-    :param name: The name of the object to import, e.g. ``os.path`` or
-        ``os.path.join``.
-    :param alternative: The value to return if no module can be imported.
-        Defaults to None.
-    :param error_callback: If non-None, a callable that is passed the ImportError
-        when the module cannot be loaded.
-    """
-    module_segments = name.split('.')
-    last_error = None
-    while module_segments:
-        module_name = '.'.join(module_segments)
-        try:
-            module = __import__(module_name)
-        except ImportError:
-            last_error = sys.exc_info()[1]
-            module_segments.pop()
-            continue
-        else:
-            break
-    else:
-        if last_error is not None and error_callback is not None:
-            error_callback(last_error)
-        return alternative
-    nonexistent = object()
-    for segment in name.split('.')[1:]:
-        module = getattr(module, segment, nonexistent)
-        if module is nonexistent:
-            if last_error is not None and error_callback is not None:
-                error_callback(last_error)
-            return alternative
-    return module
-
-
-_RAISE_EXCEPTION = object()
-def try_imports(module_names, alternative=_RAISE_EXCEPTION, error_callback=None):
-    """Attempt to import modules.
-
-    Tries to import the first module in ``module_names``.  If it can be
-    imported, we return it.  If not, we go on to the second module and try
-    that.  The process continues until we run out of modules to try.  If none
-    of the modules can be imported, either raise an exception or return the
-    provided ``alternative`` value.
-
-    :param module_names: A sequence of module names to try to import.
-    :param alternative: The value to return if no module can be imported.
-        If unspecified, we raise an ImportError.
-    :param error_callback: If None, called with the ImportError for *each*
-        module that fails to load.
-    :raises ImportError: If none of the modules can be imported and no
-        alternative value was specified.
-    """
-    module_names = list(module_names)
-    for module_name in module_names:
-        module = try_import(module_name, error_callback=error_callback)
-        if module:
-            return module
-    if alternative is _RAISE_EXCEPTION:
-        raise ImportError(
-            "Could not import any of: %s" % ', '.join(module_names))
-    return alternative
-
-
-def safe_hasattr(obj, attr, _marker=object()):
-    """Does 'obj' have an attribute 'attr'?
-
-    Use this rather than built-in hasattr, as the built-in swallows exceptions
-    in some versions of Python and behaves unpredictably with respect to
-    properties.
-    """
-    return getattr(obj, attr, _marker) is not _marker
+# Compat - removal announced in 0.9.25.
+from extras import (
+    safe_hasattr,
+    try_import,
+    try_imports,
+    )
 
 
 def map_values(function, dictionary):
diff --git a/lib/testtools/testtools/matchers/__init__.py b/lib/testtools/testtools/matchers/__init__.py
index ce949fd..771d814 100644
--- a/lib/testtools/testtools/matchers/__init__.py
+++ b/lib/testtools/testtools/matchers/__init__.py
@@ -16,6 +16,7 @@ __all__ = [
     'AfterPreprocessing',
     'AllMatch',
     'Annotate',
+    'AnyMatch',
     'Contains',
     'ContainsAll',
     'ContainedByDict',
@@ -28,6 +29,7 @@ __all__ = [
     'FileContains',
     'FileExists',
     'GreaterThan',
+    'HasLength',
     'HasPermissions',
     'Is',
     'IsInstance',
@@ -39,6 +41,7 @@ __all__ = [
     'MatchesException',
     'MatchesListwise',
     'MatchesPredicate',
+    'MatchesPredicateWithParams',
     'MatchesRegex',
     'MatchesSetwise',
     'MatchesStructure',
@@ -57,6 +60,7 @@ from ._basic import (
     EndsWith,
     Equals,
     GreaterThan,
+    HasLength,
     Is,
     IsInstance,
     LessThan,
@@ -98,9 +102,11 @@ from ._higherorder import (
     AfterPreprocessing,
     AllMatch,
     Annotate,
+    AnyMatch,
     MatchesAll,
     MatchesAny,
     MatchesPredicate,
+    MatchesPredicateWithParams,
     Not,
     )
 
diff --git a/lib/testtools/testtools/matchers/_basic.py b/lib/testtools/testtools/matchers/_basic.py
index 44a47c5..2d9f143 100644
--- a/lib/testtools/testtools/matchers/_basic.py
+++ b/lib/testtools/testtools/matchers/_basic.py
@@ -5,6 +5,7 @@ __all__ = [
     'EndsWith',
     'Equals',
     'GreaterThan',
+    'HasLength',
     'Is',
     'IsInstance',
     'LessThan',
@@ -24,7 +25,10 @@ from ..compat import (
     text_repr,
     )
 from ..helpers import list_subtract
-from ._higherorder import PostfixedMismatch
+from ._higherorder import (
+    MatchesPredicateWithParams,
+    PostfixedMismatch,
+    )
 from ._impl import (
     Matcher,
     Mismatch,
@@ -313,3 +317,10 @@ class MatchesRegex(object):
             pattern = pattern.encode("unicode_escape").decode("ascii")
             return Mismatch("%r does not match /%s/" % (
                     value, pattern.replace("\\\\", "\\")))
+
+
+def has_len(x, y):
+    return len(x) == y
+
+
+HasLength = MatchesPredicateWithParams(has_len, "len({0}) != {1}", "HasLength")
diff --git a/lib/testtools/testtools/matchers/_dict.py b/lib/testtools/testtools/matchers/_dict.py
index ff05199..b1ec915 100644
--- a/lib/testtools/testtools/matchers/_dict.py
+++ b/lib/testtools/testtools/matchers/_dict.py
@@ -241,7 +241,7 @@ class KeysEqual(Matcher):
         """
         super(KeysEqual, self).__init__()
         try:
-            self.expected = expected.keys()
+            self.expected = expected[0].keys()
         except AttributeError:
             self.expected = list(expected)
 
diff --git a/lib/testtools/testtools/matchers/_exception.py b/lib/testtools/testtools/matchers/_exception.py
index c120487..cd4c90b 100644
--- a/lib/testtools/testtools/matchers/_exception.py
+++ b/lib/testtools/testtools/matchers/_exception.py
@@ -10,8 +10,6 @@ import sys
 
 from testtools.compat import (
     classtypes,
-    _error_repr,
-    isbaseexception,
     istext,
     )
 from ._basic import MatchesRegex
@@ -22,6 +20,17 @@ from ._impl import (
     )
 
 
+_error_repr = BaseException.__repr__
+
+
+def _is_exception(exc):
+    return isinstance(exc, BaseException)
+
+
+def _is_user_exception(exc):
+    return isinstance(exc, Exception)
+
+
 class MatchesException(Matcher):
     """Match an exc_info tuple against an exception instance or type."""
 
@@ -44,7 +53,9 @@ class MatchesException(Matcher):
         if istext(value_re):
             value_re = AfterPreproccessing(str, MatchesRegex(value_re), False)
         self.value_re = value_re
-        self._is_instance = type(self.expected) not in classtypes() + (tuple,)
+        expected_type = type(self.expected)
+        self._is_instance = not any(issubclass(expected_type, class_type)
+                for class_type in classtypes() + (tuple,))
 
     def match(self, other):
         if type(other) != tuple:
@@ -101,9 +112,10 @@ class Raises(Matcher):
             else:
                 mismatch = None
             # The exception did not match, or no explicit matching logic was
-            # performed. If the exception is a non-user exception (that is, not
-            # a subclass of Exception on Python 2.5+) then propogate it.
-            if isbaseexception(exc_info[1]):
+            # performed. If the exception is a non-user exception then
+            # propagate it.
+            exception = exc_info[1]
+            if _is_exception(exception) and not _is_user_exception(exception):
                 del exc_info
                 raise
             return mismatch
diff --git a/lib/testtools/testtools/matchers/_higherorder.py b/lib/testtools/testtools/matchers/_higherorder.py
index 53c52b6..3570f57 100644
--- a/lib/testtools/testtools/matchers/_higherorder.py
+++ b/lib/testtools/testtools/matchers/_higherorder.py
@@ -4,6 +4,7 @@ __all__ = [
     'AfterPreprocessing',
     'AllMatch',
     'Annotate',
+    'AnyMatch',
     'MatchesAny',
     'MatchesAll',
     'Not',
@@ -287,3 +288,81 @@ class MatchesPredicate(Matcher):
     def match(self, x):
         if not self.predicate(x):
             return Mismatch(self.message % x)
+
+
+def MatchesPredicateWithParams(predicate, message, name=None):
+    """Match if a given parameterised function returns True.
+
+    It is reasonably common to want to make a very simple matcher based on a
+    function that you already have that returns True or False given some
+    arguments. This matcher makes it very easy to do so. e.g.::
+
+      HasLength = MatchesPredicate(
+          lambda x, y: len(x) == y, 'len({0}) is not {1}')
+      # This assertion will fail, as 'len([1, 2]) == 3' is False.
+      self.assertThat([1, 2], HasLength(3))
+
+    Note that unlike MatchesPredicate MatchesPredicateWithParams returns a
+    factory which you then customise to use by constructing an actual matcher
+    from it.
+
+    The predicate function should take the object to match as its first
+    parameter. Any additional parameters supplied when constructing a matcher
+    are supplied to the predicate as additional parameters when checking for a
+    match.
+
+    :param predicate: The predicate function.
+    :param message: A format string for describing mis-matches.
+    :param name: Optional replacement name for the matcher.
+    """
+    def construct_matcher(*args, **kwargs):
+        return _MatchesPredicateWithParams(
+            predicate, message, name, *args, **kwargs)
+    return construct_matcher
+
+
+class _MatchesPredicateWithParams(Matcher):
+
+    def __init__(self, predicate, message, name, *args, **kwargs):
+        """Create a ``MatchesPredicateWithParams`` matcher.
+
+        :param predicate: A function that takes an object to match and
+            additional params as given in ``*args`` and ``**kwargs``. The
+            result of the function will be interpreted as a boolean to
+            determine a match.
+        :param message: A message to describe a mismatch.  It will be formatted
+            with .format() and be given a tuple containing whatever was passed
+            to ``match()`` + ``*args`` in ``*args``, and whatever was passed to
+            ``**kwargs`` as its ``**kwargs``.
+
+            For instance, to format a single parameter::
+
+                "{0} is not a {1}"
+
+            To format a keyword arg::
+
+                "{0} is not a {type_to_check}"
+        :param name: What name to use for the matcher class. Pass None to use
+            the default.
+        """
+        self.predicate = predicate
+        self.message = message
+        self.name = name
+        self.args = args
+        self.kwargs = kwargs
+
+    def __str__(self):
+        args = [str(arg) for arg in self.args]
+        kwargs = ["%s=%s" % item for item in self.kwargs.items()]
+        args = ", ".join(args + kwargs)
+        if self.name is None:
+            name = 'MatchesPredicateWithParams(%r, %r)' % (
+                self.predicate, self.message)
+        else:
+            name = self.name
+        return '%s(%s)' % (name, args)
+
+    def match(self, x):
+        if not self.predicate(x, *self.args, **self.kwargs):
+            return Mismatch(
+                self.message.format(*((x,) + self.args), **self.kwargs))
diff --git a/lib/testtools/testtools/matchers/_impl.py b/lib/testtools/testtools/matchers/_impl.py
index 36e5ee0..19a93af 100644
--- a/lib/testtools/testtools/matchers/_impl.py
+++ b/lib/testtools/testtools/matchers/_impl.py
@@ -114,9 +114,7 @@ class MismatchError(AssertionError):
     # characters are in the matchee, matcher or mismatch.
 
     def __init__(self, matchee, matcher, mismatch, verbose=False):
-        # Have to use old-style upcalling for Python 2.4 and 2.5
-        # compatibility.
-        AssertionError.__init__(self)
+        super(MismatchError, self).__init__()
         self.matchee = matchee
         self.matcher = matcher
         self.mismatch = mismatch
diff --git a/lib/testtools/testtools/run.py b/lib/testtools/testtools/run.py
index c417bd0..48cc807 100755
--- a/lib/testtools/testtools/run.py
+++ b/lib/testtools/testtools/run.py
@@ -8,46 +8,93 @@ For instance, to run the testtools test suite.
  $ python -m testtools.run testtools.tests.test_suite
 """
 
-import os
-import unittest
+import argparse
+from functools import partial
+import os.path
+import unittest2 as unittest
 import sys
 
-from testtools import TextTestResult
+from extras import safe_hasattr
+
+from testtools import TextTestResult, testcase
 from testtools.compat import classtypes, istext, unicode_output_stream
-from testtools.testsuite import iterate_tests, sorted_tests
+from testtools.testsuite import filter_by_ids, iterate_tests, sorted_tests
 
 
 defaultTestLoader = unittest.defaultTestLoader
 defaultTestLoaderCls = unittest.TestLoader
-
-if getattr(defaultTestLoader, 'discover', None) is None:
-    try:
-        import discover
-        defaultTestLoader = discover.DiscoveringTestLoader()
-        defaultTestLoaderCls = discover.DiscoveringTestLoader
-        have_discover = True
-    except ImportError:
-        have_discover = False
-else:
-    have_discover = True
+have_discover = True
+discover_impl = unittest.loader
+
+# Kept for API compatibility, but no longer used.
+BUFFEROUTPUT = ""
+CATCHBREAK = ""
+FAILFAST = ""
+USAGE_AS_MAIN = ""
+
+def list_test(test):
+    """Return the test ids that would be run if test() was run.
+
+    When things fail to import they can be represented as well, though
+    we use an ugly hack (see http://bugs.python.org/issue19746 for details)
+    to determine that. The difference matters because if a user is
+    filtering tests to run on the returned ids, a failed import can reduce
+    the visible tests but it can be impossible to tell that the selected
+    test would have been one of the imported ones.
+
+    :return: A tuple of test ids that would run and error strings
+        describing things that failed to import.
+    """
+    unittest_import_strs = set([
+        'unittest2.loader.ModuleImportFailure.',
+        'unittest.loader.ModuleImportFailure.',
+        'discover.ModuleImportFailure.'
+        ])
+    test_ids = []
+    errors = []
+    for test in iterate_tests(test):
+        # Much ugly.
+        for prefix in unittest_import_strs:
+            if test.id().startswith(prefix):
+                errors.append(test.id()[len(prefix):])
+                break
+        else:
+            test_ids.append(test.id())
+    return test_ids, errors
 
 
 class TestToolsTestRunner(object):
     """ A thunk object to support unittest.TestProgram."""
 
-    def __init__(self, verbosity=None, failfast=None, buffer=None):
+    def __init__(self, verbosity=None, failfast=None, buffer=None,
+        stdout=None):
         """Create a TestToolsTestRunner.
 
         :param verbosity: Ignored.
         :param failfast: Stop running tests at the first failure.
         :param buffer: Ignored.
+        :param stdout: Stream to use for stdout.
         """
         self.failfast = failfast
+        if stdout is None:
+            stdout = sys.stdout
+        self.stdout = stdout
+
+    def list(self, test, loader):
+        """List the tests that would be run if test() was run."""
+        test_ids, _ = list_test(test)
+        for test_id in test_ids:
+            self.stdout.write('%s\n' % test_id)
+        errors = loader.errors
+        if errors:
+            for test_id in errors:
+                self.stdout.write('%s\n' % test_id)
+            sys.exit(2)
 
     def run(self, test):
         "Run the given test case or test suite."
         result = TextTestResult(
-            unicode_output_stream(sys.stdout), failfast=self.failfast)
+            unicode_output_stream(self.stdout), failfast=self.failfast)
         result.startTestRun()
         try:
             return test.run(result)
@@ -59,73 +106,23 @@ class TestToolsTestRunner(object):
 # Taken from python 2.7 and slightly modified for compatibility with
 # older versions. Delete when 2.7 is the oldest supported version.
 # Modifications:
-#  - Use have_discover to raise an error if the user tries to use
-#    discovery on an old version and doesn't have discover installed.
-#  - If --catch is given check that installHandler is available, as
-#    it won't be on old python versions.
-#  - print calls have been been made single-source python3 compatibile.
-#  - exception handling likewise.
-#  - The default help has been changed to USAGE_AS_MAIN and USAGE_FROM_MODULE
-#    removed.
-#  - A tweak has been added to detect 'python -m *.run' and use a
-#    better progName in that case.
-#  - self.module is more comprehensively set to None when being invoked from
-#    the commandline - __name__ is used as a sentinel value.
+#  - If --catch is given, check that installHandler is available, as
+#    it won't be on old python versions or python builds without signals.
 #  - --list has been added which can list tests (should be upstreamed).
 #  - --load-list has been added which can reduce the tests used (should be
 #    upstreamed).
-#  - The limitation of using getopt is declared to the user.
-#  - http://bugs.python.org/issue16709 is worked around, by sorting tests when
-#    discover is used.
-
-FAILFAST     = "  -f, --failfast   Stop on first failure\n"
-CATCHBREAK   = "  -c, --catch      Catch control-C and display results\n"
-BUFFEROUTPUT = "  -b, --buffer     Buffer stdout and stderr during test runs\n"
-
-USAGE_AS_MAIN = """\
-Usage: %(progName)s [options] [tests]
-
-Options:
-  -h, --help       Show this message
-  -v, --verbose    Verbose output
-  -q, --quiet      Minimal output
-  -l, --list       List tests rather than executing them.
-  --load-list      Specifies a file containing test ids, only tests matching
-                   those ids are executed.
-%(failfast)s%(catchbreak)s%(buffer)s
-Examples:
-  %(progName)s test_module               - run tests from test_module
-  %(progName)s module.TestClass          - run tests from module.TestClass
-  %(progName)s module.Class.test_method  - run specified test method
-
-All options must come before [tests].  [tests] can be a list of any number of
-test modules, classes and test methods.
-
-Alternative Usage: %(progName)s discover [options]
-
-Options:
-  -v, --verbose    Verbose output
-%(failfast)s%(catchbreak)s%(buffer)s  -s directory     Directory to start discovery ('.' default)
-  -p pattern       Pattern to match test files ('test*.py' default)
-  -t directory     Top level directory of project (default to
-                   start directory)
-  -l, --list       List tests rather than executing them.
-  --load-list      Specifies a file containing test ids, only tests matching
-                   those ids are executed.
-
-For test discovery all test modules must be importable from the top
-level directory of the project.
-"""
 
 
-class TestProgram(object):
+class TestProgram(unittest.TestProgram):
     """A command-line program that runs a set of tests; this is primarily
        for making test modules conveniently executable.
     """
-    USAGE = USAGE_AS_MAIN
 
     # defaults for testing
+    module=None
+    verbosity = 1
     failfast = catchbreak = buffer = progName = None
+    _discovery_parser = None
 
     def __init__(self, module=__name__, defaultTest=None, argv=None,
                     testRunner=None, testLoader=defaultTestLoader,
@@ -143,6 +140,7 @@ class TestProgram(object):
             argv = sys.argv
         if stdout is None:
             stdout = sys.stdout
+        self.stdout = stdout
 
         self.exit = exit
         self.failfast = failfast
@@ -150,6 +148,7 @@ class TestProgram(object):
         self.verbosity = verbosity
         self.buffer = buffer
         self.defaultTest = defaultTest
+        # XXX: Local edit (see http://bugs.python.org/issue22860)
         self.listtests = False
         self.load_list = None
         self.testRunner = testRunner
@@ -162,6 +161,7 @@ class TestProgram(object):
             progName = os.path.basename(argv[0])
         self.progName = progName
         self.parseArgs(argv)
+        # XXX: Local edit (see http://bugs.python.org/issue22860)
         if self.load_list:
             # TODO: preserve existing suites (like testresources does in
             # OptimisingTestSuite.add, but with a standard protocol).
@@ -173,178 +173,78 @@ class TestProgram(object):
             finally:
                 source.close()
             test_ids = set(line.strip().decode('utf-8') for line in lines)
-            filtered = unittest.TestSuite()
-            for test in iterate_tests(self.test):
-                if test.id() in test_ids:
-                    filtered.addTest(test)
-            self.test = filtered
+            self.test = filter_by_ids(self.test, test_ids)
+        # XXX: Local edit (see http://bugs.python.org/issue22860)
         if not self.listtests:
             self.runTests()
         else:
-            for test in iterate_tests(self.test):
-                stdout.write('%s\n' % test.id())
-
-    def usageExit(self, msg=None):
-        if msg:
-            print(msg)
-        usage = {'progName': self.progName, 'catchbreak': '', 'failfast': '',
-                 'buffer': ''}
-        if self.failfast != False:
-            usage['failfast'] = FAILFAST
-        if self.catchbreak != False:
-            usage['catchbreak'] = CATCHBREAK
-        if self.buffer != False:
-            usage['buffer'] = BUFFEROUTPUT
-        print(self.USAGE % usage)
-        sys.exit(2)
-
-    def parseArgs(self, argv):
-        if len(argv) > 1 and argv[1].lower() == 'discover':
-            self._do_discovery(argv[2:])
-            return
-
-        import getopt
-        long_opts = ['help', 'verbose', 'quiet', 'failfast', 'catch', 'buffer',
-            'list', 'load-list=']
-        try:
-            options, args = getopt.getopt(argv[1:], 'hHvqfcbl', long_opts)
-            for opt, value in options:
-                if opt in ('-h','-H','--help'):
-                    self.usageExit()
-                if opt in ('-q','--quiet'):
-                    self.verbosity = 0
-                if opt in ('-v','--verbose'):
-                    self.verbosity = 2
-                if opt in ('-f','--failfast'):
-                    if self.failfast is None:
-                        self.failfast = True
-                    # Should this raise an exception if -f is not valid?
-                if opt in ('-c','--catch'):
-                    if self.catchbreak is None:
-                        self.catchbreak = True
-                    # Should this raise an exception if -c is not valid?
-                if opt in ('-b','--buffer'):
-                    if self.buffer is None:
-                        self.buffer = True
-                    # Should this raise an exception if -b is not valid?
-                if opt in ('-l', '--list'):
-                    self.listtests = True
-                if opt == '--load-list':
-                    self.load_list = value
-            if len(args) == 0 and self.defaultTest is None:
-                # createTests will load tests from self.module
-                self.testNames = None
-            elif len(args) > 0:
-                self.testNames = args
+            runner = self._get_runner()
+            if safe_hasattr(runner, 'list'):
+                try:
+                    runner.list(self.test, loader=self.testLoader)
+                except TypeError:
+                    runner.list(self.test)
             else:
-                self.testNames = (self.defaultTest,)
-            self.createTests()
-        except getopt.error:
-            self.usageExit(sys.exc_info()[1])
-
-    def createTests(self):
-        if self.testNames is None:
-            self.test = self.testLoader.loadTestsFromModule(self.module)
-        else:
-            self.test = self.testLoader.loadTestsFromNames(self.testNames,
-                                                           self.module)
-
-    def _do_discovery(self, argv, Loader=defaultTestLoaderCls):
-        # handle command line args for test discovery
-        if not have_discover:
-            raise AssertionError("Unable to use discovery, must use python 2.7 "
-                    "or greater, or install the discover package.")
-        self.progName = '%s discover' % self.progName
-        import optparse
-        parser = optparse.OptionParser()
-        parser.prog = self.progName
-        parser.add_option('-v', '--verbose', dest='verbose', default=False,
-                          help='Verbose output', action='store_true')
-        if self.failfast != False:
-            parser.add_option('-f', '--failfast', dest='failfast', default=False,
-                              help='Stop on first fail or error',
-                              action='store_true')
-        if self.catchbreak != False:
-            parser.add_option('-c', '--catch', dest='catchbreak', default=False,
-                              help='Catch ctrl-C and display results so far',
-                              action='store_true')
-        if self.buffer != False:
-            parser.add_option('-b', '--buffer', dest='buffer', default=False,
-                              help='Buffer stdout and stderr during tests',
-                              action='store_true')
-        parser.add_option('-s', '--start-directory', dest='start', default='.',
-                          help="Directory to start discovery ('.' default)")
-        parser.add_option('-p', '--pattern', dest='pattern', default='test*.py',
-                          help="Pattern to match tests ('test*.py' default)")
-        parser.add_option('-t', '--top-level-directory', dest='top', default=None,
-                          help='Top level directory of project (defaults to start directory)')
-        parser.add_option('-l', '--list', dest='listtests', default=False, action="store_true",
-                          help='List tests rather than running them.')
-        parser.add_option('--load-list', dest='load_list', default=None,
-                          help='Specify a filename containing the test ids to use.')
-
-        options, args = parser.parse_args(argv)
-        if len(args) > 3:
-            self.usageExit()
-
-        for name, value in zip(('start', 'pattern', 'top'), args):
-            setattr(options, name, value)
-
-        # only set options from the parsing here
-        # if they weren't set explicitly in the constructor
-        if self.failfast is None:
-            self.failfast = options.failfast
-        if self.catchbreak is None:
-            self.catchbreak = options.catchbreak
-        if self.buffer is None:
-            self.buffer = options.buffer
-        self.listtests = options.listtests
-        self.load_list = options.load_list
-
-        if options.verbose:
-            self.verbosity = 2
-
-        start_dir = options.start
-        pattern = options.pattern
-        top_level_dir = options.top
-
-        loader = Loader()
-        # See http://bugs.python.org/issue16709
-        # While sorting here is intrusive, its better than being random.
-        # Rules for the sort:
-        # - standard suites are flattened, and the resulting tests sorted by
-        #   id.
-        # - non-standard suites are preserved as-is, and sorted into position
-        #   by the first test found by iterating the suite.
-        # We do this by a DSU process: flatten and grab a key, sort, strip the
-        # keys.
-        loaded = loader.discover(start_dir, pattern, top_level_dir)
-        self.test = sorted_tests(loaded)
+                for test in iterate_tests(self.test):
+                    self.stdout.write('%s\n' % test.id())
+        del self.testLoader.errors[:]
+
+    def _getParentArgParser(self):
+        parser = super(TestProgram, self)._getParentArgParser()
+        # XXX: Local edit (see http://bugs.python.org/issue22860)
+        parser.add_argument('-l', '--list', dest='listtests', default=False,
+            action='store_true', help='List tests rather than executing them')
+        parser.add_argument('--load-list', dest='load_list', default=None,
+            help='Specifies a file containing test ids, only tests matching '
+                'those ids are executed')
+        return parser
+
+    def _do_discovery(self, argv, Loader=None):
+        super(TestProgram, self)._do_discovery(argv, Loader=Loader)
+        # XXX: Local edit (see http://bugs.python.org/issue22860)
+        self.test = sorted_tests(self.test)
 
     def runTests(self):
+        # XXX: Local edit (see http://bugs.python.org/issue22860)
         if (self.catchbreak
             and getattr(unittest, 'installHandler', None) is not None):
             unittest.installHandler()
+        testRunner = self._get_runner()
+        self.result = testRunner.run(self.test)
+        if self.exit:
+            sys.exit(not self.result.wasSuccessful())
+
+    def _get_runner(self):
+        # XXX: Local edit (see http://bugs.python.org/issue22860)
         if self.testRunner is None:
             self.testRunner = TestToolsTestRunner
-        if isinstance(self.testRunner, classtypes()):
+        try:
+            testRunner = self.testRunner(verbosity=self.verbosity,
+                                         failfast=self.failfast,
+                                         buffer=self.buffer,
+                                         stdout=self.stdout)
+        except TypeError:
+            # didn't accept the verbosity, buffer, failfast or stdout arguments
+            # Try with the prior contract
             try:
                 testRunner = self.testRunner(verbosity=self.verbosity,
                                              failfast=self.failfast,
                                              buffer=self.buffer)
             except TypeError:
-                # didn't accept the verbosity, buffer or failfast arguments
-                testRunner = self.testRunner()
-        else:
-            # it is assumed to be a TestRunner instance
-            testRunner = self.testRunner
-        self.result = testRunner.run(self.test)
-        if self.exit:
-            sys.exit(not self.result.wasSuccessful())
+                # Now try calling it with defaults
+                try:
+                    testRunner = self.testRunner()
+                except TypeError:
+                    # it is assumed to be a TestRunner instance
+                    testRunner = self.testRunner
+        return testRunner
+
+
+
 ################
 
 def main(argv, stdout):
-    program = TestProgram(argv=argv, testRunner=TestToolsTestRunner,
+    program = TestProgram(argv=argv, testRunner=partial(TestToolsTestRunner, stdout=stdout),
         stdout=stdout)
 
 if __name__ == '__main__':
diff --git a/lib/testtools/testtools/runtest.py b/lib/testtools/testtools/runtest.py
index 507ad87..a29cdd6 100644
--- a/lib/testtools/testtools/runtest.py
+++ b/lib/testtools/testtools/runtest.py
@@ -47,17 +47,23 @@ class RunTest(object):
         reporting of error/failure/skip etc.
     """
 
-    def __init__(self, case, handlers=None):
+    def __init__(self, case, handlers=None, last_resort=None):
         """Create a RunTest to run a case.
 
         :param case: A testtools.TestCase test case object.
         :param handlers: Exception handlers for this RunTest. These are stored
             in self.handlers and can be modified later if needed.
+        :param last_resort: A handler of last resort: any exception which is
+            not handled by handlers will cause the last resort handler to be
+            called as last_resort(exc_info), and then the exception will be
+            raised - aborting the test run as this is inside the runner
+            machinery rather than the confined context of the test.
         """
         self.case = case
         self.handlers = handlers or []
         self.exception_caught = object()
         self._exceptions = []
+        self.last_resort = last_resort or (lambda case, result, exc: None)
 
     def run(self, result=None):
         """Run self.case reporting activity to result.
@@ -106,12 +112,23 @@ class RunTest(object):
                     if isinstance(e, exc_class):
                         handler(self.case, self.result, e)
                         break
+                else:
+                    self.last_resort(self.case, self.result, e)
+                    raise e
         finally:
             result.stopTest(self.case)
         return result
 
     def _run_core(self):
         """Run the user supplied test code."""
+        test_method = self.case._get_test_method()
+        if getattr(test_method, '__unittest_skip__', False):
+            self.result.addSkip(
+                self.case,
+                reason=getattr(test_method, '__unittest_skip_why__', None)
+            )
+            return
+
         if self.exception_caught == self._run_user(self.case._run_setup,
             self.result):
             # Don't run the test method if we failed getting here.
@@ -135,6 +152,9 @@ class RunTest(object):
                         self._run_cleanups, self.result):
                         failed = True
                 finally:
+                    if getattr(self.case, 'force_failure', None):
+                        self._run_user(_raise_force_fail_error)
+                        failed = True
                     if not failed:
                         self.result.addSuccess(self.case,
                             details=self.case.getDetails())
@@ -167,8 +187,6 @@ class RunTest(object):
         """
         try:
             return fn(*args, **kwargs)
-        except KeyboardInterrupt:
-            raise
         except:
             return self._got_user_exception(sys.exc_info())
 
@@ -193,11 +211,15 @@ class RunTest(object):
             self.case.onException(exc_info, tb_label=tb_label)
         finally:
             del exc_info
-        for exc_class, handler in self.handlers:
-            if isinstance(e, exc_class):
-                self._exceptions.append(e)
-                return self.exception_caught
-        raise e
+        self._exceptions.append(e)
+        # Yes, this means we catch everything - we re-raise KeyBoardInterrupt
+        # etc later, after tearDown and cleanUp - since those may be cleaning up
+        # external processes.
+        return self.exception_caught
+
+
+def _raise_force_fail_error():
+    raise AssertionError("Forced Test Failure")
 
 
 # Signal that this is part of the testing framework, and that code from this
diff --git a/lib/testtools/testtools/testcase.py b/lib/testtools/testtools/testcase.py
index fc5f863..cc4d6eb 100644
--- a/lib/testtools/testtools/testcase.py
+++ b/lib/testtools/testtools/testcase.py
@@ -4,6 +4,7 @@
 
 __metaclass__ = type
 __all__ = [
+    'attr',
     'clone_test_with_new_id',
     'ExpectedException',
     'gather_details',
@@ -15,14 +16,19 @@ __all__ = [
     ]
 
 import copy
+import functools
 import itertools
 import sys
 import types
-import unittest
+
+from extras import (
+    safe_hasattr,
+    try_import,
+    )
+import unittest2 as unittest
 
 from testtools import (
     content,
-    try_import,
     )
 from testtools.compat import (
     advance_iterator,
@@ -51,8 +57,8 @@ wraps = try_import('functools.wraps')
 
 class TestSkipped(Exception):
     """Raised within TestCase.run() when a test is skipped."""
-testSkipped = try_import('unittest2.case.SkipTest', TestSkipped)
 TestSkipped = try_import('unittest.case.SkipTest', TestSkipped)
+TestSkipped = try_import('unittest2.case.SkipTest', TestSkipped)
 
 
 class _UnexpectedSuccess(Exception):
@@ -62,9 +68,9 @@ class _UnexpectedSuccess(Exception):
     module.
     """
 _UnexpectedSuccess = try_import(
-    'unittest2.case._UnexpectedSuccess', _UnexpectedSuccess)
-_UnexpectedSuccess = try_import(
     'unittest.case._UnexpectedSuccess', _UnexpectedSuccess)
+_UnexpectedSuccess = try_import(
+    'unittest2.case._UnexpectedSuccess', _UnexpectedSuccess)
 
 class _ExpectedFailure(Exception):
     """An expected failure occured.
@@ -73,9 +79,23 @@ class _ExpectedFailure(Exception):
     module.
     """
 _ExpectedFailure = try_import(
-    'unittest2.case._ExpectedFailure', _ExpectedFailure)
-_ExpectedFailure = try_import(
     'unittest.case._ExpectedFailure', _ExpectedFailure)
+_ExpectedFailure = try_import(
+    'unittest2.case._ExpectedFailure', _ExpectedFailure)
+
+
+# Copied from unittest before python 3.4 release. Used to maintain
+# compatibility with unittest sub-test feature. Users should not use this
+# directly.
+def _expectedFailure(func):
+    @functools.wraps(func)
+    def wrapper(*args, **kwargs):
+        try:
+            func(*args, **kwargs)
+        except Exception:
+            raise _ExpectedFailure(sys.exc_info())
+        raise _UnexpectedSuccess
+    return wrapper
 
 
 def run_test_with(test_runner, **kwargs):
@@ -106,9 +126,16 @@ def run_test_with(test_runner, **kwargs):
     def decorator(function):
         # Set an attribute on 'function' which will inform TestCase how to
         # make the runner.
-        function._run_test_with = (
-            lambda case, handlers=None:
-                test_runner(case, handlers=handlers, **kwargs))
+        def _run_test_with(case, handlers=None, last_resort=None):
+            try:
+                return test_runner(
+                    case, handlers=handlers, last_resort=last_resort,
+                    **kwargs)
+            except TypeError:
+                # Backwards compat: if we can't call the constructor
+                # with last_resort, try without that.
+                return test_runner(case, handlers=handlers, **kwargs)
+        function._run_test_with = _run_test_with
         return function
     return decorator
 
@@ -150,6 +177,8 @@ class TestCase(unittest.TestCase):
     :ivar exception_handlers: Exceptions to catch from setUp, runTest and
         tearDown. This list is able to be modified at any time and consists of
         (exception_class, handler(case, result, exception_value)) pairs.
+    :ivar force_failure: Force testtools.RunTest to fail the test after the
+        test has completed.
     :cvar run_tests_with: A factory to make the ``RunTest`` to run tests with.
         Defaults to ``RunTest``.  The factory is expected to take a test case
         and an optional list of exception handlers.
@@ -185,7 +214,12 @@ class TestCase(unittest.TestCase):
             runTest = getattr(
                 test_method, '_run_test_with', self.run_tests_with)
         self.__RunTest = runTest
+        if getattr(test_method, '__unittest_expecting_failure__', False):
+            setattr(self, self._testMethodName, _expectedFailure(test_method))
+        # Used internally for onException processing - used to gather extra
+        # data from exceptions.
         self.__exception_handlers = []
+        # Passed to RunTest to map exceptions to result actions
         self.exception_handlers = [
             (self.skipException, self._report_skip),
             (self.failureException, self._report_failure),
@@ -193,9 +227,6 @@ class TestCase(unittest.TestCase):
             (_UnexpectedSuccess, self._report_unexpected_success),
             (Exception, self._report_error),
             ]
-        if sys.version_info < (2, 6):
-            # Catch old-style string exceptions with None as the instance
-            self.exception_handlers.append((type(None), self._report_error))
 
     def __eq__(self, other):
         eq = getattr(unittest.TestCase, '__eq__', None)
@@ -318,9 +349,9 @@ class TestCase(unittest.TestCase):
 
     failUnlessEqual = assertEquals = assertEqual
 
-    def assertIn(self, needle, haystack):
+    def assertIn(self, needle, haystack, message=''):
         """Assert that needle is in haystack."""
-        self.assertThat(haystack, Contains(needle))
+        self.assertThat(haystack, Contains(needle), message)
 
     def assertIsNone(self, observed, message=''):
         """Assert that 'observed' is equal to None.
@@ -355,10 +386,10 @@ class TestCase(unittest.TestCase):
         matcher = Not(Is(expected))
         self.assertThat(observed, matcher, message)
 
-    def assertNotIn(self, needle, haystack):
+    def assertNotIn(self, needle, haystack, message=''):
         """Assert that needle is not in haystack."""
         matcher = Not(Contains(needle))
-        self.assertThat(haystack, matcher)
+        self.assertThat(haystack, matcher, message)
 
     def assertIsInstance(self, obj, klass, msg=None):
         if isinstance(klass, tuple):
@@ -397,19 +428,62 @@ class TestCase(unittest.TestCase):
         :param matcher: An object meeting the testtools.Matcher protocol.
         :raises MismatchError: When matcher does not match thing.
         """
+        mismatch_error = self._matchHelper(matchee, matcher, message, verbose)
+        if mismatch_error is not None:
+            raise mismatch_error
+
+    def addDetailUniqueName(self, name, content_object):
+        """Add a detail to the test, but ensure it's name is unique.
+
+        This method checks whether ``name`` conflicts with a detail that has
+        already been added to the test. If it does, it will modify ``name`` to
+        avoid the conflict.
+
+        For more details see pydoc testtools.TestResult.
+
+        :param name: The name to give this detail.
+        :param content_object: The content object for this detail. See
+            testtools.content for more detail.
+        """
+        existing_details = self.getDetails()
+        full_name = name
+        suffix = 1
+        while full_name in existing_details:
+            full_name = "%s-%d" % (name, suffix)
+            suffix += 1
+        self.addDetail(full_name, content_object)
+
+    def expectThat(self, matchee, matcher, message='', verbose=False):
+        """Check that matchee is matched by matcher, but delay the assertion failure.
+
+        This method behaves similarly to ``assertThat``, except that a failed
+        match does not exit the test immediately. The rest of the test code will
+        continue to run, and the test will be marked as failing after the test
+        has finished.
+
+        :param matchee: An object to match with matcher.
+        :param matcher: An object meeting the testtools.Matcher protocol.
+        :param message: If specified, show this message with any failed match.
+        """
+        mismatch_error = self._matchHelper(matchee, matcher, message, verbose)
+
+        if mismatch_error is not None:
+            self.addDetailUniqueName(
+                "Failed expectation",
+                content.StacktraceContent(
+                    postfix_content="MismatchError: " + str(mismatch_error)
+                )
+            )
+            self.force_failure = True
+
+    def _matchHelper(self, matchee, matcher, message, verbose):
         matcher = Annotate.if_message(message, matcher)
         mismatch = matcher.match(matchee)
         if not mismatch:
             return
-        existing_details = self.getDetails()
-        for (name, content) in mismatch.get_details().items():
-            full_name = name
-            suffix = 1
-            while full_name in existing_details:
-                full_name = "%s-%d" % (name, suffix)
-                suffix += 1
-            self.addDetail(full_name, content)
-        raise MismatchError(matchee, matcher, mismatch, verbose)
+        for (name, value) in mismatch.get_details().items():
+            self.addDetailUniqueName(name, value)
+        return MismatchError(matchee, matcher, mismatch, verbose)
 
     def defaultTestResult(self):
         return TestResult()
@@ -505,9 +579,12 @@ class TestCase(unittest.TestCase):
     def _report_traceback(self, exc_info, tb_label='traceback'):
         id_gen = self._traceback_id_gens.setdefault(
             tb_label, itertools.count(0))
-        tb_id = advance_iterator(id_gen)
-        if tb_id:
-            tb_label = '%s-%d' % (tb_label, tb_id)
+        while True:
+            tb_id = advance_iterator(id_gen)
+            if tb_id:
+                tb_label = '%s-%d' % (tb_label, tb_id)
+            if tb_label not in self.getDetails():
+                break
         self.addDetail(tb_label, content.TracebackContent(exc_info, self))
 
     @staticmethod
@@ -515,7 +592,14 @@ class TestCase(unittest.TestCase):
         result.addUnexpectedSuccess(self, details=self.getDetails())
 
     def run(self, result=None):
-        return self.__RunTest(self, self.exception_handlers).run(result)
+        try:
+            run_test = self.__RunTest(
+                self, self.exception_handlers, last_resort=self._report_error)
+        except TypeError:
+            # Backwards compat: if we can't call the constructor
+            # with last_resort, try without that.
+            run_test = self.__RunTest(self, self.exception_handlers)
+        return run_test.run(result)
 
     def _run_setup(self, result):
         """Run the setUp function for this test.
@@ -527,10 +611,12 @@ class TestCase(unittest.TestCase):
         ret = self.setUp()
         if not self.__setup_called:
             raise ValueError(
+                "In File: %s\n"
                 "TestCase.setUp was not called. Have you upcalled all the "
                 "way up the hierarchy from your setUp? e.g. Call "
                 "super(%s, self).setUp() from your setUp()."
-                % self.__class__.__name__)
+                % (sys.modules[self.__class__.__module__].__file__,
+                   self.__class__.__name__))
         return ret
 
     def _run_teardown(self, result):
@@ -543,19 +629,16 @@ class TestCase(unittest.TestCase):
         ret = self.tearDown()
         if not self.__teardown_called:
             raise ValueError(
+                "In File: %s\n"
                 "TestCase.tearDown was not called. Have you upcalled all the "
                 "way up the hierarchy from your tearDown? e.g. Call "
                 "super(%s, self).tearDown() from your tearDown()."
-                % self.__class__.__name__)
+                % (sys.modules[self.__class__.__module__].__file__,
+                   self.__class__.__name__))
         return ret
 
     def _get_test_method(self):
-        absent_attr = object()
-        # Python 2.5+
-        method_name = getattr(self, '_testMethodName', absent_attr)
-        if method_name is absent_attr:
-            # Python 2.4
-            method_name = getattr(self, '_TestCase__testMethodName')
+        method_name = getattr(self, '_testMethodName')
         return getattr(self, method_name)
 
     def _run_test_method(self, result):
@@ -578,8 +661,18 @@ class TestCase(unittest.TestCase):
         try:
             fixture.setUp()
         except:
-            gather_details(fixture.getDetails(), self.getDetails())
-            raise
+            exc_info = sys.exc_info()
+            try:
+                gather_details(fixture.getDetails(), self.getDetails())
+            except:
+                # Report the setUp exception, then raise the error during
+                # gather_details.
+                self._report_traceback(exc_info)
+                raise
+            else:
+                # Gather_details worked, so raise the exception setUp
+                # encountered.
+                reraise(*exc_info)
         else:
             self.addCleanup(fixture.cleanUp)
             self.addCleanup(
@@ -588,11 +681,24 @@ class TestCase(unittest.TestCase):
 
     def setUp(self):
         super(TestCase, self).setUp()
+        if self.__setup_called:
+            raise ValueError(
+                "In File: %s\n"
+                "TestCase.setUp was already called. Do not explicitly call "
+                "setUp from your tests. In your own setUp, use super to call "
+                "the base setUp."
+                % (sys.modules[self.__class__.__module__].__file__,))
         self.__setup_called = True
 
     def tearDown(self):
         super(TestCase, self).tearDown()
-        unittest.TestCase.tearDown(self)
+        if self.__teardown_called:
+            raise ValueError(
+                "In File: %s\n"
+                "TestCase.tearDown was already called. Do not explicitly call "
+                "tearDown from your tests. In your own tearDown, use super to "
+                "call the base tearDown."
+                % (sys.modules[self.__class__.__module__].__file__,))
         self.__teardown_called = True
 
 
@@ -606,7 +712,7 @@ class PlaceHolder(object):
     failureException = None
 
     def __init__(self, test_id, short_description=None, details=None,
-        outcome='addSuccess', error=None):
+        outcome='addSuccess', error=None, tags=None, timestamps=(None, None)):
         """Construct a `PlaceHolder`.
 
         :param test_id: The id of the placeholder test.
@@ -614,6 +720,9 @@ class PlaceHolder(object):
             test. If not provided, the id will be used instead.
         :param details: Outcome details as accepted by addSuccess etc.
         :param outcome: The outcome to call. Defaults to 'addSuccess'.
+        :param tags: Tags to report for the test.
+        :param timestamps: A two-tuple of timestamps for the test start and
+            finish. Each timestamp may be None to indicate it is not known.
         """
         self._test_id = test_id
         self._short_description = short_description
@@ -621,6 +730,9 @@ class PlaceHolder(object):
         self._outcome = outcome
         if error is not None:
             self._details['traceback'] = content.TracebackContent(error, self)
+        tags = tags or frozenset()
+        self._tags = frozenset(tags)
+        self._timestamps = timestamps
 
     def __call__(self, result=None):
         return self.run(result=result)
@@ -654,10 +766,16 @@ class PlaceHolder(object):
 
     def run(self, result=None):
         result = self._result(result)
+        if self._timestamps[0] is not None:
+            result.time(self._timestamps[0])
+        result.tags(self._tags, set())
         result.startTest(self)
+        if self._timestamps[1] is not None:
+            result.time(self._timestamps[1])
         outcome = getattr(result, self._outcome)
         outcome(self, details=self._details)
         result.stopTest(self)
+        result.tags(set(), self._tags)
 
     def shortDescription(self):
         if self._short_description is None:
@@ -680,9 +798,19 @@ def ErrorHolder(test_id, error, short_description=None, details=None):
         details=details, outcome='addError', error=error)
 
 
-# Python 2.4 did not know how to copy functions.
-if types.FunctionType not in copy._copy_dispatch:
-    copy._copy_dispatch[types.FunctionType] = copy._copy_immutable
+def _clone_test_id_callback(test, callback):
+    """Copy a `TestCase`, and make it call callback for its id().
+
+    This is only expected to be used on tests that have been constructed but
+    not executed.
+
+    :param test: A TestCase instance.
+    :param callback: A callable that takes no parameters and returns a string.
+    :return: A copy.copy of the test with id=callback.
+    """
+    newTest = copy.copy(test)
+    newTest.id = callback
+    return newTest
 
 
 def clone_test_with_new_id(test, new_id):
@@ -691,9 +819,45 @@ def clone_test_with_new_id(test, new_id):
     This is only expected to be used on tests that have been constructed but
     not executed.
     """
-    newTest = copy.copy(test)
-    newTest.id = lambda: new_id
-    return newTest
+    return _clone_test_id_callback(test, lambda: new_id)
+
+
+def attr(*args):
+    """Decorator for adding attributes to WithAttributes.
+
+    :param args: The name of attributes to add.
+    :return: A callable that when applied to a WithAttributes will
+        alter its id to enumerate the added attributes.
+    """
+    def decorate(fn):
+        if not safe_hasattr(fn, '__testtools_attrs'):
+            fn.__testtools_attrs = set()
+        fn.__testtools_attrs.update(args)
+        return fn
+    return decorate
+
+
+class WithAttributes(object):
+    """A mix-in class for modifying test id by attributes.
+
+    e.g.
+    >>> class MyTest(WithAttributes, TestCase):
+    ...    @attr('foo')
+    ...    def test_bar(self):
+    ...        pass
+    >>> MyTest('test_bar').id()
+    testtools.testcase.MyTest/test_bar[foo]
+    """
+
+    def id(self):
+        orig = super(WithAttributes, self).id()
+        # Depends on testtools.TestCase._get_test_method, be nice to support
+        # plain unittest.
+        fn = self._get_test_method()
+        attributes = getattr(fn, '__testtools_attrs', None)
+        if not attributes:
+            return orig
+        return orig + '[' + ','.join(sorted(attributes)) + ']'
 
 
 def skip(reason):
@@ -704,6 +868,12 @@ def skip(reason):
     @unittest.skip decorator.
     """
     def decorator(test_item):
+        # This attribute signals to RunTest._run_core that the entire test
+        # must be skipped - including setUp and tearDown. This makes us
+        # compatible with testtools.skip* functions, which set the same
+        # attributes.
+        test_item.__unittest_skip__ = True
+        test_item.__unittest_skip_why__ = reason
         if wraps is not None:
             @wraps(test_item)
             def skip_wrapper(*args, **kwargs):
@@ -716,7 +886,7 @@ def skip(reason):
 
 
 def skipIf(condition, reason):
-    """Skip a test if the condition is true."""
+    """A decorator to skip a test if the condition is true."""
     if condition:
         return skip(reason)
     def _id(obj):
@@ -725,7 +895,7 @@ def skipIf(condition, reason):
 
 
 def skipUnless(condition, reason):
-    """Skip a test unless the condition is true."""
+    """A decorator to skip a test unless the condition is true."""
     if not condition:
         return skip(reason)
     def _id(obj):
@@ -736,8 +906,6 @@ def skipUnless(condition, reason):
 class ExpectedException:
     """A context manager to handle expected exceptions.
 
-    In Python 2.5 or later::
-
       def test_foo(self):
           with ExpectedException(ValueError, 'fo.*'):
               raise ValueError('foo')
@@ -748,26 +916,33 @@ class ExpectedException:
     exception is raised, an AssertionError will be raised.
     """
 
-    def __init__(self, exc_type, value_re=None):
+    def __init__(self, exc_type, value_re=None, msg=None):
         """Construct an `ExpectedException`.
 
         :param exc_type: The type of exception to expect.
         :param value_re: A regular expression to match against the
             'str()' of the raised exception.
+        :param msg: An optional message explaining the failure.
         """
         self.exc_type = exc_type
         self.value_re = value_re
+        self.msg = msg
 
     def __enter__(self):
         pass
 
     def __exit__(self, exc_type, exc_value, traceback):
         if exc_type is None:
-            raise AssertionError('%s not raised.' % self.exc_type.__name__)
+            error_msg = '%s not raised.' % self.exc_type.__name__
+            if self.msg:
+                error_msg = error_msg + ' : ' + self.msg
+            raise AssertionError(error_msg)
         if exc_type != self.exc_type:
             return False
         if self.value_re:
             matcher = MatchesException(self.exc_type, self.value_re)
+            if self.msg:
+                matcher = Annotate(self.msg, matcher)
             mismatch = matcher.match((exc_type, exc_value, traceback))
             if mismatch:
                 raise AssertionError(mismatch.describe())
@@ -793,6 +968,55 @@ class Nullary(object):
         return repr(self._callable_object)
 
 
+class DecorateTestCaseResult(object):
+    """Decorate a TestCase and permit customisation of the result for runs."""
+
+    def __init__(self, case, callout, before_run=None, after_run=None):
+        """Construct a DecorateTestCaseResult.
+
+        :param case: The case to decorate.
+        :param callout: A callback to call when run/__call__/debug is called.
+            Must take a result parameter and return a result object to be used.
+            For instance: lambda result: result.
+        :param before_run: If set, call this with the decorated result before
+            calling into the decorated run/__call__ method.
+        :param before_run: If set, call this with the decorated result after
+            calling into the decorated run/__call__ method.
+        """
+        self.decorated = case
+        self.callout = callout
+        self.before_run = before_run
+        self.after_run = after_run
+
+    def _run(self, result, run_method):
+        result = self.callout(result)
+        if self.before_run:
+            self.before_run(result)
+        try:
+            return run_method(result)
+        finally:
+            if self.after_run:
+                self.after_run(result)
+
+    def run(self, result=None):
+        self._run(result, self.decorated.run)
+
+    def __call__(self, result=None):
+        self._run(result, self.decorated)
+
+    def __getattr__(self, name):
+        return getattr(self.decorated, name)
+
+    def __delattr__(self, name):
+        delattr(self.decorated, name)
+
+    def __setattr__(self, name, value):
+        if name in ('decorated', 'callout', 'before_run', 'after_run'):
+            self.__dict__[name] = value
+            return
+        setattr(self.decorated, name, value)
+
+
 # Signal that this is part of the testing framework, and that code from this
 # should not normally appear in tracebacks.
 __unittest = True
diff --git a/lib/testtools/testtools/testresult/__init__.py b/lib/testtools/testtools/testresult/__init__.py
index d37a772..5bf8f9c 100644
--- a/lib/testtools/testtools/testresult/__init__.py
+++ b/lib/testtools/testtools/testresult/__init__.py
@@ -3,23 +3,47 @@
 """Test result objects."""
 
 __all__ = [
+    'CopyStreamResult',
     'ExtendedToOriginalDecorator',
+    'ExtendedToStreamDecorator',
     'MultiTestResult',
+    'StreamFailFast',
+    'StreamResult',
+    'StreamResultRouter',
+    'StreamSummary',
+    'StreamTagger',
+    'StreamToDict',
+    'StreamToExtendedDecorator',
+    'StreamToQueue',
     'Tagger',
     'TestByTestResult',
+    'TestControl',
     'TestResult',
     'TestResultDecorator',
     'TextTestResult',
     'ThreadsafeForwardingResult',
+    'TimestampingStreamResult',
     ]
 
 from testtools.testresult.real import (
+    CopyStreamResult,
     ExtendedToOriginalDecorator,
+    ExtendedToStreamDecorator,
     MultiTestResult,
+    StreamFailFast,
+    StreamResult,
+    StreamResultRouter,
+    StreamSummary,
+    StreamTagger,
+    StreamToDict,
+    StreamToExtendedDecorator,
+    StreamToQueue,
     Tagger,
     TestByTestResult,
+    TestControl,
     TestResult,
     TestResultDecorator,
     TextTestResult,
     ThreadsafeForwardingResult,
+    TimestampingStreamResult,
     )
diff --git a/lib/testtools/testtools/testresult/doubles.py b/lib/testtools/testtools/testresult/doubles.py
index 1865e93..d86f7fa 100644
--- a/lib/testtools/testtools/testresult/doubles.py
+++ b/lib/testtools/testtools/testresult/doubles.py
@@ -6,6 +6,7 @@ __all__ = [
     'Python26TestResult',
     'Python27TestResult',
     'ExtendedTestResult',
+    'StreamResult',
     ]
 
 
@@ -148,3 +149,26 @@ class ExtendedTestResult(Python27TestResult):
 
     def wasSuccessful(self):
         return self._was_successful
+
+
+class StreamResult(object):
+    """A StreamResult implementation for testing.
+
+    All events are logged to _events.
+    """
+
+    def __init__(self):
+        self._events = []
+
+    def startTestRun(self):
+        self._events.append(('startTestRun',))
+
+    def stopTestRun(self):
+        self._events.append(('stopTestRun',))
+
+    def status(self, test_id=None, test_status=None, test_tags=None,
+        runnable=True, file_name=None, file_bytes=None, eof=False,
+        mime_type=None, route_code=None, timestamp=None):
+        self._events.append(('status', test_id, test_status, test_tags,
+            runnable, file_name, file_bytes, eof, mime_type, route_code,
+            timestamp))
diff --git a/lib/testtools/testtools/testresult/real.py b/lib/testtools/testtools/testresult/real.py
index 0a69872..1453041 100644
--- a/lib/testtools/testtools/testresult/real.py
+++ b/lib/testtools/testtools/testresult/real.py
@@ -5,24 +5,43 @@
 __metaclass__ = type
 __all__ = [
     'ExtendedToOriginalDecorator',
+    'ExtendedToStreamDecorator',
     'MultiTestResult',
+    'StreamFailFast',
+    'StreamResult',
+    'StreamSummary',
+    'StreamTagger',
+    'StreamToDict',
+    'StreamToExtendedDecorator',
+    'StreamToQueue',
     'Tagger',
+    'TestControl',
     'TestResult',
     'TestResultDecorator',
     'ThreadsafeForwardingResult',
+    'TimestampingStreamResult',
     ]
 
 import datetime
+from operator import methodcaller
 import sys
 import unittest
 
-from testtools.compat import all, str_is_unicode, _u
+from extras import safe_hasattr, try_import, try_imports
+parse_mime_type = try_import('mimeparse.parse_mime_type')
+Queue = try_imports(['Queue.Queue', 'queue.Queue'])
+
+from testtools.compat import str_is_unicode, _u, _b
 from testtools.content import (
+    Content,
     text_content,
     TracebackContent,
     )
-from testtools.helpers import safe_hasattr
+from testtools.content_type import ContentType
 from testtools.tags import TagContext
+# circular import
+# from testtools.testcase import PlaceHolder
+PlaceHolder = None
 
 # From http://docs.python.org/library/datetime.html
 _ZERO = datetime.timedelta(0)
@@ -243,6 +262,531 @@ class TestResult(unittest.TestResult):
         """
 
 
+class StreamResult(object):
+    """A test result for reporting the activity of a test run.
+
+    Typical use
+
+      >>> result = StreamResult()
+      >>> result.startTestRun()
+      >>> try:
+      ...     case.run(result)
+      ... finally:
+      ...     result.stopTestRun()
+
+    The case object will be either a TestCase or a TestSuite, and
+    generally make a sequence of calls like::
+
+      >>> result.status(self.id(), 'inprogress')
+      >>> result.status(self.id(), 'success')
+
+    General concepts
+
+    StreamResult is built to process events that are emitted by tests during a
+    test run or test enumeration. The test run may be running concurrently, and
+    even be spread out across multiple machines.
+
+    All events are timestamped to prevent network buffering or scheduling
+    latency causing false timing reports. Timestamps are datetime objects in
+    the UTC timezone.
+
+    A route_code is a unicode string that identifies where a particular test
+    run. This is optional in the API but very useful when multiplexing multiple
+    streams together as it allows identification of interactions between tests
+    that were run on the same hardware or in the same test process. Generally
+    actual tests never need to bother with this - it is added and processed
+    by StreamResult's that do multiplexing / run analysis. route_codes are
+    also used to route stdin back to pdb instances.
+
+    The StreamResult base class does no accounting or processing, rather it
+    just provides an empty implementation of every method, suitable for use
+    as a base class regardless of intent.
+    """
+
+    def startTestRun(self):
+        """Start a test run.
+
+        This will prepare the test result to process results (which might imply
+        connecting to a database or remote machine).
+        """
+
+    def stopTestRun(self):
+        """Stop a test run.
+
+        This informs the result that no more test updates will be received. At
+        this point any test ids that have started and not completed can be
+        considered failed-or-hung.
+        """
+
+    def status(self, test_id=None, test_status=None, test_tags=None,
+        runnable=True, file_name=None, file_bytes=None, eof=False,
+        mime_type=None, route_code=None, timestamp=None):
+        """Inform the result about a test status.
+
+        :param test_id: The test whose status is being reported. None to
+            report status about the test run as a whole.
+        :param test_status: The status for the test. There are two sorts of
+            status - interim and final status events. As many interim events
+            can be generated as desired, but only one final event. After a
+            final status event any further file or status events from the
+            same test_id+route_code may be discarded or associated with a new
+            test by the StreamResult. (But no exception will be thrown).
+
+            Interim states:
+              * None - no particular status is being reported, or status being
+                reported is not associated with a test (e.g. when reporting on
+                stdout / stderr chatter).
+              * inprogress - the test is currently running. Emitted by tests when
+                they start running and at any intermediary point they might
+                choose to indicate their continual operation.
+
+            Final states:
+              * exists - the test exists. This is used when a test is not being
+                executed. Typically this is when querying what tests could be run
+                in a test run (which is useful for selecting tests to run).
+              * xfail - the test failed but that was expected. This is purely
+                informative - the test is not considered to be a failure.
+              * uxsuccess - the test passed but was expected to fail. The test
+                will be considered a failure.
+              * success - the test has finished without error.
+              * fail - the test failed (or errored). The test will be considered
+                a failure.
+              * skip - the test was selected to run but chose to be skipped. E.g.
+                a test dependency was missing. This is purely informative - the
+                test is not considered to be a failure.
+
+        :param test_tags: Optional set of tags to apply to the test. Tags
+            have no intrinsic meaning - that is up to the test author.
+        :param runnable: Allows status reports to mark that they are for
+            tests which are not able to be explicitly run. For instance,
+            subtests will report themselves as non-runnable.
+        :param file_name: The name for the file_bytes. Any unicode string may
+            be used. While there is no semantic value attached to the name
+            of any attachment, the names 'stdout' and 'stderr' and 'traceback'
+            are recommended for use only for output sent to stdout, stderr and
+            tracebacks of exceptions. When file_name is supplied, file_bytes
+            must be a bytes instance.
+        :param file_bytes: A bytes object containing content for the named
+            file. This can just be a single chunk of the file - emitting
+            another file event with more later. Must be None unleses a
+            file_name is supplied.
+        :param eof: True if this chunk is the last chunk of the file, any
+            additional chunks with the same name should be treated as an error
+            and discarded. Ignored unless file_name has been supplied.
+        :param mime_type: An optional MIME type for the file. stdout and
+            stderr will generally be "text/plain; charset=utf8". If None,
+            defaults to application/octet-stream. Ignored unless file_name
+            has been supplied.
+        """
+
+
+def domap(*args, **kwargs):
+    return list(map(*args, **kwargs))
+
+
+class CopyStreamResult(StreamResult):
+    """Copies all event it receives to multiple results.
+
+    This provides an easy facility for combining multiple StreamResults.
+
+    For TestResult the equivalent class was ``MultiTestResult``.
+    """
+
+    def __init__(self, targets):
+        super(CopyStreamResult, self).__init__()
+        self.targets = targets
+
+    def startTestRun(self):
+        super(CopyStreamResult, self).startTestRun()
+        domap(methodcaller('startTestRun'), self.targets)
+
+    def stopTestRun(self):
+        super(CopyStreamResult, self).stopTestRun()
+        domap(methodcaller('stopTestRun'), self.targets)
+
+    def status(self, *args, **kwargs):
+        super(CopyStreamResult, self).status(*args, **kwargs)
+        domap(methodcaller('status', *args, **kwargs), self.targets)
+
+
+class StreamFailFast(StreamResult):
+    """Call the supplied callback if an error is seen in a stream.
+
+    An example callback::
+
+       def do_something():
+           pass
+    """
+
+    def __init__(self, on_error):
+        self.on_error = on_error
+
+    def status(self, test_id=None, test_status=None, test_tags=None,
+        runnable=True, file_name=None, file_bytes=None, eof=False,
+        mime_type=None, route_code=None, timestamp=None):
+        if test_status in ('uxsuccess', 'fail'):
+            self.on_error()
+
+
+class StreamResultRouter(StreamResult):
+    """A StreamResult that routes events.
+
+    StreamResultRouter forwards received events to another StreamResult object,
+    selected by a dynamic forwarding policy. Events where no destination is
+    found are forwarded to the fallback StreamResult, or an error is raised.
+
+    Typical use is to construct a router with a fallback and then either
+    create up front mapping rules, or create them as-needed from the fallback
+    handler::
+
+      >>> router = StreamResultRouter()
+      >>> sink = doubles.StreamResult()
+      >>> router.add_rule(sink, 'route_code_prefix', route_prefix='0',
+      ...     consume_route=True)
+      >>> router.status(test_id='foo', route_code='0/1', test_status='uxsuccess')
+
+    StreamResultRouter has no buffering.
+
+    When adding routes (and for the fallback) whether to call startTestRun and
+    stopTestRun or to not call them is controllable by passing
+    'do_start_stop_run'. The default is to call them for the fallback only.
+    If a route is added after startTestRun has been called, and
+    do_start_stop_run is True then startTestRun is called immediately on the
+    new route sink.
+
+    There is no a-priori defined lookup order for routes: if they are ambiguous
+    the behaviour is undefined. Only a single route is chosen for any event.
+    """
+
+    _policies = {}
+
+    def __init__(self, fallback=None, do_start_stop_run=True):
+        """Construct a StreamResultRouter with optional fallback.
+
+        :param fallback: A StreamResult to forward events to when no route
+            exists for them.
+        :param do_start_stop_run: If False do not pass startTestRun and
+            stopTestRun onto the fallback.
+        """
+        self.fallback = fallback
+        self._route_code_prefixes = {}
+        self._test_ids = {}
+        # Records sinks that should have do_start_stop_run called on them.
+        self._sinks = []
+        if do_start_stop_run and fallback:
+            self._sinks.append(fallback)
+        self._in_run = False
+
+    def startTestRun(self):
+        super(StreamResultRouter, self).startTestRun()
+        for sink in self._sinks:
+            sink.startTestRun()
+        self._in_run = True
+
+    def stopTestRun(self):
+        super(StreamResultRouter, self).stopTestRun()
+        for sink in self._sinks:
+            sink.stopTestRun()
+        self._in_run = False
+
+    def status(self, **kwargs):
+        route_code = kwargs.get('route_code', None)
+        test_id = kwargs.get('test_id', None)
+        if route_code is not None:
+            prefix = route_code.split('/')[0]
+        else:
+            prefix = route_code
+        if prefix in self._route_code_prefixes:
+            target, consume_route = self._route_code_prefixes[prefix]
+            if route_code is not None and consume_route:
+                route_code = route_code[len(prefix) + 1:]
+                if not route_code:
+                    route_code = None
+                kwargs['route_code'] = route_code
+        elif test_id in self._test_ids:
+            target = self._test_ids[test_id]
+        else:
+            target = self.fallback
+        target.status(**kwargs)
+
+    def add_rule(self, sink, policy, do_start_stop_run=False, **policy_args):
+        """Add a rule to route events to sink when they match a given policy.
+
+        :param sink: A StreamResult to receive events.
+        :param policy: A routing policy. Valid policies are
+            'route_code_prefix' and 'test_id'.
+        :param do_start_stop_run: If True then startTestRun and stopTestRun
+            events will be passed onto this sink.
+
+        :raises: ValueError if the policy is unknown
+        :raises: TypeError if the policy is given arguments it cannot handle.
+
+        ``route_code_prefix`` routes events based on a prefix of the route
+        code in the event. It takes a ``route_prefix`` argument to match on
+        (e.g. '0') and a ``consume_route`` argument, which, if True, removes
+        the prefix from the ``route_code`` when forwarding events.
+
+        ``test_id`` routes events based on the test id.  It takes a single
+        argument, ``test_id``.  Use ``None`` to select non-test events.
+        """
+        policy_method = StreamResultRouter._policies.get(policy, None)
+        if not policy_method:
+            raise ValueError("bad policy %r" % (policy,))
+        policy_method(self, sink, **policy_args)
+        if do_start_stop_run:
+            self._sinks.append(sink)
+        if self._in_run:
+            sink.startTestRun()
+
+    def _map_route_code_prefix(self, sink, route_prefix, consume_route=False):
+        if '/' in route_prefix:
+            raise TypeError(
+                "%r is more than one route step long" % (route_prefix,))
+        self._route_code_prefixes[route_prefix] = (sink, consume_route)
+    _policies['route_code_prefix'] = _map_route_code_prefix
+
+    def _map_test_id(self, sink, test_id):
+        self._test_ids[test_id] = sink
+    _policies['test_id'] = _map_test_id
+
+
+class StreamTagger(CopyStreamResult):
+    """Adds or discards tags from StreamResult events."""
+
+    def __init__(self, targets, add=None, discard=None):
+        """Create a StreamTagger.
+
+        :param targets: A list of targets to forward events onto.
+        :param add: Either None or an iterable of tags to add to each event.
+        :param discard: Either None or an iterable of tags to discard from each
+            event.
+        """
+        super(StreamTagger, self).__init__(targets)
+        self.add = frozenset(add or ())
+        self.discard = frozenset(discard or ())
+
+    def status(self, *args, **kwargs):
+        test_tags = kwargs.get('test_tags') or set()
+        test_tags.update(self.add)
+        test_tags.difference_update(self.discard)
+        kwargs['test_tags'] = test_tags or None
+        super(StreamTagger, self).status(*args, **kwargs)
+
+
+class StreamToDict(StreamResult):
+    """A specialised StreamResult that emits a callback as tests complete.
+
+    Top level file attachments are simply discarded. Hung tests are detected
+    by stopTestRun and notified there and then.
+
+    The callback is passed a dict with the following keys:
+
+      * id: the test id.
+      * tags: The tags for the test. A set of unicode strings.
+      * details: A dict of file attachments - ``testtools.content.Content``
+        objects.
+      * status: One of the StreamResult status codes (including inprogress) or
+        'unknown' (used if only file events for a test were received...)
+      * timestamps: A pair of timestamps - the first one received with this
+        test id, and the one in the event that triggered the notification.
+        Hung tests have a None for the second end event. Timestamps are not
+        compared - their ordering is purely order received in the stream.
+
+    Only the most recent tags observed in the stream are reported.
+    """
+
+    def __init__(self, on_test):
+        """Create a StreamToDict calling on_test on test completions.
+
+        :param on_test: A callback that accepts one parameter - a dict
+            describing a test.
+        """
+        super(StreamToDict, self).__init__()
+        self.on_test = on_test
+        if parse_mime_type is None:
+            raise ImportError("mimeparse module missing.")
+
+    def startTestRun(self):
+        super(StreamToDict, self).startTestRun()
+        self._inprogress = {}
+
+    def status(self, test_id=None, test_status=None, test_tags=None,
+        runnable=True, file_name=None, file_bytes=None, eof=False,
+        mime_type=None, route_code=None, timestamp=None):
+        super(StreamToDict, self).status(test_id, test_status,
+            test_tags=test_tags, runnable=runnable, file_name=file_name,
+            file_bytes=file_bytes, eof=eof, mime_type=mime_type,
+            route_code=route_code, timestamp=timestamp)
+        key = self._ensure_key(test_id, route_code, timestamp)
+        # update fields
+        if not key:
+            return
+        if test_status is not None:
+            self._inprogress[key]['status'] = test_status
+        self._inprogress[key]['timestamps'][1] = timestamp
+        case = self._inprogress[key]
+        if file_name is not None:
+            if file_name not in case['details']:
+                if mime_type is None:
+                    mime_type = 'application/octet-stream'
+                primary, sub, parameters = parse_mime_type(mime_type)
+                if 'charset' in parameters:
+                    if ',' in parameters['charset']:
+                        # testtools was emitting a bad encoding, workaround it,
+                        # Though this does lose data - probably want to drop
+                        # this in a few releases.
+                        parameters['charset'] = parameters['charset'][
+                            :parameters['charset'].find(',')]
+                content_type = ContentType(primary, sub, parameters)
+                content_bytes = []
+                case['details'][file_name] = Content(
+                    content_type, lambda:content_bytes)
+            case['details'][file_name].iter_bytes().append(file_bytes)
+        if test_tags is not None:
+            self._inprogress[key]['tags'] = test_tags
+        # notify completed tests.
+        if test_status not in (None, 'inprogress'):
+            self.on_test(self._inprogress.pop(key))
+
+    def stopTestRun(self):
+        super(StreamToDict, self).stopTestRun()
+        while self._inprogress:
+            case = self._inprogress.popitem()[1]
+            case['timestamps'][1] = None
+            self.on_test(case)
+
+    def _ensure_key(self, test_id, route_code, timestamp):
+        if test_id is None:
+            return
+        key = (test_id, route_code)
+        if key not in self._inprogress:
+            self._inprogress[key] = {
+                'id': test_id,
+                'tags': set(),
+                'details': {},
+                'status': 'unknown',
+                'timestamps': [timestamp, None]}
+        return key
+
+
+_status_map = {
+    'inprogress': 'addFailure',
+    'unknown': 'addFailure',
+    'success': 'addSuccess',
+    'skip': 'addSkip',
+    'fail': 'addFailure',
+    'xfail': 'addExpectedFailure',
+    'uxsuccess': 'addUnexpectedSuccess',
+    }
+
+
+def test_dict_to_case(test_dict):
+    """Convert a test dict into a TestCase object.
+
+    :param test_dict: A test dict as generated by StreamToDict.
+    :return: A PlaceHolder test object.
+    """
+    # Circular import.
+    global PlaceHolder
+    if PlaceHolder is None:
+        from testtools.testcase import PlaceHolder
+    outcome = _status_map[test_dict['status']]
+    return PlaceHolder(test_dict['id'], outcome=outcome,
+        details=test_dict['details'], tags=test_dict['tags'],
+        timestamps=test_dict['timestamps'])
+
+
+class StreamSummary(StreamToDict):
+    """A specialised StreamResult that summarises a stream.
+
+    The summary uses the same representation as the original
+    unittest.TestResult contract, allowing it to be consumed by any test
+    runner.
+    """
+
+    def __init__(self):
+        super(StreamSummary, self).__init__(self._gather_test)
+        self._handle_status = {
+            'success': self._success,
+            'skip': self._skip,
+            'exists': self._exists,
+            'fail': self._fail,
+            'xfail': self._xfail,
+            'uxsuccess': self._uxsuccess,
+            'unknown': self._incomplete,
+            'inprogress': self._incomplete,
+            }
+
+    def startTestRun(self):
+        super(StreamSummary, self).startTestRun()
+        self.failures = []
+        self.errors = []
+        self.testsRun = 0
+        self.skipped = []
+        self.expectedFailures = []
+        self.unexpectedSuccesses = []
+
+    def wasSuccessful(self):
+        """Return False if any failure has occured.
+
+        Note that incomplete tests can only be detected when stopTestRun is
+        called, so that should be called before checking wasSuccessful.
+        """
+        return (not self.failures and not self.errors)
+
+    def _gather_test(self, test_dict):
+        if test_dict['status'] == 'exists':
+            return
+        self.testsRun += 1
+        case = test_dict_to_case(test_dict)
+        self._handle_status[test_dict['status']](case)
+
+    def _incomplete(self, case):
+        self.errors.append((case, "Test did not complete"))
+
+    def _success(self, case):
+        pass
+
+    def _skip(self, case):
+        if 'reason' not in case._details:
+            reason = "Unknown"
+        else:
+            reason = case._details['reason'].as_text()
+        self.skipped.append((case, reason))
+
+    def _exists(self, case):
+        pass
+
+    def _fail(self, case):
+        message = _details_to_str(case._details, special="traceback")
+        self.errors.append((case, message))
+
+    def _xfail(self, case):
+        message = _details_to_str(case._details, special="traceback")
+        self.expectedFailures.append((case, message))
+
+    def _uxsuccess(self, case):
+        case._outcome = 'addUnexpectedSuccess'
+        self.unexpectedSuccesses.append(case)
+
+
+class TestControl(object):
+    """Controls a running test run, allowing it to be interrupted.
+
+    :ivar shouldStop: If True, tests should not run and should instead
+        return immediately. Similarly a TestSuite should check this between
+        each test and if set stop dispatching any new tests and return.
+    """
+
+    def __init__(self):
+        super(TestControl, self).__init__()
+        self.shouldStop = False
+
+    def stop(self):
+        """Indicate that tests should stop running."""
+        self.shouldStop = True
+
+
 class MultiTestResult(TestResult):
     """A test result that dispatches to many test results."""
 
@@ -737,6 +1281,241 @@ class ExtendedToOriginalDecorator(object):
         return self.decorated.wasSuccessful()
 
 
+class ExtendedToStreamDecorator(CopyStreamResult, StreamSummary, TestControl):
+    """Permit using old TestResult API code with new StreamResult objects.
+
+    This decorates a StreamResult and converts old (Python 2.6 / 2.7 /
+    Extended) TestResult API calls into StreamResult calls.
+
+    It also supports regular StreamResult calls, making it safe to wrap around
+    any StreamResult.
+    """
+
+    def __init__(self, decorated):
+        super(ExtendedToStreamDecorator, self).__init__([decorated])
+        # Deal with mismatched base class constructors.
+        TestControl.__init__(self)
+        self._started = False
+
+    def _get_failfast(self):
+        return len(self.targets) == 2
+    def _set_failfast(self, value):
+        if value:
+            if len(self.targets) == 2:
+                return
+            self.targets.append(StreamFailFast(self.stop))
+        else:
+            del self.targets[1:]
+    failfast = property(_get_failfast, _set_failfast)
+
+    def startTest(self, test):
+        if not self._started:
+            self.startTestRun()
+        self.status(test_id=test.id(), test_status='inprogress', timestamp=self._now())
+        self._tags = TagContext(self._tags)
+
+    def stopTest(self, test):
+        self._tags = self._tags.parent
+
+    def addError(self, test, err=None, details=None):
+        self._check_args(err, details)
+        self._convert(test, err, details, 'fail')
+    addFailure = addError
+
+    def _convert(self, test, err, details, status, reason=None):
+        if not self._started:
+            self.startTestRun()
+        test_id = test.id()
+        now = self._now()
+        if err is not None:
+            if details is None:
+                details = {}
+            details['traceback'] = TracebackContent(err, test)
+        if details is not None:
+            for name, content in details.items():
+                mime_type = repr(content.content_type)
+                file_bytes = None
+                for next_bytes in content.iter_bytes():
+                    if file_bytes is not None:
+                        self.status(file_name=name, file_bytes=file_bytes,
+                            mime_type=mime_type, test_id=test_id, timestamp=now)
+                    file_bytes = next_bytes
+                self.status(file_name=name, file_bytes=file_bytes, eof=True,
+                    mime_type=mime_type, test_id=test_id, timestamp=now)
+        if reason is not None:
+            self.status(file_name='reason', file_bytes=reason.encode('utf8'),
+                eof=True, mime_type="text/plain; charset=utf8",
+                test_id=test_id, timestamp=now)
+        self.status(test_id=test_id, test_status=status,
+            test_tags=self.current_tags, timestamp=now)
+
+    def addExpectedFailure(self, test, err=None, details=None):
+        self._check_args(err, details)
+        self._convert(test, err, details, 'xfail')
+
+    def addSkip(self, test, reason=None, details=None):
+        self._convert(test, None, details, 'skip', reason)
+
+    def addUnexpectedSuccess(self, test, details=None):
+        self._convert(test, None, details, 'uxsuccess')
+
+    def addSuccess(self, test, details=None):
+        self._convert(test, None, details, 'success')
+
+    def _check_args(self, err, details):
+        param_count = 0
+        if err is not None:
+            param_count += 1
+        if details is not None:
+            param_count += 1
+        if param_count != 1:
+            raise ValueError("Must pass only one of err '%s' and details '%s"
+                % (err, details))
+
+    def startTestRun(self):
+        super(ExtendedToStreamDecorator, self).startTestRun()
+        self._tags = TagContext()
+        self.shouldStop = False
+        self.__now = None
+        self._started = True
+
+    def stopTest(self, test):
+        self._tags = self._tags.parent
+
+    @property
+    def current_tags(self):
+        """The currently set tags."""
+        return self._tags.get_current_tags()
+
+    def tags(self, new_tags, gone_tags):
+        """Add and remove tags from the test.
+
+        :param new_tags: A set of tags to be added to the stream.
+        :param gone_tags: A set of tags to be removed from the stream.
+        """
+        self._tags.change_tags(new_tags, gone_tags)
+
+    def _now(self):
+        """Return the current 'test time'.
+
+        If the time() method has not been called, this is equivalent to
+        datetime.now(), otherwise its the last supplied datestamp given to the
+        time() method.
+        """
+        if self.__now is None:
+            return datetime.datetime.now(utc)
+        else:
+            return self.__now
+
+    def time(self, a_datetime):
+        self.__now = a_datetime
+
+    def wasSuccessful(self):
+        if not self._started:
+            self.startTestRun()
+        return super(ExtendedToStreamDecorator, self).wasSuccessful()
+
+
+class StreamToExtendedDecorator(StreamResult):
+    """Convert StreamResult API calls into ExtendedTestResult calls.
+
+    This will buffer all calls for all concurrently active tests, and
+    then flush each test as they complete.
+
+    Incomplete tests will be flushed as errors when the test run stops.
+
+    Non test file attachments are accumulated into a test called
+    'testtools.extradata' flushed at the end of the run.
+    """
+
+    def __init__(self, decorated):
+        # ExtendedToOriginalDecorator takes care of thunking details back to
+        # exceptions/reasons etc.
+        self.decorated = ExtendedToOriginalDecorator(decorated)
+        # StreamToDict buffers and gives us individual tests.
+        self.hook = StreamToDict(self._handle_tests)
+
+    def status(self, test_id=None, test_status=None, *args, **kwargs):
+        if test_status == 'exists':
+            return
+        self.hook.status(
+            test_id=test_id, test_status=test_status, *args, **kwargs)
+
+    def startTestRun(self):
+        self.decorated.startTestRun()
+        self.hook.startTestRun()
+
+    def stopTestRun(self):
+        self.hook.stopTestRun()
+        self.decorated.stopTestRun()
+
+    def _handle_tests(self, test_dict):
+        case = test_dict_to_case(test_dict)
+        case.run(self.decorated)
+
+
+class StreamToQueue(StreamResult):
+    """A StreamResult which enqueues events as a dict to a queue.Queue.
+
+    Events have their route code updated to include the route code
+    StreamToQueue was constructed with before they are submitted. If the event
+    route code is None, it is replaced with the StreamToQueue route code,
+    otherwise it is prefixed with the supplied code + a hyphen.
+
+    startTestRun and stopTestRun are forwarded to the queue. Implementors that
+    dequeue events back into StreamResult calls should take care not to call
+    startTestRun / stopTestRun on other StreamResult objects multiple times
+    (e.g. by filtering startTestRun and stopTestRun).
+
+    ``StreamToQueue`` is typically used by
+    ``ConcurrentStreamTestSuite``, which creates one ``StreamToQueue``
+    per thread, forwards status events to the the StreamResult that
+    ``ConcurrentStreamTestSuite.run()`` was called with, and uses the
+    stopTestRun event to trigger calling join() on the each thread.
+
+    Unlike ThreadsafeForwardingResult which this supercedes, no buffering takes
+    place - any event supplied to a StreamToQueue will be inserted into the
+    queue immediately.
+
+    Events are forwarded as a dict with a key ``event`` which is one of
+    ``startTestRun``, ``stopTestRun`` or ``status``. When ``event`` is
+    ``status`` the dict also has keys matching the keyword arguments
+    of ``StreamResult.status``, otherwise it has one other key ``result`` which
+    is the result that invoked ``startTestRun``.
+    """
+
+    def __init__(self, queue, routing_code):
+        """Create a StreamToQueue forwarding to target.
+
+        :param queue: A ``queue.Queue`` to receive events.
+        :param routing_code: The routing code to apply to messages.
+        """
+        super(StreamToQueue, self).__init__()
+        self.queue = queue
+        self.routing_code = routing_code
+
+    def startTestRun(self):
+        self.queue.put(dict(event='startTestRun', result=self))
+
+    def status(self, test_id=None, test_status=None, test_tags=None,
+        runnable=True, file_name=None, file_bytes=None, eof=False,
+        mime_type=None, route_code=None, timestamp=None):
+        self.queue.put(dict(event='status', test_id=test_id,
+            test_status=test_status, test_tags=test_tags, runnable=runnable,
+            file_name=file_name, file_bytes=file_bytes, eof=eof,
+            mime_type=mime_type, route_code=self.route_code(route_code),
+            timestamp=timestamp))
+
+    def stopTestRun(self):
+        self.queue.put(dict(event='stopTestRun', result=self))
+
+    def route_code(self, route_code):
+        """Adjust route_code on the way through."""
+        if route_code is None:
+            return self.routing_code
+        return self.routing_code + _u("/") + route_code
+
+
 class TestResultDecorator(object):
     """General pass-through decorator.
 
@@ -901,6 +1680,23 @@ class TestByTestResult(TestResult):
         self._details = details
 
 
+class TimestampingStreamResult(CopyStreamResult):
+    """A StreamResult decorator that assigns a timestamp when none is present.
+
+    This is convenient for ensuring events are timestamped.
+    """
+
+    def __init__(self, target):
+        super(TimestampingStreamResult, self).__init__([target])
+
+    def status(self, *args, **kwargs):
+        timestamp = kwargs.pop('timestamp', None)
+        if timestamp is None:
+            timestamp = datetime.datetime.now(utc)
+        super(TimestampingStreamResult, self).status(
+            *args, timestamp=timestamp, **kwargs)
+
+
 class _StringException(Exception):
     """An exception made from an arbitrary string."""
 
diff --git a/lib/testtools/testtools/tests/__init__.py b/lib/testtools/testtools/tests/__init__.py
index df9d44b..5e18e07 100644
--- a/lib/testtools/testtools/tests/__init__.py
+++ b/lib/testtools/testtools/tests/__init__.py
@@ -1,6 +1,7 @@
+# Copyright (c) 2008-2013 testtools developers. See LICENSE for details.
+
 """Tests for testtools itself."""
 
-# See README for copyright and licensing details.
 
 from unittest import TestSuite
 
@@ -8,6 +9,7 @@ from unittest import TestSuite
 def test_suite():
     from testtools.tests import (
         matchers,
+        test_assert_that,
         test_compat,
         test_content,
         test_content_type,
@@ -23,9 +25,11 @@ def test_suite():
         test_testcase,
         test_testresult,
         test_testsuite,
+        test_with_with,
         )
     modules = [
         matchers,
+        test_assert_that,
         test_compat,
         test_content,
         test_content_type,
@@ -41,6 +45,7 @@ def test_suite():
         test_testcase,
         test_testresult,
         test_testsuite,
+        test_with_with,
         ]
     suites = map(lambda x: x.test_suite(), modules)
     return TestSuite(suites)
diff --git a/lib/testtools/testtools/tests/helpers.py b/lib/testtools/testtools/tests/helpers.py
index ade2d96..f766da3 100644
--- a/lib/testtools/testtools/tests/helpers.py
+++ b/lib/testtools/testtools/tests/helpers.py
@@ -8,11 +8,10 @@ __all__ = [
 
 import sys
 
+from extras import safe_hasattr
+
 from testtools import TestResult
-from testtools.helpers import (
-    safe_hasattr,
-    )
-from testtools.content import TracebackContent
+from testtools.content import StackLinesContent
 from testtools import runtest
 
 
@@ -84,12 +83,12 @@ class LoggingResult(TestResult):
 
 
 def is_stack_hidden():
-    return TracebackContent.HIDE_INTERNAL_STACK
+    return StackLinesContent.HIDE_INTERNAL_STACK
 
 
 def hide_testtools_stack(should_hide=True):
-    result = TracebackContent.HIDE_INTERNAL_STACK
-    TracebackContent.HIDE_INTERNAL_STACK = should_hide
+    result = StackLinesContent.HIDE_INTERNAL_STACK
+    StackLinesContent.HIDE_INTERNAL_STACK = should_hide
     return result
 
 
diff --git a/lib/testtools/testtools/tests/matchers/test_basic.py b/lib/testtools/testtools/tests/matchers/test_basic.py
index 1109fa4..c53bc9e 100644
--- a/lib/testtools/testtools/tests/matchers/test_basic.py
+++ b/lib/testtools/testtools/tests/matchers/test_basic.py
@@ -19,6 +19,7 @@ from testtools.matchers._basic import (
     IsInstance,
     LessThan,
     GreaterThan,
+    HasLength,
     MatchesRegex,
     NotEquals,
     SameMembers,
@@ -35,8 +36,14 @@ class Test_BinaryMismatch(TestCase):
     _long_b = _b(_long_string)
     _long_u = _u(_long_string)
 
+    class CustomRepr(object):
+        def __init__(self, repr_string):
+            self._repr_string = repr_string
+        def __repr__(self):
+            return _u('<object ') + _u(self._repr_string) + _u('>')
+
     def test_short_objects(self):
-        o1, o2 = object(), object()
+        o1, o2 = self.CustomRepr('a'), self.CustomRepr('b')
         mismatch = _BinaryMismatch(o1, "!~", o2)
         self.assertEqual(mismatch.describe(), "%r !~ %r" % (o1, o2))
 
@@ -369,6 +376,21 @@ class TestMatchesRegex(TestCase, TestMatchersInterface):
         ]
 
 
+class TestHasLength(TestCase, TestMatchersInterface):
+
+    matches_matcher = HasLength(2)
+    matches_matches = [[1, 2]]
+    matches_mismatches = [[], [1], [3, 2, 1]]
+
+    str_examples = [
+        ("HasLength(2)", HasLength(2)),
+        ]
+
+    describe_examples = [
+        ("len([]) != 1", [], HasLength(1)),
+        ]
+
+
 def test_suite():
     from unittest import TestLoader
     return TestLoader().loadTestsFromName(__name__)
diff --git a/lib/testtools/testtools/tests/matchers/test_dict.py b/lib/testtools/testtools/tests/matchers/test_dict.py
index c6e2c9c..00368dd 100644
--- a/lib/testtools/testtools/tests/matchers/test_dict.py
+++ b/lib/testtools/testtools/tests/matchers/test_dict.py
@@ -30,7 +30,7 @@ class TestMatchesAllDictInterface(TestCase, TestMatchersInterface):
         ]
 
 
-class TestKeysEqual(TestCase, TestMatchersInterface):
+class TestKeysEqualWithList(TestCase, TestMatchersInterface):
 
     matches_matcher = KeysEqual('foo', 'bar')
     matches_matches = [
@@ -60,6 +60,11 @@ class TestKeysEqual(TestCase, TestMatchersInterface):
                 % (matchee,)))
 
 
+class TestKeysEqualWithDict(TestKeysEqualWithList):
+
+    matches_matcher = KeysEqual({'foo': 3, 'bar': 4})
+
+
 class TestSubDictOf(TestCase, TestMatchersInterface):
 
     matches_matcher = _SubDictOf({'foo': 'bar', 'baz': 'qux'})
diff --git a/lib/testtools/testtools/tests/matchers/test_exception.py b/lib/testtools/testtools/tests/matchers/test_exception.py
index ef7185f..a74043a 100644
--- a/lib/testtools/testtools/tests/matchers/test_exception.py
+++ b/lib/testtools/testtools/tests/matchers/test_exception.py
@@ -163,12 +163,7 @@ class TestRaisesBaseTypes(TestCase):
         # Exception, it is propogated.
         match_keyb = Raises(MatchesException(KeyboardInterrupt))
         def raise_keyb_from_match():
-            if sys.version_info > (2, 5):
-                matcher = Raises(MatchesException(Exception))
-            else:
-                # On Python 2.4 KeyboardInterrupt is a StandardError subclass
-                # but should propogate from less generic exception matchers
-                matcher = Raises(MatchesException(EnvironmentError))
+            matcher = Raises(MatchesException(Exception))
             matcher.match(self.raiser)
         self.assertThat(raise_keyb_from_match, match_keyb)
 
diff --git a/lib/testtools/testtools/tests/matchers/test_higherorder.py b/lib/testtools/testtools/tests/matchers/test_higherorder.py
index c5cc44e..fb86b7f 100644
--- a/lib/testtools/testtools/tests/matchers/test_higherorder.py
+++ b/lib/testtools/testtools/tests/matchers/test_higherorder.py
@@ -18,6 +18,7 @@ from testtools.matchers._higherorder import (
     MatchesAny,
     MatchesAll,
     MatchesPredicate,
+    MatchesPredicateWithParams,
     Not,
     )
 from testtools.tests.helpers import FullStackRunTest
@@ -222,6 +223,32 @@ class TestMatchesPredicate(TestCase, TestMatchersInterface):
         ]
 
 
+def between(x, low, high):
+    return low < x < high
+
+
+class TestMatchesPredicateWithParams(TestCase, TestMatchersInterface):
+
+    matches_matcher = MatchesPredicateWithParams(
+        between, "{0} is not between {1} and {2}")(1, 9)
+    matches_matches = [2, 4, 6, 8]
+    matches_mismatches = [0, 1, 9, 10]
+
+    str_examples = [
+        ("MatchesPredicateWithParams(%r, %r)(%s)" % (
+            between, "{0} is not between {1} and {2}", "1, 2"),
+         MatchesPredicateWithParams(
+            between, "{0} is not between {1} and {2}")(1, 2)),
+        ("Between(1, 2)", MatchesPredicateWithParams(
+            between, "{0} is not between {1} and {2}", "Between")(1, 2)),
+        ]
+
+    describe_examples = [
+        ('1 is not between 2 and 3', 1, MatchesPredicateWithParams(
+            between, "{0} is not between {1} and {2}")(2, 3)),
+        ]
+
+
 def test_suite():
     from unittest import TestLoader
     return TestLoader().loadTestsFromName(__name__)
diff --git a/lib/testtools/testtools/tests/test_compat.py b/lib/testtools/testtools/tests/test_compat.py
index b29dc34..84e57be 100644
--- a/lib/testtools/testtools/tests/test_compat.py
+++ b/lib/testtools/testtools/tests/test_compat.py
@@ -2,6 +2,7 @@
 
 """Tests for miscellaneous compatibility functions"""
 
+import io
 import linecache
 import os
 import sys
@@ -13,6 +14,9 @@ import testtools
 from testtools.compat import (
     _b,
     _detect_encoding,
+    _format_exc_info,
+    _format_exception_only,
+    _format_stack_list,
     _get_source_encoding,
     _u,
     reraise,
@@ -21,6 +25,9 @@ from testtools.compat import (
     unicode_output_stream,
     )
 from testtools.matchers import (
+    Equals,
+    Is,
+    IsInstance,
     MatchesException,
     Not,
     Raises,
@@ -106,7 +113,8 @@ class TestDetectEncoding(testtools.TestCase):
             '\xef\xbb\xbfThose should be latin-1 bytes"""\n'))
         self._check_encoding("utf-8", (
             "\xef\xbb\xbf# Is the coding: utf-8 or coding: euc-jp instead?\n",
-            '"""Module docstring say \xe2\x98\x86"""\n'))
+            '"""Module docstring say \xe2\x98\x86"""\n'),
+            possibly_invalid=True)
 
     def test_multiple_coding_comments(self):
         """Test only the first of multiple coding declarations counts"""
@@ -256,12 +264,30 @@ class TestUnicodeOutputStream(testtools.TestCase):
             newio = True
         sout = StringIO()
         soutwrapper = unicode_output_stream(sout)
-        if newio:
-            self.expectFailure("Python 3 StringIO expects text not bytes",
-                self.assertThat, lambda: soutwrapper.write(self.uni),
-                Not(Raises(MatchesException(TypeError))))
         soutwrapper.write(self.uni)
-        self.assertEqual("pa???n", sout.getvalue())
+        if newio:
+            self.assertEqual(self.uni, sout.getvalue())
+        else:
+            self.assertEqual("pa???n", sout.getvalue())
+
+    def test_io_stringio(self):
+        # io.StringIO only accepts unicode so should be returned as itself.
+        s = io.StringIO()
+        self.assertEqual(s, unicode_output_stream(s))
+
+    def test_io_bytesio(self):
+        # io.BytesIO only accepts bytes so should be wrapped.
+        bytes_io = io.BytesIO()
+        self.assertThat(bytes_io, Not(Is(unicode_output_stream(bytes_io))))
+        # Will error if s was not wrapped properly.
+        unicode_output_stream(bytes_io).write(_u('foo'))
+
+    def test_io_textwrapper(self):
+        # textwrapper is unicode, should be returned as itself.
+        text_io = io.TextIOWrapper(io.BytesIO())
+        self.assertThat(unicode_output_stream(text_io), Is(text_io))
+        # To be sure...
+        unicode_output_stream(text_io).write(_u('foo'))
 
 
 class TestTextRepr(testtools.TestCase):
@@ -427,6 +453,151 @@ class TestReraise(testtools.TestCase):
         self.assertRaises(CustomException, reraise, *_exc_info)
 
 
+class Python2CompatibilityTests(testtools.TestCase):
+
+    def setUp(self):
+        super(Python2CompatibilityTests, self).setUp()
+        if sys.version[0] >= '3':
+            self.skip("These tests are only applicable to python 2.")
+
+
+class TestExceptionFormatting(Python2CompatibilityTests):
+    """Test the _format_exception_only function."""
+
+    def _assert_exception_format(self, eclass, evalue, expected):
+        actual = _format_exception_only(eclass, evalue)
+        self.assertThat(actual, Equals(expected))
+        self.assertThat(''.join(actual), IsInstance(unicode))
+
+    def test_supports_string_exception(self):
+        self._assert_exception_format(
+            "String_Exception",
+            None,
+            [_u("String_Exception\n")]
+        )
+
+    def test_supports_regular_exception(self):
+        self._assert_exception_format(
+            RuntimeError,
+            RuntimeError("Something went wrong"),
+            [_u("RuntimeError: Something went wrong\n")]
+        )
+
+    def test_supports_unprintable_exceptions(self):
+        """Verify support for exception classes that raise an exception when
+        __unicode__ or __str__ is called.
+        """
+        class UnprintableException(Exception):
+
+            def __str__(self):
+                raise Exception()
+
+            def __unicode__(self):
+                raise Exception()
+
+        self._assert_exception_format(
+            UnprintableException,
+            UnprintableException("Foo"),
+            [_u("UnprintableException: <unprintable UnprintableException object>\n")]
+        )
+
+    def test_supports_exceptions_with_no_string_value(self):
+        class NoStringException(Exception):
+
+            def __str__(self):
+                return ""
+
+            def __unicode__(self):
+                return _u("")
+
+        self._assert_exception_format(
+            NoStringException,
+            NoStringException("Foo"),
+            [_u("NoStringException\n")]
+        )
+
+    def test_supports_strange_syntax_error(self):
+        """Test support for syntax errors with unusual number of arguments"""
+        self._assert_exception_format(
+            SyntaxError,
+            SyntaxError("Message"),
+            [_u("SyntaxError: Message\n")]
+        )
+
+    def test_supports_syntax_error(self):
+        self._assert_exception_format(
+            SyntaxError,
+            SyntaxError(
+                "Some Syntax Message",
+                (
+                    "/path/to/file",
+                    12,
+                    2,
+                    "This is the line of code",
+                )
+            ),
+            [
+                _u('  File "/path/to/file", line 12\n'),
+                _u('    This is the line of code\n'),
+                _u('     ^\n'),
+                _u('SyntaxError: Some Syntax Message\n'),
+            ]
+        )
+
+
+class StackListFormattingTests(Python2CompatibilityTests):
+    """Test the _format_stack_list function."""
+
+    def _assert_stack_format(self, stack_lines, expected_output):
+        actual = _format_stack_list(stack_lines)
+        self.assertThat(actual, Equals([expected_output]))
+
+    def test_single_complete_stack_line(self):
+        stack_lines = [(
+            '/path/to/filename',
+            12,
+            'func_name',
+            'some_code()',
+        )]
+        expected = \
+            _u('  File "/path/to/filename", line 12, in func_name\n' \
+               '    some_code()\n')
+
+        self._assert_stack_format(stack_lines, expected)
+
+    def test_single_stack_line_no_code(self):
+        stack_lines = [(
+            '/path/to/filename',
+            12,
+            'func_name',
+            None
+        )]
+        expected = _u('  File "/path/to/filename", line 12, in func_name\n')
+        self._assert_stack_format(stack_lines, expected)
+
+
+class FormatExceptionInfoTests(Python2CompatibilityTests):
+
+    def test_individual_functions_called(self):
+        self.patch(
+            testtools.compat,
+            '_format_stack_list',
+            lambda stack_list: [_u("format stack list called\n")]
+        )
+        self.patch(
+            testtools.compat,
+            '_format_exception_only',
+            lambda etype, evalue: [_u("format exception only called\n")]
+        )
+        result = _format_exc_info(None, None, None)
+        expected = [
+            _u("Traceback (most recent call last):\n"),
+            _u("format stack list called\n"),
+            _u("format exception only called\n"),
+        ]
+        self.assertThat(expected, Equals(result))
+
+
 def test_suite():
     from unittest import TestLoader
     return TestLoader().loadTestsFromName(__name__)
diff --git a/lib/testtools/testtools/tests/test_content.py b/lib/testtools/testtools/tests/test_content.py
index bc72513..09feebd 100644
--- a/lib/testtools/testtools/tests/test_content.py
+++ b/lib/testtools/testtools/tests/test_content.py
@@ -5,12 +5,13 @@ import os
 import tempfile
 import unittest
 
-from testtools import TestCase
+from testtools import TestCase, skipUnless
 from testtools.compat import (
     _b,
     _u,
     BytesIO,
     StringIO,
+    str_is_unicode,
     )
 from testtools.content import (
     attach_file,
@@ -19,6 +20,8 @@ from testtools.content import (
     content_from_stream,
     JSON,
     json_content,
+    StackLinesContent,
+    StacktraceContent,
     TracebackContent,
     text_content,
     )
@@ -188,12 +191,71 @@ class TestContent(TestCase):
         expected = Content(UTF8_TEXT, lambda: [data.encode('utf8')])
         self.assertEqual(expected, text_content(data))
 
+    @skipUnless(str_is_unicode, "Test only applies in python 3.")
+    def test_text_content_raises_TypeError_when_passed_bytes(self):
+        data = _b("Some Bytes")
+        self.assertRaises(TypeError, text_content, data)
+
+    def test_text_content_raises_TypeError_when_passed_non_text(self):
+        bad_values = (None, list(), dict(), 42, 1.23)
+        for value in bad_values:
+            self.assertThat(
+                lambda: text_content(value),
+                raises(
+                    TypeError("text_content must be given text, not '%s'." %
+                        type(value).__name__)
+                ),
+            )
+
     def test_json_content(self):
         data = {'foo': 'bar'}
         expected = Content(JSON, lambda: [_b('{"foo": "bar"}')])
         self.assertEqual(expected, json_content(data))
 
 
+class TestStackLinesContent(TestCase):
+
+    def _get_stack_line_and_expected_output(self):
+        stack_lines = [
+            ('/path/to/file', 42, 'some_function', 'print("Hello World")'),
+        ]
+        expected = '  File "/path/to/file", line 42, in some_function\n' \
+                   '    print("Hello World")\n'
+        return stack_lines, expected
+
+    def test_single_stack_line(self):
+        stack_lines, expected = self._get_stack_line_and_expected_output()
+        actual = StackLinesContent(stack_lines).as_text()
+
+        self.assertEqual(expected, actual)
+
+    def test_prefix_content(self):
+        stack_lines, expected = self._get_stack_line_and_expected_output()
+        prefix = self.getUniqueString() + '\n'
+        content = StackLinesContent(stack_lines, prefix_content=prefix)
+        actual = content.as_text()
+        expected = prefix  + expected
+
+        self.assertEqual(expected, actual)
+
+    def test_postfix_content(self):
+        stack_lines, expected = self._get_stack_line_and_expected_output()
+        postfix = '\n' + self.getUniqueString()
+        content = StackLinesContent(stack_lines, postfix_content=postfix)
+        actual = content.as_text()
+        expected = expected + postfix
+
+        self.assertEqual(expected, actual)
+
+    def test___init___sets_content_type(self):
+        stack_lines, expected = self._get_stack_line_and_expected_output()
+        content = StackLinesContent(stack_lines)
+        expected_content_type = ContentType("text", "x-traceback",
+            {"language": "python", "charset": "utf8"})
+
+        self.assertEqual(expected_content_type, content.content_type)
+
+
 class TestTracebackContent(TestCase):
 
     def test___init___None_errors(self):
@@ -210,6 +272,33 @@ class TestTracebackContent(TestCase):
         self.assertEqual(expected, ''.join(list(content.iter_text())))
 
 
+class TestStacktraceContent(TestCase):
+
+    def test___init___sets_ivars(self):
+        content = StacktraceContent()
+        content_type = ContentType("text", "x-traceback",
+            {"language": "python", "charset": "utf8"})
+
+        self.assertEqual(content_type, content.content_type)
+
+    def test_prefix_is_used(self):
+        prefix = self.getUniqueString()
+        actual = StacktraceContent(prefix_content=prefix).as_text()
+
+        self.assertTrue(actual.startswith(prefix))
+
+    def test_postfix_is_used(self):
+        postfix = self.getUniqueString()
+        actual = StacktraceContent(postfix_content=postfix).as_text()
+
+        self.assertTrue(actual.endswith(postfix))
+
+    def test_top_frame_is_skipped_when_no_stack_is_specified(self):
+        actual = StacktraceContent().as_text()
+
+        self.assertTrue('testtools/content.py' not in actual)
+
+
 class TestAttachFile(TestCase):
 
     def make_file(self, data):
diff --git a/lib/testtools/testtools/tests/test_content_type.py b/lib/testtools/testtools/tests/test_content_type.py
index ecb8e3a..2d34f95 100644
--- a/lib/testtools/testtools/tests/test_content_type.py
+++ b/lib/testtools/testtools/tests/test_content_type.py
@@ -43,7 +43,7 @@ class TestContentType(TestCase):
         content_type = ContentType(
             'text', 'plain', {'foo': 'bar', 'baz': 'qux'})
         self.assertThat(
-            repr(content_type), Equals('text/plain; baz="qux", foo="bar"'))
+            repr(content_type), Equals('text/plain; baz="qux"; foo="bar"'))
 
 
 class TestBuiltinContentTypes(TestCase):
diff --git a/lib/testtools/testtools/tests/test_deferredruntest.py b/lib/testtools/testtools/tests/test_deferredruntest.py
index 3373c06..997f6c8 100644
--- a/lib/testtools/testtools/tests/test_deferredruntest.py
+++ b/lib/testtools/testtools/tests/test_deferredruntest.py
@@ -5,6 +5,8 @@
 import os
 import signal
 
+from extras import try_import
+
 from testtools import (
     skipIf,
     TestCase,
@@ -13,7 +15,6 @@ from testtools import (
 from testtools.content import (
     text_content,
     )
-from testtools.helpers import try_import
 from testtools.matchers import (
     Equals,
     KeysEqual,
@@ -52,6 +53,12 @@ class X(object):
             self.calls.append('tearDown')
             super(X.Base, self).tearDown()
 
+    class BaseExceptionRaised(Base):
+        expected_calls = ['setUp', 'tearDown', 'clean-up']
+        expected_results = [('addError', SystemExit)]
+        def test_something(self):
+            raise SystemExit(0)
+
     class ErrorInSetup(Base):
         expected_calls = ['setUp', 'clean-up']
         expected_results = [('addError', RuntimeError)]
@@ -102,7 +109,10 @@ class X(object):
         def test_runner(self):
             result = ExtendedTestResult()
             test = self.test_factory('test_something', runTest=self.runner)
-            test.run(result)
+            if self.test_factory is X.BaseExceptionRaised:
+                self.assertRaises(SystemExit, test.run, result)
+            else:
+                test.run(result)
             self.assertEqual(test.calls, self.test_factory.expected_calls)
             self.assertResultsMatch(test, result)
 
@@ -117,6 +127,7 @@ def make_integration_tests():
         ]
 
     tests = [
+        X.BaseExceptionRaised,
         X.ErrorInSetup,
         X.ErrorInTest,
         X.ErrorInTearDown,
@@ -545,7 +556,7 @@ class TestAsynchronousDeferredRunTest(NeedsTwistedTestCase):
                 self.addCleanup(lambda: 3 / 0)
                 # Dirty the reactor.
                 from twisted.internet.protocol import ServerFactory
-                reactor.listenTCP(0, ServerFactory())
+                reactor.listenTCP(0, ServerFactory(), interface='127.0.0.1')
                 # Unhandled error.
                 defer.maybeDeferred(lambda: 2 / 0)
                 # Actual error.
@@ -760,7 +771,10 @@ class TestRunWithLogObservers(NeedsTwistedTestCase):
 
 
 def test_suite():
-    from unittest import TestLoader, TestSuite
-    return TestSuite(
-        [TestLoader().loadTestsFromName(__name__),
-         make_integration_tests()])
+    from unittest2 import TestLoader, TestSuite
+    return TestLoader().loadTestsFromName(__name__)
+
+
+def load_tests(loader, tests, pattern):
+    tests.addTest(make_integration_tests())
+    return tests
diff --git a/lib/testtools/testtools/tests/test_distutilscmd.py b/lib/testtools/testtools/tests/test_distutilscmd.py
index 59762df..fd0dd90 100644
--- a/lib/testtools/testtools/tests/test_distutilscmd.py
+++ b/lib/testtools/testtools/tests/test_distutilscmd.py
@@ -4,12 +4,13 @@
 
 from distutils.dist import Distribution
 
+from extras import try_import
+
 from testtools.compat import (
     _b,
     _u,
     BytesIO,
     )
-from testtools.helpers import try_import
 fixtures = try_import('fixtures')
 
 import testtools
@@ -60,8 +61,8 @@ class TestCommandTest(TestCase):
         dist.cmdclass = {'test': TestCommand}
         dist.command_options = {
             'test': {'test_module': ('command line', 'testtools.runexample')}}
-        cmd = dist.reinitialize_command('test')
         with fixtures.MonkeyPatch('sys.stdout', stdout.stream):
+            cmd = dist.reinitialize_command('test')
             dist.run_command('test')
         self.assertThat(
             stdout.getDetails()['stdout'].as_text(),
@@ -82,8 +83,8 @@ OK
             'test': {
                 'test_suite': (
                     'command line', 'testtools.runexample.test_suite')}}
-        cmd = dist.reinitialize_command('test')
         with fixtures.MonkeyPatch('sys.stdout', stdout.stream):
+            cmd = dist.reinitialize_command('test')
             dist.run_command('test')
         self.assertThat(
             stdout.getDetails()['stdout'].as_text(),
diff --git a/lib/testtools/testtools/tests/test_fixturesupport.py b/lib/testtools/testtools/tests/test_fixturesupport.py
index cff9eb4..e309045 100644
--- a/lib/testtools/testtools/tests/test_fixturesupport.py
+++ b/lib/testtools/testtools/tests/test_fixturesupport.py
@@ -2,13 +2,15 @@
 
 import unittest
 
+from extras import try_import
+
 from testtools import (
     TestCase,
     content,
     content_type,
     )
 from testtools.compat import _b, _u
-from testtools.helpers import try_import
+from testtools.matchers import Contains
 from testtools.testresult.doubles import (
     ExtendedTestResult,
     )
@@ -111,6 +113,32 @@ class TestFixtureSupport(TestCase):
         self.assertEqual(['content', 'traceback'], sorted(details))
         self.assertEqual('foobar', ''.join(details['content'].iter_text()))
 
+    def test_useFixture_original_exception_raised_if_gather_details_fails(self):
+        # In bug #1368440 it was reported that when a fixture fails setUp
+        # and gather_details errors on it, then the original exception that
+        # failed is not reported.
+        class BrokenFixture(fixtures.Fixture):
+            def getDetails(self):
+                raise AttributeError("getDetails broke")
+            def setUp(self):
+                fixtures.Fixture.setUp(self)
+                raise Exception("setUp broke")
+        fixture = BrokenFixture()
+        class SimpleTest(TestCase):
+            def test_foo(self):
+                self.useFixture(fixture)
+        result = ExtendedTestResult()
+        SimpleTest('test_foo').run(result)
+        self.assertEqual('addError', result._events[-2][0])
+        details = result._events[-2][2]
+        self.assertEqual(['traceback', 'traceback-1'], sorted(details))
+        self.assertThat(
+            ''.join(details['traceback'].iter_text()),
+            Contains('setUp broke'))
+        self.assertThat(
+            ''.join(details['traceback-1'].iter_text()),
+            Contains('getDetails broke'))
+
 
 def test_suite():
     from unittest import TestLoader
diff --git a/lib/testtools/testtools/tests/test_helpers.py b/lib/testtools/testtools/tests/test_helpers.py
index 98da534..848c2f0 100644
--- a/lib/testtools/testtools/tests/test_helpers.py
+++ b/lib/testtools/testtools/tests/test_helpers.py
@@ -1,196 +1,13 @@
 # Copyright (c) 2010-2012 testtools developers. See LICENSE for details.
 
 from testtools import TestCase
-from testtools.helpers import (
-    try_import,
-    try_imports,
-    )
-from testtools.matchers import (
-    Equals,
-    Is,
-    Not,
-    )
 from testtools.tests.helpers import (
     FullStackRunTest,
     hide_testtools_stack,
     is_stack_hidden,
-    safe_hasattr,
     )
 
 
-def check_error_callback(test, function, arg, expected_error_count,
-    expect_result):
-    """General test template for error_callback argument.
-
-    :param test: Test case instance.
-    :param function: Either try_import or try_imports.
-    :param arg: Name or names to import.
-    :param expected_error_count: Expected number of calls to the callback.
-    :param expect_result: Boolean for whether a module should
-        ultimately be returned or not.
-    """
-    cb_calls = []
-    def cb(e):
-        test.assertIsInstance(e, ImportError)
-        cb_calls.append(e)
-    try:
-        result = function(arg, error_callback=cb)
-    except ImportError:
-        test.assertFalse(expect_result)
-    else:
-        if expect_result:
-            test.assertThat(result, Not(Is(None)))
-        else:
-            test.assertThat(result, Is(None))
-    test.assertEquals(len(cb_calls), expected_error_count)
-
-
-class TestSafeHasattr(TestCase):
-
-    def test_attribute_not_there(self):
-        class Foo(object):
-            pass
-        self.assertEqual(False, safe_hasattr(Foo(), 'anything'))
-
-    def test_attribute_there(self):
-        class Foo(object):
-            pass
-        foo = Foo()
-        foo.attribute = None
-        self.assertEqual(True, safe_hasattr(foo, 'attribute'))
-
-    def test_property_there(self):
-        class Foo(object):
-            @property
-            def attribute(self):
-                return None
-        foo = Foo()
-        self.assertEqual(True, safe_hasattr(foo, 'attribute'))
-
-    def test_property_raises(self):
-        class Foo(object):
-            @property
-            def attribute(self):
-                1/0
-        foo = Foo()
-        self.assertRaises(ZeroDivisionError, safe_hasattr, foo, 'attribute')
-
-
-class TestTryImport(TestCase):
-
-    def test_doesnt_exist(self):
-        # try_import('thing', foo) returns foo if 'thing' doesn't exist.
-        marker = object()
-        result = try_import('doesntexist', marker)
-        self.assertThat(result, Is(marker))
-
-    def test_None_is_default_alternative(self):
-        # try_import('thing') returns None if 'thing' doesn't exist.
-        result = try_import('doesntexist')
-        self.assertThat(result, Is(None))
-
-    def test_existing_module(self):
-        # try_import('thing', foo) imports 'thing' and returns it if it's a
-        # module that exists.
-        result = try_import('os', object())
-        import os
-        self.assertThat(result, Is(os))
-
-    def test_existing_submodule(self):
-        # try_import('thing.another', foo) imports 'thing' and returns it if
-        # it's a module that exists.
-        result = try_import('os.path', object())
-        import os
-        self.assertThat(result, Is(os.path))
-
-    def test_nonexistent_submodule(self):
-        # try_import('thing.another', foo) imports 'thing' and returns foo if
-        # 'another' doesn't exist.
-        marker = object()
-        result = try_import('os.doesntexist', marker)
-        self.assertThat(result, Is(marker))
-
-    def test_object_from_module(self):
-        # try_import('thing.object') imports 'thing' and returns
-        # 'thing.object' if 'thing' is a module and 'object' is not.
-        result = try_import('os.path.join')
-        import os
-        self.assertThat(result, Is(os.path.join))
-
-    def test_error_callback(self):
-        # the error callback is called on failures.
-        check_error_callback(self, try_import, 'doesntexist', 1, False)
-
-    def test_error_callback_missing_module_member(self):
-        # the error callback is called on failures to find an object
-        # inside an existing module.
-        check_error_callback(self, try_import, 'os.nonexistent', 1, False)
-
-    def test_error_callback_not_on_success(self):
-        # the error callback is not called on success.
-        check_error_callback(self, try_import, 'os.path', 0, True)
-
-
-class TestTryImports(TestCase):
-
-    def test_doesnt_exist(self):
-        # try_imports('thing', foo) returns foo if 'thing' doesn't exist.
-        marker = object()
-        result = try_imports(['doesntexist'], marker)
-        self.assertThat(result, Is(marker))
-
-    def test_fallback(self):
-        result = try_imports(['doesntexist', 'os'])
-        import os
-        self.assertThat(result, Is(os))
-
-    def test_None_is_default_alternative(self):
-        # try_imports('thing') returns None if 'thing' doesn't exist.
-        e = self.assertRaises(
-            ImportError, try_imports, ['doesntexist', 'noreally'])
-        self.assertThat(
-            str(e),
-            Equals("Could not import any of: doesntexist, noreally"))
-
-    def test_existing_module(self):
-        # try_imports('thing', foo) imports 'thing' and returns it if it's a
-        # module that exists.
-        result = try_imports(['os'], object())
-        import os
-        self.assertThat(result, Is(os))
-
-    def test_existing_submodule(self):
-        # try_imports('thing.another', foo) imports 'thing' and returns it if
-        # it's a module that exists.
-        result = try_imports(['os.path'], object())
-        import os
-        self.assertThat(result, Is(os.path))
-
-    def test_nonexistent_submodule(self):
-        # try_imports('thing.another', foo) imports 'thing' and returns foo if
-        # 'another' doesn't exist.
-        marker = object()
-        result = try_imports(['os.doesntexist'], marker)
-        self.assertThat(result, Is(marker))
-
-    def test_fallback_submodule(self):
-        result = try_imports(['os.doesntexist', 'os.path'])
-        import os
-        self.assertThat(result, Is(os.path))
-
-    def test_error_callback(self):
-        # One error for every class that doesn't exist.
-        check_error_callback(self, try_imports,
-            ['os.doesntexist', 'os.notthiseither'],
-            2, False)
-        check_error_callback(self, try_imports,
-            ['os.doesntexist', 'os.notthiseither', 'os'],
-            2, True)
-        check_error_callback(self, try_imports,
-            ['os.path'],
-            0, True)
-
-
 class TestStackHiding(TestCase):
 
     run_tests_with = FullStackRunTest
diff --git a/lib/testtools/testtools/tests/test_run.py b/lib/testtools/testtools/tests/test_run.py
index 5971a4b..2babdf8 100644
--- a/lib/testtools/testtools/tests/test_run.py
+++ b/lib/testtools/testtools/tests/test_run.py
@@ -2,27 +2,41 @@
 
 """Tests for the test runner logic."""
 
+import doctest
 from unittest import TestSuite
+import sys
+from textwrap import dedent
 
+from extras import try_import
+fixtures = try_import('fixtures')
+testresources = try_import('testresources')
+import unittest2
+
+import testtools
+from testtools import TestCase, run, skipUnless
 from testtools.compat import (
     _b,
+    _u,
     StringIO,
     )
-from testtools.helpers import try_import
-fixtures = try_import('fixtures')
-
-import testtools
-from testtools import TestCase, run
-from testtools.matchers import Contains
+from testtools.matchers import (
+    Contains,
+    DocTestMatches,
+    MatchesRegex,
+    )
 
 
 if fixtures:
     class SampleTestFixture(fixtures.Fixture):
         """Creates testtools.runexample temporarily."""
 
-        def __init__(self):
-            self.package = fixtures.PythonPackage(
-            'runexample', [('__init__.py', _b("""
+        def __init__(self, broken=False):
+            """Create a SampleTestFixture.
+
+            :param broken: If True, the sample file will not be importable.
+            """
+            if not broken:
+                init_contents = _b("""\
 from testtools import TestCase
 
 class TestFoo(TestCase):
@@ -33,13 +47,90 @@ class TestFoo(TestCase):
 def test_suite():
     from unittest import TestLoader
     return TestLoader().loadTestsFromName(__name__)
-"""))])
+""")
+            else:
+                init_contents = b"class not in\n"
+            self.package = fixtures.PythonPackage(
+            'runexample', [('__init__.py', init_contents)])
 
         def setUp(self):
             super(SampleTestFixture, self).setUp()
             self.useFixture(self.package)
             testtools.__path__.append(self.package.base)
             self.addCleanup(testtools.__path__.remove, self.package.base)
+            self.addCleanup(sys.modules.pop, 'testtools.runexample', None)
+
+
+if fixtures and testresources:
+    class SampleResourcedFixture(fixtures.Fixture):
+        """Creates a test suite that uses testresources."""
+
+        def __init__(self):
+            super(SampleResourcedFixture, self).__init__()
+            self.package = fixtures.PythonPackage(
+            'resourceexample', [('__init__.py', _b("""
+from fixtures import Fixture
+from testresources import (
+    FixtureResource,
+    OptimisingTestSuite,
+    ResourcedTestCase,
+    )
+from testtools import TestCase
+
+class Printer(Fixture):
+
+    def setUp(self):
+        super(Printer, self).setUp()
+        print('Setting up Printer')
+
+    def reset(self):
+        pass
+
+class TestFoo(TestCase, ResourcedTestCase):
+    # When run, this will print just one Setting up Printer, unless the
+    # OptimisingTestSuite is not honoured, when one per test case will print.
+    resources=[('res', FixtureResource(Printer()))]
+    def test_bar(self):
+        pass
+    def test_foo(self):
+        pass
+    def test_quux(self):
+        pass
+def test_suite():
+    from unittest import TestLoader
+    return OptimisingTestSuite(TestLoader().loadTestsFromName(__name__))
+"""))])
+
+        def setUp(self):
+            super(SampleResourcedFixture, self).setUp()
+            self.useFixture(self.package)
+            self.addCleanup(testtools.__path__.remove, self.package.base)
+            testtools.__path__.append(self.package.base)
+
+
+if fixtures:
+    class SampleLoadTestsPackage(fixtures.Fixture):
+        """Creates a test suite package using load_tests."""
+
+        def __init__(self):
+            super(SampleLoadTestsPackage, self).__init__()
+            self.package = fixtures.PythonPackage(
+            'discoverexample', [('__init__.py', _b("""
+from testtools import TestCase, clone_test_with_new_id
+
+class TestExample(TestCase):
+    def test_foo(self):
+        pass
+
+def load_tests(loader, tests, pattern):
+    tests.addTest(clone_test_with_new_id(tests._tests[1]._tests[0], "fred"))
+    return tests
+"""))])
+
+        def setUp(self):
+            super(SampleLoadTestsPackage, self).setUp()
+            self.useFixture(self.package)
+            self.addCleanup(sys.path.remove, self.package.base)
 
 
 class TestRun(TestCase):
@@ -49,14 +140,80 @@ class TestRun(TestCase):
         if fixtures is None:
             self.skipTest("Need fixtures")
 
+    def test_run_custom_list(self):
+        self.useFixture(SampleTestFixture())
+        tests = []
+        class CaptureList(run.TestToolsTestRunner):
+            def list(self, test):
+                tests.append(set([case.id() for case
+                    in testtools.testsuite.iterate_tests(test)]))
+        out = StringIO()
+        try:
+            program = run.TestProgram(
+                argv=['prog', '-l', 'testtools.runexample.test_suite'],
+                stdout=out, testRunner=CaptureList)
+        except SystemExit:
+            exc_info = sys.exc_info()
+            raise AssertionError("-l tried to exit. %r" % exc_info[1])
+        self.assertEqual([set(['testtools.runexample.TestFoo.test_bar',
+            'testtools.runexample.TestFoo.test_quux'])], tests)
+
+    def test_run_list_with_loader(self):
+        # list() is attempted with a loader first.
+        self.useFixture(SampleTestFixture())
+        tests = []
+        class CaptureList(run.TestToolsTestRunner):
+            def list(self, test, loader=None):
+                tests.append(set([case.id() for case
+                    in testtools.testsuite.iterate_tests(test)]))
+                tests.append(loader)
+        out = StringIO()
+        try:
+            program = run.TestProgram(
+                argv=['prog', '-l', 'testtools.runexample.test_suite'],
+                stdout=out, testRunner=CaptureList)
+        except SystemExit:
+            exc_info = sys.exc_info()
+            raise AssertionError("-l tried to exit. %r" % exc_info[1])
+        self.assertEqual([set(['testtools.runexample.TestFoo.test_bar',
+            'testtools.runexample.TestFoo.test_quux']), program.testLoader],
+            tests)
+
     def test_run_list(self):
         self.useFixture(SampleTestFixture())
         out = StringIO()
-        run.main(['prog', '-l', 'testtools.runexample.test_suite'], out)
+        try:
+            run.main(['prog', '-l', 'testtools.runexample.test_suite'], out)
+        except SystemExit:
+            exc_info = sys.exc_info()
+            raise AssertionError("-l tried to exit. %r" % exc_info[1])
         self.assertEqual("""testtools.runexample.TestFoo.test_bar
 testtools.runexample.TestFoo.test_quux
 """, out.getvalue())
 
+    def test_run_list_failed_import(self):
+        broken = self.useFixture(SampleTestFixture(broken=True))
+        out = StringIO()
+        # XXX: http://bugs.python.org/issue22811
+        unittest2.defaultTestLoader._top_level_dir = None
+        exc = self.assertRaises(
+            SystemExit,
+            run.main, ['prog', 'discover', '-l', broken.package.base, '*.py'], out)
+        self.assertEqual(2, exc.args[0])
+        self.assertThat(out.getvalue(), DocTestMatches("""\
+Failed to import test module: runexample
+Traceback (most recent call last):
+  File ".../loader.py", line ..., in _find_test_path
+    package = self._get_module_from_name(name)
+  File ".../loader.py", line ..., in _get_module_from_name
+    __import__(name)
+  File ".../runexample/__init__.py", line 1
+    class not in
+...^...
+SyntaxError: invalid syntax
+
+""", doctest.ELLIPSIS))
+
     def test_run_orders_tests(self):
         self.useFixture(SampleTestFixture())
         out = StringIO()
@@ -73,8 +230,13 @@ testtools.runexample.missingtest
 """))
         finally:
             f.close()
-        run.main(['prog', '-l', '--load-list', tempname,
-            'testtools.runexample.test_suite'], out)
+        try:
+            run.main(['prog', '-l', '--load-list', tempname,
+                'testtools.runexample.test_suite'], out)
+        except SystemExit:
+            exc_info = sys.exc_info()
+            raise AssertionError(
+                "-l --load-list tried to exit. %r" % exc_info[1])
         self.assertEqual("""testtools.runexample.TestFoo.test_bar
 """, out.getvalue())
 
@@ -94,11 +256,43 @@ testtools.runexample.missingtest
 """))
         finally:
             f.close()
-        run.main(['prog', '-l', '--load-list', tempname,
-            'testtools.runexample.test_suite'], out)
+        try:
+            run.main(['prog', '-l', '--load-list', tempname,
+                'testtools.runexample.test_suite'], out)
+        except SystemExit:
+            exc_info = sys.exc_info()
+            raise AssertionError(
+                "-l --load-list tried to exit. %r" % exc_info[1])
         self.assertEqual("""testtools.runexample.TestFoo.test_bar
 """, out.getvalue())
 
+    def test_load_list_preserves_custom_suites(self):
+        if testresources is None:
+            self.skipTest("Need testresources")
+        self.useFixture(SampleResourcedFixture())
+        # We load two tests, not loading one. Both share a resource, so we
+        # should see just one resource setup occur.
+        tempdir = self.useFixture(fixtures.TempDir())
+        tempname = tempdir.path + '/tests.list'
+        f = open(tempname, 'wb')
+        try:
+            f.write(_b("""
+testtools.resourceexample.TestFoo.test_bar
+testtools.resourceexample.TestFoo.test_foo
+"""))
+        finally:
+            f.close()
+        stdout = self.useFixture(fixtures.StringStream('stdout'))
+        with fixtures.MonkeyPatch('sys.stdout', stdout.stream):
+            try:
+                run.main(['prog', '--load-list', tempname,
+                    'testtools.resourceexample.test_suite'], stdout.stream)
+            except SystemExit:
+                # Evil resides in TestProgram.
+                pass
+        out = stdout.getDetails()['stdout'].as_text()
+        self.assertEqual(1, out.count('Setting up Printer'), "%r" % out)
+
     def test_run_failfast(self):
         stdout = self.useFixture(fixtures.StringStream('stdout'))
 
@@ -107,12 +301,44 @@ testtools.runexample.missingtest
                 self.fail('a')
             def test_b(self):
                 self.fail('b')
-        runner = run.TestToolsTestRunner(failfast=True)
         with fixtures.MonkeyPatch('sys.stdout', stdout.stream):
+            runner = run.TestToolsTestRunner(failfast=True)
             runner.run(TestSuite([Failing('test_a'), Failing('test_b')]))
         self.assertThat(
             stdout.getDetails()['stdout'].as_text(), Contains('Ran 1 test'))
 
+    def test_stdout_honoured(self):
+        self.useFixture(SampleTestFixture())
+        tests = []
+        out = StringIO()
+        exc = self.assertRaises(SystemExit, run.main,
+            argv=['prog', 'testtools.runexample.test_suite'],
+            stdout=out)
+        self.assertEqual((0,), exc.args)
+        self.assertThat(
+            out.getvalue(),
+            MatchesRegex(_u("""Tests running...
+
+Ran 2 tests in \\d.\\d\\d\\ds
+OK
+""")))
+
+    @skipUnless(fixtures, "fixtures not present")
+    def test_issue_16662(self):
+        # unittest's discover implementation didn't handle load_tests on
+        # packages. That is fixed pending commit, but we want to offer it
+        # to all testtools users regardless of Python version.
+        # See http://bugs.python.org/issue16662
+        pkg = self.useFixture(SampleLoadTestsPackage())
+        out = StringIO()
+        # XXX: http://bugs.python.org/issue22811
+        unittest2.defaultTestLoader._top_level_dir = None
+        self.assertEqual(None, run.main(
+            ['prog', 'discover', '-l', pkg.package.base], out))
+        self.assertEqual(dedent("""\
+            discoverexample.TestExample.test_foo
+            fred
+            """), out.getvalue())
 
 
 def test_suite():
diff --git a/lib/testtools/testtools/tests/test_runtest.py b/lib/testtools/testtools/tests/test_runtest.py
index afbb8ba..3ae8b13 100644
--- a/lib/testtools/testtools/tests/test_runtest.py
+++ b/lib/testtools/testtools/tests/test_runtest.py
@@ -34,6 +34,12 @@ class TestRunTest(TestCase):
         run = RunTest("bar", handlers)
         self.assertEqual(handlers, run.handlers)
 
+    def test__init____handlers_last_resort(self):
+        handlers = [("quux", "baz")]
+        last_resort = "foo"
+        run = RunTest("bar", handlers, last_resort)
+        self.assertEqual(last_resort, run.last_resort)
+
     def test_run_with_result(self):
         # test.run passes result down to _run_test_method.
         log = []
@@ -61,15 +67,19 @@ class TestRunTest(TestCase):
         run.run()
         self.assertEqual(['foo'], log)
 
-    def test__run_user_does_not_catch_keyboard(self):
-        case = self.make_case()
-        def raises():
-            raise KeyboardInterrupt("yo")
-        run = RunTest(case, None)
+    def test__run_prepared_result_does_not_mask_keyboard(self):
+        class Case(TestCase):
+            def test(self):
+                raise KeyboardInterrupt("go")
+        case = Case('test')
+        run = RunTest(case)
         run.result = ExtendedTestResult()
-        self.assertThat(lambda: run._run_user(raises),
+        self.assertThat(lambda: run._run_prepared_result(run.result),
             Raises(MatchesException(KeyboardInterrupt)))
-        self.assertEqual([], run.result._events)
+        self.assertEqual(
+            [('startTest', case), ('stopTest', case)], run.result._events)
+        # tearDown is still run though!
+        self.assertEqual(True, getattr(case, '_TestCase__teardown_called'))
 
     def test__run_user_calls_onException(self):
         case = self.make_case()
@@ -103,21 +113,43 @@ class TestRunTest(TestCase):
         self.assertEqual([], run.result._events)
         self.assertEqual([], log)
 
-    def test__run_user_uncaught_Exception_raised(self):
-        case = self.make_case()
+    def test__run_prepared_result_uncaught_Exception_raised(self):
         e = KeyError('Yo')
-        def raises():
-            raise e
+        class Case(TestCase):
+            def test(self):
+                raise e
+        case = Case('test')
         log = []
         def log_exc(self, result, err):
             log.append((result, err))
         run = RunTest(case, [(ValueError, log_exc)])
         run.result = ExtendedTestResult()
-        self.assertThat(lambda: run._run_user(raises),
+        self.assertThat(lambda: run._run_prepared_result(run.result),
             Raises(MatchesException(KeyError)))
-        self.assertEqual([], run.result._events)
+        self.assertEqual(
+            [('startTest', case), ('stopTest', case)], run.result._events)
         self.assertEqual([], log)
 
+    def test__run_prepared_result_uncaught_Exception_triggers_error(self):
+        # https://bugs.launchpad.net/testtools/+bug/1364188
+        # When something isn't handled, the test that was
+        # executing has errored, one way or another.
+        e = SystemExit(0)
+        class Case(TestCase):
+            def test(self):
+                raise e
+        case = Case('test')
+        log = []
+        def log_exc(self, result, err):
+            log.append((result, err))
+        run = RunTest(case, [], log_exc)
+        run.result = ExtendedTestResult()
+        self.assertThat(lambda: run._run_prepared_result(run.result),
+            Raises(MatchesException(SystemExit)))
+        self.assertEqual(
+            [('startTest', case), ('stopTest', case)], run.result._events)
+        self.assertEqual([(run.result, e)], log)
+
     def test__run_user_uncaught_Exception_from_exception_handler_raised(self):
         case = self.make_case()
         def broken_handler(exc_info):
diff --git a/lib/testtools/testtools/tests/test_spinner.py b/lib/testtools/testtools/tests/test_spinner.py
index 3d677bd..31110ca 100644
--- a/lib/testtools/testtools/tests/test_spinner.py
+++ b/lib/testtools/testtools/tests/test_spinner.py
@@ -5,11 +5,12 @@
 import os
 import signal
 
+from extras import try_import
+
 from testtools import (
     skipIf,
     TestCase,
     )
-from testtools.helpers import try_import
 from testtools.matchers import (
     Equals,
     Is,
@@ -231,7 +232,7 @@ class TestRunInReactor(NeedsTwistedTestCase):
         from twisted.internet.protocol import ServerFactory
         reactor = self.make_reactor()
         spinner = self.make_spinner(reactor)
-        port = reactor.listenTCP(0, ServerFactory())
+        port = reactor.listenTCP(0, ServerFactory(), interface='127.0.0.1')
         spinner.run(self.make_timeout(), lambda: None)
         results = spinner.get_junk()
         self.assertThat(results, Equals([port]))
@@ -244,14 +245,7 @@ class TestRunInReactor(NeedsTwistedTestCase):
         timeout = self.make_timeout()
         spinner = self.make_spinner(reactor)
         spinner.run(timeout, reactor.callInThread, time.sleep, timeout / 2.0)
-        # Python before 2.5 has a race condition with thread handling where
-        # join() does not remove threads from enumerate before returning - the
-        # thread being joined does the removal. This was fixed in Python 2.5
-        # but we still support 2.4, so we have to workaround the issue.
-        # http://bugs.python.org/issue1703448.
-        self.assertThat(
-            [thread for thread in threading.enumerate() if thread.isAlive()],
-            Equals(current_threads))
+        self.assertThat(list(threading.enumerate()), Equals(current_threads))
 
     def test_leftover_junk_available(self):
         # If 'run' is given a function that leaves the reactor dirty in some
@@ -261,7 +255,7 @@ class TestRunInReactor(NeedsTwistedTestCase):
         reactor = self.make_reactor()
         spinner = self.make_spinner(reactor)
         port = spinner.run(
-            self.make_timeout(), reactor.listenTCP, 0, ServerFactory())
+            self.make_timeout(), reactor.listenTCP, 0, ServerFactory(), interface='127.0.0.1')
         self.assertThat(spinner.get_junk(), Equals([port]))
 
     def test_will_not_run_with_previous_junk(self):
@@ -271,7 +265,7 @@ class TestRunInReactor(NeedsTwistedTestCase):
         reactor = self.make_reactor()
         spinner = self.make_spinner(reactor)
         timeout = self.make_timeout()
-        spinner.run(timeout, reactor.listenTCP, 0, ServerFactory())
+        spinner.run(timeout, reactor.listenTCP, 0, ServerFactory(), interface='127.0.0.1')
         self.assertThat(lambda: spinner.run(timeout, lambda: None),
             Raises(MatchesException(_spinner.StaleJunkError)))
 
@@ -282,7 +276,7 @@ class TestRunInReactor(NeedsTwistedTestCase):
         reactor = self.make_reactor()
         spinner = self.make_spinner(reactor)
         timeout = self.make_timeout()
-        port = spinner.run(timeout, reactor.listenTCP, 0, ServerFactory())
+        port = spinner.run(timeout, reactor.listenTCP, 0, ServerFactory(), interface='127.0.0.1')
         junk = spinner.clear_junk()
         self.assertThat(junk, Equals([port]))
         self.assertThat(spinner.get_junk(), Equals([]))
diff --git a/lib/testtools/testtools/tests/test_testcase.py b/lib/testtools/testtools/tests/test_testcase.py
index eca781b..185b726 100644
--- a/lib/testtools/testtools/tests/test_testcase.py
+++ b/lib/testtools/testtools/tests/test_testcase.py
@@ -8,6 +8,7 @@ import sys
 import unittest
 
 from testtools import (
+    DecorateTestCaseResult,
     ErrorHolder,
     MultipleExceptions,
     PlaceHolder,
@@ -23,15 +24,23 @@ from testtools.compat import (
     _b,
     _u,
     )
-from testtools.content import TracebackContent
+from testtools.content import (
+    text_content,
+    TracebackContent,
+    )
 from testtools.matchers import (
     Annotate,
     DocTestMatches,
     Equals,
+    HasLength,
     MatchesException,
     Raises,
     )
-from testtools.testcase import Nullary
+from testtools.testcase import (
+    attr,
+    Nullary,
+    WithAttributes,
+    )
 from testtools.testresult.doubles import (
     Python26TestResult,
     Python27TestResult,
@@ -42,12 +51,6 @@ from testtools.tests.helpers import (
     FullStackRunTest,
     LoggingResult,
     )
-try:
-    exec('from __future__ import with_statement')
-except SyntaxError:
-    pass
-else:
-    from testtools.tests.test_with_with import *
 
 
 class TestPlaceHolder(TestCase):
@@ -109,7 +112,8 @@ class TestPlaceHolder(TestCase):
         log = []
         test.run(LoggingResult(log))
         self.assertEqual(
-            [('startTest', test), ('addSuccess', test), ('stopTest', test)],
+            [('tags', set(), set()), ('startTest', test), ('addSuccess', test),
+             ('stopTest', test), ('tags', set(), set()),],
             log)
 
     def test_supplies_details(self):
@@ -118,9 +122,27 @@ class TestPlaceHolder(TestCase):
         result = ExtendedTestResult()
         test.run(result)
         self.assertEqual(
-            [('startTest', test),
+            [('tags', set(), set()),
+             ('startTest', test),
              ('addSuccess', test, details),
-             ('stopTest', test)],
+             ('stopTest', test),
+             ('tags', set(), set()),
+             ],
+            result._events)
+
+    def test_supplies_timestamps(self):
+        test = PlaceHolder('foo', details={}, timestamps=["A", "B"])
+        result = ExtendedTestResult()
+        test.run(result)
+        self.assertEqual(
+            [('time', "A"),
+             ('tags', set(), set()),
+             ('startTest', test),
+             ('time', "B"),
+             ('addSuccess', test),
+             ('stopTest', test),
+             ('tags', set(), set()),
+             ],
             result._events)
 
     def test_call_is_run(self):
@@ -141,6 +163,19 @@ class TestPlaceHolder(TestCase):
         # A PlaceHolder can be debugged.
         self.makePlaceHolder().debug()
 
+    def test_supports_tags(self):
+        result = ExtendedTestResult()
+        tags = set(['foo', 'bar'])
+        case = PlaceHolder("foo", tags=tags)
+        case.run(result)
+        self.assertEqual([
+            ('tags', tags, set()),
+            ('startTest', case),
+            ('addSuccess', case),
+            ('stopTest', case),
+            ('tags', set(), tags),
+            ], result._events)
+
 
 class TestErrorHolder(TestCase):
     # Note that these tests exist because ErrorHolder exists - it could be
@@ -194,9 +229,11 @@ class TestErrorHolder(TestCase):
         log = result._events
         test.run(result)
         self.assertEqual(
-            [('startTest', test),
+            [('tags', set(), set()),
+             ('startTest', test),
              ('addError', test, test._details),
-             ('stopTest', test)], log)
+             ('stopTest', test),
+             ('tags', set(), set())], log)
 
     def test_call_is_run(self):
         # A PlaceHolder can be called, in which case it behaves like run.
@@ -259,6 +296,19 @@ class TestAssertions(TestCase):
         # assertRaises asserts that a callable raises a particular exception.
         self.assertRaises(RuntimeError, self.raiseError, RuntimeError)
 
+    def test_assertRaises_exception_w_metaclass(self):
+        # assertRaises works when called for exceptions with custom metaclasses
+        class MyExMeta(type):
+            def __init__(cls, name, bases, dct):
+                """ Do some dummy metaclass stuff """
+                dct.update({'answer': 42})
+                type.__init__(cls, name, bases, dct)
+
+        class MyEx(Exception):
+            __metaclass__ = MyExMeta
+
+        self.assertRaises(MyEx, self.raiseError, MyEx)
+
     def test_assertRaises_fails_when_no_error_raised(self):
         # assertRaises raises self.failureException when it's passed a
         # callable that raises no error.
@@ -344,6 +394,16 @@ class TestAssertions(TestCase):
             '%r not in %r' % ('qux', 'foo bar baz'),
             self.assertIn, 'qux', 'foo bar baz')
 
+    def test_assertIn_failure_with_message(self):
+        # assertIn(needle, haystack) fails the test when 'needle' is not in
+        # 'haystack'.
+        self.assertFails('3 not in [0, 1, 2]: foo bar', self.assertIn, 3,
+                         [0, 1, 2], 'foo bar')
+        self.assertFails(
+            '%r not in %r: foo bar' % ('qux', 'foo bar baz'),
+            self.assertIn, 'qux', 'foo bar baz', 'foo bar')
+
+
     def test_assertNotIn_success(self):
         # assertNotIn(needle, haystack) asserts that 'needle' is not in
         # 'haystack'.
@@ -359,6 +419,18 @@ class TestAssertions(TestCase):
             "'foo bar baz' matches Contains('foo')",
             self.assertNotIn, 'foo', 'foo bar baz')
 
+
+    def test_assertNotIn_failure_with_message(self):
+        # assertNotIn(needle, haystack) fails the test when 'needle' is in
+        # 'haystack'.
+        self.assertFails('[1, 2, 3] matches Contains(3): foo bar', self.assertNotIn,
+            3, [1, 2, 3], 'foo bar')
+        self.assertFails(
+            "'foo bar baz' matches Contains('foo'): foo bar",
+            self.assertNotIn, 'foo', 'foo bar baz', "foo bar")
+
+
+
     def test_assertIsInstance(self):
         # assertIsInstance asserts that an object is an instance of a class.
 
@@ -513,6 +585,48 @@ class TestAssertions(TestCase):
         self.assertFails(
             expected, self.assertThat, matchee, matcher, verbose=True)
 
+    def test_expectThat_matches_clean(self):
+        class Matcher(object):
+            def match(self, foo):
+                return None
+        self.expectThat("foo", Matcher())
+
+    def test_expectThat_mismatch_fails_test(self):
+        class Test(TestCase):
+            def test(self):
+                self.expectThat("foo", Equals("bar"))
+        result = Test("test").run()
+        self.assertFalse(result.wasSuccessful())
+
+    def test_expectThat_does_not_exit_test(self):
+        class Test(TestCase):
+            marker = False
+            def test(self):
+                self.expectThat("foo", Equals("bar"))
+                Test.marker = True
+        result = Test("test").run()
+        self.assertFalse(result.wasSuccessful())
+        self.assertTrue(Test.marker)
+
+    def test_expectThat_adds_detail(self):
+        class Test(TestCase):
+            def test(self):
+                self.expectThat("foo", Equals("bar"))
+        test = Test("test")
+        result = test.run()
+        details = test.getDetails()
+        self.assertTrue("Failed expectation" in details)
+
+    def test__force_failure_fails_test(self):
+        class Test(TestCase):
+            def test_foo(self):
+                self.force_failure = True
+                self.remaining_code_run = True
+        test = Test('test_foo')
+        result = test.run()
+        self.assertFalse(result.wasSuccessful())
+        self.assertTrue(test.remaining_code_run)
+
     def get_error_string(self, e):
         """Get the string showing how 'e' would be formatted in test output.
 
@@ -609,6 +723,18 @@ class TestAssertions(TestCase):
         self.assertFails(expected_error, self.assertIsNotNone, None)
 
 
+    def test_fail_preserves_traceback_detail(self):
+        class Test(TestCase):
+            def test(self):
+                self.addDetail('traceback', text_content('foo'))
+                self.fail('bar')
+        test = Test('test')
+        result = ExtendedTestResult()
+        test.run(result)
+        self.assertEqual(set(['traceback', 'traceback-1']),
+            set(result._events[1][2].keys()))
+
+
 class TestAddCleanup(TestCase):
     """Tests for TestCase.addCleanup."""
 
@@ -777,6 +903,18 @@ class TestAddCleanup(TestCase):
             set(self.logging_result._events[1][2].keys()))
 
 
+class TestRunTestUsage(TestCase):
+
+    def test_last_resort_in_place(self):
+        class TestBase(TestCase):
+            def test_base_exception(self):
+                raise SystemExit(0)
+        result = ExtendedTestResult()
+        test = TestBase("test_base_exception")
+        self.assertRaises(SystemExit, test.run, result)
+        self.assertFalse(result.wasSuccessful())
+
+
 class TestWithDetails(TestCase):
 
     run_test_with = FullStackRunTest
@@ -874,6 +1012,28 @@ class TestExpectedFailure(TestWithDetails):
         self.assertDetailsProvided(case, "addUnexpectedSuccess",
             ["foo", "reason"])
 
+    @skipIf(not hasattr(unittest, 'expectedFailure'), 'Need py27+')
+    def test_unittest_expectedFailure_decorator_works_with_failure(self):
+        class ReferenceTest(TestCase):
+            @unittest.expectedFailure
+            def test_fails_expectedly(self):
+                self.assertEquals(1, 0)
+
+        test = ReferenceTest('test_fails_expectedly')
+        result = test.run()
+        self.assertEqual(True, result.wasSuccessful())
+
+    @skipIf(not hasattr(unittest, 'expectedFailure'), 'Need py27+')
+    def test_unittest_expectedFailure_decorator_works_with_success(self):
+        class ReferenceTest(TestCase):
+            @unittest.expectedFailure
+            def test_passes_unexpectedly(self):
+                self.assertEquals(1, 1)
+
+        test = ReferenceTest('test_passes_unexpectedly')
+        result = test.run()
+        self.assertEqual(False, result.wasSuccessful())
+
 
 class TestUniqueFactories(TestCase):
     """Tests for getUniqueString and getUniqueInteger."""
@@ -1039,11 +1199,32 @@ class TestDetailsProvided(TestWithDetails):
         self.assertDetailsProvided(Case("test"), "addFailure",
             ["foo", "foo-1", "traceback"])
 
+    def test_addDetailUniqueName_works(self):
+        content = self.get_content()
+        class Case(TestCase):
+            def test(self):
+                self.addDetailUniqueName("foo", content)
+                self.addDetailUniqueName("foo", content)
+        self.assertDetailsProvided(Case("test"), "addSuccess",
+            ["foo", "foo-1"])
+
 
 class TestSetupTearDown(TestCase):
 
     run_test_with = FullStackRunTest
 
+    def test_setUpCalledTwice(self):
+        class CallsTooMuch(TestCase):
+            def test_method(self):
+                self.setUp()
+        result = unittest.TestResult()
+        CallsTooMuch('test_method').run(result)
+        self.assertThat(result.errors, HasLength(1))
+        self.assertThat(result.errors[0][1],
+            DocTestMatches(
+                "...ValueError...File...testtools/tests/test_testcase.py...",
+                ELLIPSIS))
+
     def test_setUpNotCalled(self):
         class DoesnotcallsetUp(TestCase):
             def setUp(self):
@@ -1052,7 +1233,23 @@ class TestSetupTearDown(TestCase):
                 pass
         result = unittest.TestResult()
         DoesnotcallsetUp('test_method').run(result)
-        self.assertEqual(1, len(result.errors))
+        self.assertThat(result.errors, HasLength(1))
+        self.assertThat(result.errors[0][1],
+            DocTestMatches(
+                "...ValueError...File...testtools/tests/test_testcase.py...",
+                ELLIPSIS))
+
+    def test_tearDownCalledTwice(self):
+        class CallsTooMuch(TestCase):
+            def test_method(self):
+                self.tearDown()
+        result = unittest.TestResult()
+        CallsTooMuch('test_method').run(result)
+        self.assertThat(result.errors, HasLength(1))
+        self.assertThat(result.errors[0][1],
+            DocTestMatches(
+                "...ValueError...File...testtools/tests/test_testcase.py...",
+                ELLIPSIS))
 
     def test_tearDownNotCalled(self):
         class DoesnotcalltearDown(TestCase):
@@ -1062,7 +1259,17 @@ class TestSetupTearDown(TestCase):
                 pass
         result = unittest.TestResult()
         DoesnotcalltearDown('test_method').run(result)
-        self.assertEqual(1, len(result.errors))
+        self.assertThat(result.errors, HasLength(1))
+        self.assertThat(result.errors[0][1],
+            DocTestMatches(
+                "...ValueError...File...testtools/tests/test_testcase.py...",
+                ELLIPSIS))
+
+
+require_py27_minimum = skipIf(
+    sys.version < '2.7',
+    "Requires python 2.7 or greater"
+)
 
 
 class TestSkipping(TestCase):
@@ -1168,6 +1375,71 @@ class TestSkipping(TestCase):
         test.run(result)
         self.assertEqual('addSuccess', result._events[1][0])
 
+    def check_skip_decorator_does_not_run_setup(self, decorator, reason):
+        class SkippingTest(TestCase):
+
+            setup_ran = False
+
+            def setUp(self):
+                super(SkippingTest, self).setUp()
+                self.setup_ran = True
+
+            # Use the decorator passed to us:
+            @decorator
+            def test_skipped(self):
+                self.fail()
+
+        test = SkippingTest('test_skipped')
+        result = test.run()
+        self.assertTrue(result.wasSuccessful())
+        self.assertTrue(reason in result.skip_reasons, result.skip_reasons)
+        self.assertFalse(test.setup_ran)
+
+    def test_testtools_skip_decorator_does_not_run_setUp(self):
+        reason = self.getUniqueString()
+        self.check_skip_decorator_does_not_run_setup(
+            skip(reason),
+            reason
+        )
+
+    def test_testtools_skipIf_decorator_does_not_run_setUp(self):
+        reason = self.getUniqueString()
+        self.check_skip_decorator_does_not_run_setup(
+            skipIf(True, reason),
+            reason
+        )
+
+    def test_testtools_skipUnless_decorator_does_not_run_setUp(self):
+        reason = self.getUniqueString()
+        self.check_skip_decorator_does_not_run_setup(
+            skipUnless(False, reason),
+            reason
+        )
+
+    @require_py27_minimum
+    def test_unittest_skip_decorator_does_not_run_setUp(self):
+        reason = self.getUniqueString()
+        self.check_skip_decorator_does_not_run_setup(
+            unittest.skip(reason),
+            reason
+        )
+
+    @require_py27_minimum
+    def test_unittest_skipIf_decorator_does_not_run_setUp(self):
+        reason = self.getUniqueString()
+        self.check_skip_decorator_does_not_run_setup(
+            unittest.skipIf(True, reason),
+            reason
+        )
+
+    @require_py27_minimum
+    def test_unittest_skipUnless_decorator_does_not_run_setUp(self):
+        reason = self.getUniqueString()
+        self.check_skip_decorator_does_not_run_setup(
+            unittest.skipUnless(False, reason),
+            reason
+        )
+
 
 class TestOnException(TestCase):
 
@@ -1330,6 +1602,129 @@ class TestNullary(TestCase):
         self.assertRaises(ZeroDivisionError, wrapped)
 
 
+class Attributes(WithAttributes, TestCase):
+    @attr('foo')
+    def simple(self):
+        pass
+
+    # Not sorted here, forward or backwards.
+    @attr('foo', 'quux', 'bar')
+    def many(self):
+        pass
+
+    # Not sorted here, forward or backwards.
+    @attr('bar')
+    @attr('quux')
+    @attr('foo')
+    def decorated(self):
+        pass
+
+
+class TestAttributes(TestCase):
+
+    def test_simple_attr(self):
+        # Adding an attr to a test changes its id().
+        case = Attributes('simple')
+        self.assertEqual(
+            'testtools.tests.test_testcase.Attributes.simple[foo]',
+            case.id())
+
+    def test_multiple_attributes(self):
+        case = Attributes('many')
+        self.assertEqual(
+            'testtools.tests.test_testcase.Attributes.many[bar,foo,quux]',
+            case.id())
+
+    def test_multiple_attr_decorators(self):
+        case = Attributes('decorated')
+        self.assertEqual(
+            'testtools.tests.test_testcase.Attributes.decorated[bar,foo,quux]',
+            case.id())
+
+
+class TestDecorateTestCaseResult(TestCase):
+
+    def setUp(self):
+        super(TestDecorateTestCaseResult, self).setUp()
+        self.log = []
+
+    def make_result(self, result):
+        self.log.append(('result', result))
+        return LoggingResult(self.log)
+
+    def test___call__(self):
+        case = DecorateTestCaseResult(PlaceHolder('foo'), self.make_result)
+        case(None)
+        case('something')
+        self.assertEqual([('result', None),
+            ('tags', set(), set()),
+            ('startTest', case.decorated),
+            ('addSuccess', case.decorated),
+            ('stopTest', case.decorated),
+            ('tags', set(), set()),
+            ('result', 'something'),
+            ('tags', set(), set()),
+            ('startTest', case.decorated),
+            ('addSuccess', case.decorated),
+            ('stopTest', case.decorated),
+            ('tags', set(), set())
+            ], self.log)
+
+    def test_run(self):
+        case = DecorateTestCaseResult(PlaceHolder('foo'), self.make_result)
+        case.run(None)
+        case.run('something')
+        self.assertEqual([('result', None),
+            ('tags', set(), set()),
+            ('startTest', case.decorated),
+            ('addSuccess', case.decorated),
+            ('stopTest', case.decorated),
+            ('tags', set(), set()),
+            ('result', 'something'),
+            ('tags', set(), set()),
+            ('startTest', case.decorated),
+            ('addSuccess', case.decorated),
+            ('stopTest', case.decorated),
+            ('tags', set(), set())
+            ], self.log)
+
+    def test_before_after_hooks(self):
+        case = DecorateTestCaseResult(PlaceHolder('foo'), self.make_result,
+            before_run=lambda result: self.log.append('before'),
+            after_run=lambda result: self.log.append('after'))
+        case.run(None)
+        case(None)
+        self.assertEqual([
+            ('result', None),
+            'before',
+            ('tags', set(), set()),
+            ('startTest', case.decorated),
+            ('addSuccess', case.decorated),
+            ('stopTest', case.decorated),
+            ('tags', set(), set()),
+            'after',
+            ('result', None),
+            'before',
+            ('tags', set(), set()),
+            ('startTest', case.decorated),
+            ('addSuccess', case.decorated),
+            ('stopTest', case.decorated),
+            ('tags', set(), set()),
+            'after',
+            ], self.log)
+
+    def test_other_attribute(self):
+        orig = PlaceHolder('foo')
+        orig.thing = 'fred'
+        case = DecorateTestCaseResult(orig, self.make_result)
+        self.assertEqual('fred', case.thing)
+        self.assertRaises(AttributeError, getattr, case, 'other')
+        case.other = 'barbara'
+        self.assertEqual('barbara', orig.other)
+        del case.thing
+        self.assertRaises(AttributeError, getattr, orig, 'thing')
+
+
 def test_suite():
     from unittest import TestLoader
     return TestLoader().loadTestsFromName(__name__)
diff --git a/lib/testtools/testtools/tests/test_testresult.py b/lib/testtools/testtools/tests/test_testresult.py
index 68fcc38..a8034b2 100644
--- a/lib/testtools/testtools/tests/test_testresult.py
+++ b/lib/testtools/testtools/tests/test_testresult.py
@@ -7,7 +7,9 @@ __metaclass__ = type
 import codecs
 import datetime
 import doctest
+from itertools import chain, combinations
 import os
+import re
 import shutil
 import sys
 import tempfile
@@ -15,17 +17,33 @@ import threading
 from unittest import TestSuite
 import warnings
 
+from extras import safe_hasattr, try_imports
+
+Queue = try_imports(['Queue.Queue', 'queue.Queue'])
+
 from testtools import (
+    CopyStreamResult,
     ExtendedToOriginalDecorator,
+    ExtendedToStreamDecorator,
     MultiTestResult,
     PlaceHolder,
+    StreamFailFast,
+    StreamResult,
+    StreamResultRouter,
+    StreamSummary,
+    StreamTagger,
+    StreamToDict,
+    StreamToExtendedDecorator,
+    StreamToQueue,
     Tagger,
     TestCase,
+    TestControl,
     TestResult,
     TestResultDecorator,
     TestByTestResult,
     TextTestResult,
     ThreadsafeForwardingResult,
+    TimestampingStreamResult,
     testresult,
     )
 from testtools.compat import (
@@ -44,13 +62,15 @@ from testtools.content import (
     TracebackContent,
     )
 from testtools.content_type import ContentType, UTF8_TEXT
-from testtools.helpers import safe_hasattr
 from testtools.matchers import (
+    AllMatch,
     Contains,
     DocTestMatches,
     Equals,
+    HasLength,
     MatchesAny,
     MatchesException,
+    MatchesRegex,
     Raises,
     )
 from testtools.tests.helpers import (
@@ -63,6 +83,7 @@ from testtools.testresult.doubles import (
     Python26TestResult,
     Python27TestResult,
     ExtendedTestResult,
+    StreamResult as LoggingStreamResult,
     )
 from testtools.testresult.real import (
     _details_to_str,
@@ -221,18 +242,21 @@ class TagsContract(Python27Contract):
     def test_no_tags_by_default(self):
         # Results initially have no tags.
         result = self.makeResult()
+        result.startTestRun()
         self.assertEqual(frozenset(), result.current_tags)
 
     def test_adding_tags(self):
         # Tags are added using 'tags' and thus become visible in
         # 'current_tags'.
         result = self.makeResult()
+        result.startTestRun()
         result.tags(set(['foo']), set())
         self.assertEqual(set(['foo']), result.current_tags)
 
     def test_removing_tags(self):
         # Tags are removed using 'tags'.
         result = self.makeResult()
+        result.startTestRun()
         result.tags(set(['foo']), set())
         result.tags(set(), set(['foo']))
         self.assertEqual(set(), result.current_tags)
@@ -240,6 +264,7 @@ class TagsContract(Python27Contract):
     def test_startTestRun_resets_tags(self):
         # startTestRun makes a new test run, and thus clears all the tags.
         result = self.makeResult()
+        result.startTestRun()
         result.tags(set(['foo']), set())
         result.startTestRun()
         self.assertEqual(set(), result.current_tags)
@@ -437,6 +462,12 @@ class TestAdaptedPython27TestResultContract(TestCase, DetailsContract):
         return ExtendedToOriginalDecorator(Python27TestResult())
 
 
+class TestAdaptedStreamResult(TestCase, DetailsContract):
+
+    def makeResult(self):
+        return ExtendedToStreamDecorator(StreamResult())
+
+
 class TestTestResultDecoratorContract(TestCase, StartTestRunContract):
 
     run_test_with = FullStackRunTest
@@ -445,6 +476,581 @@ class TestTestResultDecoratorContract(TestCase, StartTestRunContract):
         return TestResultDecorator(TestResult())
 
 
+# DetailsContract because ExtendedToStreamDecorator follows Python for
+# uxsuccess handling.
+class TestStreamToExtendedContract(TestCase, DetailsContract):
+
+    def makeResult(self):
+        return ExtendedToStreamDecorator(
+            StreamToExtendedDecorator(ExtendedTestResult()))
+
+
+class TestStreamResultContract(object):
+
+    def _make_result(self):
+        raise NotImplementedError(self._make_result)
+
+    def test_startTestRun(self):
+        result = self._make_result()
+        result.startTestRun()
+        result.stopTestRun()
+
+    def test_files(self):
+        # Test parameter combinations when files are being emitted.
+        result = self._make_result()
+        result.startTestRun()
+        self.addCleanup(result.stopTestRun)
+        now = datetime.datetime.now(utc)
+        inputs = list(dict(
+            eof=True,
+            mime_type="text/plain",
+            route_code=_u("1234"),
+            test_id=_u("foo"),
+            timestamp=now,
+            ).items())
+        param_dicts = self._power_set(inputs)
+        for kwargs in param_dicts:
+            result.status(file_name=_u("foo"), file_bytes=_b(""), **kwargs)
+            result.status(file_name=_u("foo"), file_bytes=_b("bar"), **kwargs)
+
+    def test_test_status(self):
+        # Tests non-file attachment parameter combinations.
+        result = self._make_result()
+        result.startTestRun()
+        self.addCleanup(result.stopTestRun)
+        now = datetime.datetime.now(utc)
+        args = [[_u("foo"), s] for s in ['exists', 'inprogress', 'xfail',
+            'uxsuccess', 'success', 'fail', 'skip']]
+        inputs = list(dict(
+            runnable=False,
+            test_tags=set(['quux']),
+            route_code=_u("1234"),
+            timestamp=now,
+            ).items())
+        param_dicts = self._power_set(inputs)
+        for kwargs in param_dicts:
+            for arg in args:
+                result.status(test_id=arg[0], test_status=arg[1], **kwargs)
+
+    def _power_set(self, iterable):
+        "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
+        s = list(iterable)
+        param_dicts = []
+        for ss in chain.from_iterable(combinations(s, r) for r in range(len(s)+1)):
+            param_dicts.append(dict(ss))
+        return param_dicts
+
+
+class TestBaseStreamResultContract(TestCase, TestStreamResultContract):
+
+    def _make_result(self):
+        return StreamResult()
+
+
+class TestCopyStreamResultContract(TestCase, TestStreamResultContract):
+
+    def _make_result(self):
+        return CopyStreamResult([StreamResult(), StreamResult()])
+
+
+class TestDoubleStreamResultContract(TestCase, TestStreamResultContract):
+
+    def _make_result(self):
+        return LoggingStreamResult()
+
+
+class TestExtendedToStreamDecoratorContract(TestCase, TestStreamResultContract):
+
+    def _make_result(self):
+        return ExtendedToStreamDecorator(StreamResult())
+
+
+class TestStreamSummaryResultContract(TestCase, TestStreamResultContract):
+
+    def _make_result(self):
+        return StreamSummary()
+
+
+class TestStreamTaggerContract(TestCase, TestStreamResultContract):
+
+    def _make_result(self):
+        return StreamTagger([StreamResult()], add=set(), discard=set())
+
+
+class TestStreamToDictContract(TestCase, TestStreamResultContract):
+
+    def _make_result(self):
+        return StreamToDict(lambda x:None)
+
+
+class TestStreamToExtendedDecoratorContract(TestCase, TestStreamResultContract):
+
+    def _make_result(self):
+        return StreamToExtendedDecorator(ExtendedTestResult())
+
+
+class TestStreamToQueueContract(TestCase, TestStreamResultContract):
+
+    def _make_result(self):
+        queue = Queue()
+        return StreamToQueue(queue, "foo")
+
+
+class TestStreamFailFastContract(TestCase, TestStreamResultContract):
+
+    def _make_result(self):
+        return StreamFailFast(lambda:None)
+
+
+class TestStreamResultRouterContract(TestCase, TestStreamResultContract):
+
+    def _make_result(self):
+        return StreamResultRouter(StreamResult())
+
+
+class TestDoubleStreamResultEvents(TestCase):
+
+    def test_startTestRun(self):
+        result = LoggingStreamResult()
+        result.startTestRun()
+        self.assertEqual([('startTestRun',)], result._events)
+
+    def test_stopTestRun(self):
+        result = LoggingStreamResult()
+        result.startTestRun()
+        result.stopTestRun()
+        self.assertEqual([('startTestRun',), ('stopTestRun',)], result._events)
+
+    def test_file(self):
+        result = LoggingStreamResult()
+        result.startTestRun()
+        now = datetime.datetime.now(utc)
+        result.status(file_name="foo", file_bytes="bar", eof=True, mime_type="text/json",
+            test_id="id", route_code='abc', timestamp=now)
+        self.assertEqual(
+            [('startTestRun',),
+             ('status', 'id', None, None, True, 'foo', 'bar', True, 'text/json', 'abc', now)],
+            result._events)
+
+    def test_status(self):
+        result = LoggingStreamResult()
+        result.startTestRun()
+        now = datetime.datetime.now(utc)
+        result.status("foo", "success", test_tags=set(['tag']),
+            runnable=False, route_code='abc', timestamp=now)
+        self.assertEqual(
+            [('startTestRun',),
+             ('status', 'foo', 'success', set(['tag']), False, None, None, False, None, 'abc', now)],
+            result._events)
+
+
+class TestCopyStreamResultCopies(TestCase):
+
+    def setUp(self):
+        super(TestCopyStreamResultCopies, self).setUp()
+        self.target1 = LoggingStreamResult()
+        self.target2 = LoggingStreamResult()
+        self.targets = [self.target1._events, self.target2._events]
+        self.result = CopyStreamResult([self.target1, self.target2])
+
+    def test_startTestRun(self):
+        self.result.startTestRun()
+        self.assertThat(self.targets, AllMatch(Equals([('startTestRun',)])))
+
+    def test_stopTestRun(self):
+        self.result.startTestRun()
+        self.result.stopTestRun()
+        self.assertThat(self.targets,
+            AllMatch(Equals([('startTestRun',), ('stopTestRun',)])))
+
+    def test_status(self):
+        self.result.startTestRun()
+        now = datetime.datetime.now(utc)
+        self.result.status("foo", "success", test_tags=set(['tag']),
+            runnable=False, file_name="foo", file_bytes=b'bar', eof=True,
+            mime_type="text/json", route_code='abc', timestamp=now)
+        self.assertThat(self.targets,
+            AllMatch(Equals([('startTestRun',),
+                ('status', 'foo', 'success', set(['tag']), False, "foo",
+                 b'bar', True, "text/json", 'abc', now)
+                ])))
+
+
+class TestStreamTagger(TestCase):
+
+    def test_adding(self):
+        log = LoggingStreamResult()
+        result = StreamTagger([log], add=['foo'])
+        result.startTestRun()
+        result.status()
+        result.status(test_tags=set(['bar']))
+        result.status(test_tags=None)
+        result.stopTestRun()
+        self.assertEqual([
+            ('startTestRun',),
+            ('status', None, None, set(['foo']), True, None, None, False, None, None, None),
+            ('status', None, None, set(['foo', 'bar']), True, None, None, False, None, None, None),
+            ('status', None, None, set(['foo']), True, None, None, False, None, None, None),
+            ('stopTestRun',),
+            ], log._events)
+
+    def test_discarding(self):
+        log = LoggingStreamResult()
+        result = StreamTagger([log], discard=['foo'])
+        result.startTestRun()
+        result.status()
+        result.status(test_tags=None)
+        result.status(test_tags=set(['foo']))
+        result.status(test_tags=set(['bar']))
+        result.status(test_tags=set(['foo', 'bar']))
+        result.stopTestRun()
+        self.assertEqual([
+            ('startTestRun',),
+            ('status', None, None, None, True, None, None, False, None, None, None),
+            ('status', None, None, None, True, None, None, False, None, None, None),
+            ('status', None, None, None, True, None, None, False, None, None, None),
+            ('status', None, None, set(['bar']), True, None, None, False, None, None, None),
+            ('status', None, None, set(['bar']), True, None, None, False, None, None, None),
+            ('stopTestRun',),
+            ], log._events)
+
+
+class TestStreamToDict(TestCase):
+
+    def test_hung_test(self):
+        tests = []
+        result = StreamToDict(tests.append)
+        result.startTestRun()
+        result.status('foo', 'inprogress')
+        self.assertEqual([], tests)
+        result.stopTestRun()
+        self.assertEqual([
+            {'id': 'foo', 'tags': set(), 'details': {}, 'status': 'inprogress',
+             'timestamps': [None, None]}
+            ], tests)
+
+    def test_all_terminal_states_reported(self):
+        tests = []
+        result = StreamToDict(tests.append)
+        result.startTestRun()
+        result.status('success', 'success')
+        result.status('skip', 'skip')
+        result.status('exists', 'exists')
+        result.status('fail', 'fail')
+        result.status('xfail', 'xfail')
+        result.status('uxsuccess', 'uxsuccess')
+        self.assertThat(tests, HasLength(6))
+        self.assertEqual(
+            ['success', 'skip', 'exists', 'fail', 'xfail', 'uxsuccess'],
+            [test['id'] for test in tests])
+        result.stopTestRun()
+        self.assertThat(tests, HasLength(6))
+
+    def test_files_reported(self):
+        tests = []
+        result = StreamToDict(tests.append)
+        result.startTestRun()
+        result.status(file_name="some log.txt",
+            file_bytes=_b("1234 log message"), eof=True,
+            mime_type="text/plain; charset=utf8", test_id="foo.bar")
+        result.status(file_name="another file",
+            file_bytes=_b("""Traceback..."""), test_id="foo.bar")
+        result.stopTestRun()
+        self.assertThat(tests, HasLength(1))
+        test = tests[0]
+        self.assertEqual("foo.bar", test['id'])
+        self.assertEqual("unknown", test['status'])
+        details = test['details']
+        self.assertEqual(
+            _u("1234 log message"), details['some log.txt'].as_text())
+        self.assertEqual(
+            _b("Traceback..."),
+            _b('').join(details['another file'].iter_bytes()))
+        self.assertEqual(
+            "application/octet-stream", repr(details['another file'].content_type))
+
+    def test_bad_mime(self):
+        # Testtools was making bad mime types, this tests that the specific
+        # corruption is catered for.
+        tests = []
+        result = StreamToDict(tests.append)
+        result.startTestRun()
+        result.status(file_name="file", file_bytes=b'a',
+            mime_type='text/plain; charset=utf8, language=python',
+            test_id='id')
+        result.stopTestRun()
+        self.assertThat(tests, HasLength(1))
+        test = tests[0]
+        self.assertEqual("id", test['id'])
+        details = test['details']
+        self.assertEqual(_u("a"), details['file'].as_text())
+        self.assertEqual(
+            "text/plain; charset=\"utf8\"",
+            repr(details['file'].content_type))
+
+    def test_timestamps(self):
+        tests = []
+        result = StreamToDict(tests.append)
+        result.startTestRun()
+        result.status(test_id='foo', test_status='inprogress', timestamp="A")
+        result.status(test_id='foo', test_status='success', timestamp="B")
+        result.status(test_id='bar', test_status='inprogress', timestamp="C")
+        result.stopTestRun()
+        self.assertThat(tests, HasLength(2))
+        self.assertEqual(["A", "B"], tests[0]['timestamps'])
+        self.assertEqual(["C", None], tests[1]['timestamps'])
+
+
+class TestExtendedToStreamDecorator(TestCase):
+
+    def test_explicit_time(self):
+        log = LoggingStreamResult()
+        result = ExtendedToStreamDecorator(log)
+        result.startTestRun()
+        now = datetime.datetime.now(utc)
+        result.time(now)
+        result.startTest(self)
+        result.addSuccess(self)
+        result.stopTest(self)
+        result.stopTestRun()
+        self.assertEqual([
+            ('startTestRun',),
+            ('status',
+             'testtools.tests.test_testresult.TestExtendedToStreamDecorator.test_explicit_time',
+             'inprogress',
+             None,
+             True,
+             None,
+             None,
+             False,
+             None,
+             None,
+             now),
+            ('status',
+             'testtools.tests.test_testresult.TestExtendedToStreamDecorator.test_explicit_time',
+             'success',
+              set(),
+              True,
+              None,
+              None,
+              False,
+              None,
+              None,
+              now),
+             ('stopTestRun',)], log._events)
+
+    def test_wasSuccessful_after_stopTestRun(self):
+        log = LoggingStreamResult()
+        result = ExtendedToStreamDecorator(log)
+        result.startTestRun()
+        result.status(test_id='foo', test_status='fail')
+        result.stopTestRun()
+        self.assertEqual(False, result.wasSuccessful())
+
+
+class TestStreamFailFast(TestCase):
+
+    def test_inprogress(self):
+        result = StreamFailFast(self.fail)
+        result.status('foo', 'inprogress')
+
+    def test_exists(self):
+        result = StreamFailFast(self.fail)
+        result.status('foo', 'exists')
+
+    def test_xfail(self):
+        result = StreamFailFast(self.fail)
+        result.status('foo', 'xfail')
+
+    def test_uxsuccess(self):
+        calls = []
+        def hook():
+            calls.append("called")
+        result = StreamFailFast(hook)
+        result.status('foo', 'uxsuccess')
+        result.status('foo', 'uxsuccess')
+        self.assertEqual(['called', 'called'], calls)
+
+    def test_success(self):
+        result = StreamFailFast(self.fail)
+        result.status('foo', 'success')
+
+    def test_fail(self):
+        calls = []
+        def hook():
+            calls.append("called")
+        result = StreamFailFast(hook)
+        result.status('foo', 'fail')
+        result.status('foo', 'fail')
+        self.assertEqual(['called', 'called'], calls)
+
+    def test_skip(self):
+        result = StreamFailFast(self.fail)
+        result.status('foo', 'skip')
+
+
+class TestStreamSummary(TestCase):
+
+    def test_attributes(self):
+        result = StreamSummary()
+        result.startTestRun()
+        self.assertEqual([], result.failures)
+        self.assertEqual([], result.errors)
+        self.assertEqual([], result.skipped)
+        self.assertEqual([], result.expectedFailures)
+        self.assertEqual([], result.unexpectedSuccesses)
+        self.assertEqual(0, result.testsRun)
+
+    def test_startTestRun(self):
+        result = StreamSummary()
+        result.startTestRun()
+        result.failures.append('x')
+        result.errors.append('x')
+        result.skipped.append('x')
+        result.expectedFailures.append('x')
+        result.unexpectedSuccesses.append('x')
+        result.testsRun = 1
+        result.startTestRun()
+        self.assertEqual([], result.failures)
+        self.assertEqual([], result.errors)
+        self.assertEqual([], result.skipped)
+        self.assertEqual([], result.expectedFailures)
+        self.assertEqual([], result.unexpectedSuccesses)
+        self.assertEqual(0, result.testsRun)
+
+    def test_wasSuccessful(self):
+        # wasSuccessful returns False if any of
+        # failures/errors is non-empty.
+        result = StreamSummary()
+        result.startTestRun()
+        self.assertEqual(True, result.wasSuccessful())
+        result.failures.append('x')
+        self.assertEqual(False, result.wasSuccessful())
+        result.startTestRun()
+        result.errors.append('x')
+        self.assertEqual(False, result.wasSuccessful())
+        result.startTestRun()
+        result.skipped.append('x')
+        self.assertEqual(True, result.wasSuccessful())
+        result.startTestRun()
+        result.expectedFailures.append('x')
+        self.assertEqual(True, result.wasSuccessful())
+        result.startTestRun()
+        result.unexpectedSuccesses.append('x')
+        self.assertEqual(True, result.wasSuccessful())
+
+    def test_stopTestRun(self):
+        result = StreamSummary()
+        # terminal successful codes.
+        result.startTestRun()
+        result.status("foo", "inprogress")
+        result.status("foo", "success")
+        result.status("bar", "skip")
+        result.status("baz", "exists")
+        result.stopTestRun()
+        self.assertEqual(True, result.wasSuccessful())
+        # Existence is terminal but doesn't count as 'running' a test.
+        self.assertEqual(2, result.testsRun)
+
+    def test_stopTestRun_inprogress_test_fails(self):
+        # Tests inprogress at stopTestRun trigger a failure.
+        result = StreamSummary()
+        result.startTestRun()
+        result.status("foo", "inprogress")
+        result.stopTestRun()
+        self.assertEqual(False, result.wasSuccessful())
+        self.assertThat(result.errors, HasLength(1))
+        self.assertEqual("foo", result.errors[0][0].id())
+        self.assertEqual("Test did not complete", result.errors[0][1])
+        # interim state detection handles route codes - while duplicate ids in
+        # one run is undesirable, it may happen (e.g. with repeated tests).
+        result.startTestRun()
+        result.status("foo", "inprogress")
+        result.status("foo", "inprogress", route_code="A")
+        result.status("foo", "success", route_code="A")
+        result.stopTestRun()
+        self.assertEqual(False, result.wasSuccessful())
+
+    def test_status_skip(self):
+        # when skip is seen, a synthetic test is reported with reason captured
+        # from the 'reason' file attachment if any.
+        result = StreamSummary()
+        result.startTestRun()
+        result.status(file_name="reason",
+            file_bytes=_b("Missing dependency"), eof=True,
+            mime_type="text/plain; charset=utf8", test_id="foo.bar")
+        result.status("foo.bar", "skip")
+        self.assertThat(result.skipped, HasLength(1))
+        self.assertEqual("foo.bar", result.skipped[0][0].id())
+        self.assertEqual(_u("Missing dependency"), result.skipped[0][1])
+
+    def _report_files(self, result):
+        result.status(file_name="some log.txt",
+            file_bytes=_b("1234 log message"), eof=True,
+            mime_type="text/plain; charset=utf8", test_id="foo.bar")
+        result.status(file_name="traceback",
+            file_bytes=_b("""Traceback (most recent call last):
+  File "testtools/tests/test_testresult.py", line 607, in test_stopTestRun
+      AllMatch(Equals([('startTestRun',), ('stopTestRun',)])))
+testtools.matchers._impl.MismatchError: Differences: [
+[('startTestRun',), ('stopTestRun',)] != []
+[('startTestRun',), ('stopTestRun',)] != []
+]
+"""), eof=True, mime_type="text/plain; charset=utf8", test_id="foo.bar")
+
+    files_message = Equals(_u("""some log.txt: {{{1234 log message}}}
+
+Traceback (most recent call last):
+  File "testtools/tests/test_testresult.py", line 607, in test_stopTestRun
+      AllMatch(Equals([('startTestRun',), ('stopTestRun',)])))
+testtools.matchers._impl.MismatchError: Differences: [
+[('startTestRun',), ('stopTestRun',)] != []
+[('startTestRun',), ('stopTestRun',)] != []
+]
+"""))
+
+    def test_status_fail(self):
+        # when fail is seen, a synthetic test is reported with all files
+        # attached shown as the message.
+        result = StreamSummary()
+        result.startTestRun()
+        self._report_files(result)
+        result.status("foo.bar", "fail")
+        self.assertThat(result.errors, HasLength(1))
+        self.assertEqual("foo.bar", result.errors[0][0].id())
+        self.assertThat(result.errors[0][1], self.files_message)
+
+    def test_status_xfail(self):
+        # when xfail is seen, a synthetic test is reported with all files
+        # attached shown as the message.
+        result = StreamSummary()
+        result.startTestRun()
+        self._report_files(result)
+        result.status("foo.bar", "xfail")
+        self.assertThat(result.expectedFailures, HasLength(1))
+        self.assertEqual("foo.bar", result.expectedFailures[0][0].id())
+        self.assertThat(result.expectedFailures[0][1], self.files_message)
+
+    def test_status_uxsuccess(self):
+        # when uxsuccess is seen, a synthetic test is reported.
+        result = StreamSummary()
+        result.startTestRun()
+        result.status("foo.bar", "uxsuccess")
+        self.assertThat(result.unexpectedSuccesses, HasLength(1))
+        self.assertEqual("foo.bar", result.unexpectedSuccesses[0].id())
+
+
+class TestTestControl(TestCase):
+
+    def test_default(self):
+        self.assertEqual(False, TestControl().shouldStop)
+
+    def test_stop(self):
+        control = TestControl()
+        control.stop()
+        self.assertEqual(True, control.shouldStop)
+
+
 class TestTestResult(TestCase):
     """Tests for 'TestResult'."""
 
@@ -785,6 +1391,7 @@ class TestTextTestResult(TestCase):
             DocTestMatches("...\nFAILED (failures=1)\n", doctest.ELLIPSIS))
 
     def test_stopTestRun_shows_details(self):
+        self.skip("Disabled per bug 1188420")
         def run_tests():
             self.result.startTestRun()
             make_erroring_test().run(self.result)
@@ -1097,6 +1704,193 @@ class TestMergeTags(TestCase):
             expected, _merge_tags(current_tags, changing_tags))
 
 
+class TestStreamResultRouter(TestCase):
+
+    def test_start_stop_test_run_no_fallback(self):
+        result = StreamResultRouter()
+        result.startTestRun()
+        result.stopTestRun()
+
+    def test_no_fallback_errors(self):
+        self.assertRaises(Exception, StreamResultRouter().status, test_id='f')
+
+    def test_fallback_calls(self):
+        fallback = LoggingStreamResult()
+        result = StreamResultRouter(fallback)
+        result.startTestRun()
+        result.status(test_id='foo')
+        result.stopTestRun()
+        self.assertEqual([
+            ('startTestRun',),
+            ('status', 'foo', None, None, True, None, None, False, None, None,
+             None),
+            ('stopTestRun',),
+            ],
+            fallback._events)
+
+    def test_fallback_no_do_start_stop_run(self):
+        fallback = LoggingStreamResult()
+        result = StreamResultRouter(fallback, do_start_stop_run=False)
+        result.startTestRun()
+        result.status(test_id='foo')
+        result.stopTestRun()
+        self.assertEqual([
+            ('status', 'foo', None, None, True, None, None, False, None, None,
+             None)
+            ],
+            fallback._events)
+
+    def test_add_rule_bad_policy(self):
+        router = StreamResultRouter()
+        target = LoggingStreamResult()
+        self.assertRaises(ValueError, router.add_rule, target, 'route_code_prefixa',
+            route_prefix='0')
+
+    def test_add_rule_extra_policy_arg(self):
+        router = StreamResultRouter()
+        target = LoggingStreamResult()
+        self.assertRaises(TypeError, router.add_rule, target, 'route_code_prefix',
+            route_prefix='0', foo=1)
+
+    def test_add_rule_missing_prefix(self):
+        router = StreamResultRouter()
+        target = LoggingStreamResult()
+        self.assertRaises(TypeError, router.add_rule, target, 'route_code_prefix')
+
+    def test_add_rule_slash_in_prefix(self):
+        router = StreamResultRouter()
+        target = LoggingStreamResult()
+        self.assertRaises(TypeError, router.add_rule, target, 'route_code_prefix',
+            route_prefix='0/')
+
+    def test_add_rule_route_code_consume_False(self):
+        fallback = LoggingStreamResult()
+        target = LoggingStreamResult()
+        router = StreamResultRouter(fallback)
+        router.add_rule(target, 'route_code_prefix', route_prefix='0')
+        router.status(test_id='foo', route_code='0')
+        router.status(test_id='foo', route_code='0/1')
+        router.status(test_id='foo')
+        self.assertEqual([
+            ('status', 'foo', None, None, True, None, None, False, None, '0',
+             None),
+            ('status', 'foo', None, None, True, None, None, False, None, '0/1',
+             None),
+            ],
+            target._events)
+        self.assertEqual([
+            ('status', 'foo', None, None, True, None, None, False, None, None,
+             None),
+            ],
+            fallback._events)
+
+    def test_add_rule_route_code_consume_True(self):
+        fallback = LoggingStreamResult()
+        target = LoggingStreamResult()
+        router = StreamResultRouter(fallback)
+        router.add_rule(
+            target, 'route_code_prefix', route_prefix='0', consume_route=True)
+        router.status(test_id='foo', route_code='0') # -> None
+        router.status(test_id='foo', route_code='0/1') # -> 1
+        router.status(test_id='foo', route_code='1') # -> fallback as-is.
+        self.assertEqual([
+            ('status', 'foo', None, None, True, None, None, False, None, None,
+             None),
+            ('status', 'foo', None, None, True, None, None, False, None, '1',
+             None),
+            ],
+            target._events)
+        self.assertEqual([
+            ('status', 'foo', None, None, True, None, None, False, None, '1',
+             None),
+            ],
+            fallback._events)
+
+    def test_add_rule_test_id(self):
+        nontest = LoggingStreamResult()
+        test = LoggingStreamResult()
+        router = StreamResultRouter(test)
+        router.add_rule(nontest, 'test_id', test_id=None)
+        router.status(test_id='foo', file_name="bar", file_bytes=b'')
+        router.status(file_name="bar", file_bytes=b'')
+        self.assertEqual([
+            ('status', 'foo', None, None, True, 'bar', b'', False, None, None,
+             None),], test._events)
+        self.assertEqual([
+            ('status', None, None, None, True, 'bar', b'', False, None, None,
+             None),], nontest._events)
+
+    def test_add_rule_do_start_stop_run(self):
+        nontest = LoggingStreamResult()
+        router = StreamResultRouter()
+        router.add_rule(nontest, 'test_id', test_id=None, do_start_stop_run=True)
+        router.startTestRun()
+        router.stopTestRun()
+        self.assertEqual([
+            ('startTestRun',),
+            ('stopTestRun',),
+            ], nontest._events)
+
+    def test_add_rule_do_start_stop_run_after_startTestRun(self):
+        nontest = LoggingStreamResult()
+        router = StreamResultRouter()
+        router.startTestRun()
+        router.add_rule(nontest, 'test_id', test_id=None, do_start_stop_run=True)
+        router.stopTestRun()
+        self.assertEqual([
+            ('startTestRun',),
+            ('stopTestRun',),
+            ], nontest._events)
+
+
+class TestStreamToQueue(TestCase):
+
+    def make_result(self):
+        queue = Queue()
+        return queue, StreamToQueue(queue, "foo")
+
+    def test_status(self):
+        def check_event(event_dict, route=None, time=None):
+            self.assertEqual("status", event_dict['event'])
+            self.assertEqual("test", event_dict['test_id'])
+            self.assertEqual("fail", event_dict['test_status'])
+            self.assertEqual(set(["quux"]), event_dict['test_tags'])
+            self.assertEqual(False, event_dict['runnable'])
+            self.assertEqual("file", event_dict['file_name'])
+            self.assertEqual(_b("content"), event_dict['file_bytes'])
+            self.assertEqual(True, event_dict['eof'])
+            self.assertEqual("quux", event_dict['mime_type'])
+            self.assertEqual("test", event_dict['test_id'])
+            self.assertEqual(route, event_dict['route_code'])
+            self.assertEqual(time, event_dict['timestamp'])
+        queue, result = self.make_result()
+        result.status("test", "fail", test_tags=set(["quux"]), runnable=False,
+            file_name="file", file_bytes=_b("content"), eof=True,
+            mime_type="quux", route_code=None, timestamp=None)
+        self.assertEqual(1, queue.qsize())
+        a_time = datetime.datetime.now(utc)
+        result.status("test", "fail", test_tags=set(["quux"]), runnable=False,
+            file_name="file", file_bytes=_b("content"), eof=True,
+            mime_type="quux", route_code="bar", timestamp=a_time)
+        self.assertEqual(2, queue.qsize())
+        check_event(queue.get(False), route="foo", time=None)
+        check_event(queue.get(False), route="foo/bar", time=a_time)
+
+    def testStartTestRun(self):
+        queue, result = self.make_result()
+        result.startTestRun()
+        self.assertEqual(
+            {'event':'startTestRun', 'result':result}, queue.get(False))
+        self.assertTrue(queue.empty())
+
+    def testStopTestRun(self):
+        queue, result = self.make_result()
+        result.stopTestRun()
+        self.assertEqual(
+            {'event':'stopTestRun', 'result':result}, queue.get(False))
+        self.assertTrue(queue.empty())
+
+
 class TestExtendedToOriginalResultDecoratorBase(TestCase):
 
     def make_26_result(self):
@@ -1558,13 +2352,13 @@ class TestNonAsciiResults(TestCase):
 
     def _test_external_case(self, testline, coding="ascii", modulelevel="",
             suffix=""):
-        """Create and run a test case in a separate module"""
+        """Create and run a test case in a seperate module"""
         self._setup_external_case(testline, coding, modulelevel, suffix)
         return self._run_external_case()
 
     def _setup_external_case(self, testline, coding="ascii", modulelevel="",
             suffix=""):
-        """Create a test case in a separate module"""
+        """Create a test case in a seperate module"""
         _, prefix, self.modname = self.id().rsplit(".", 2)
         self.dir = tempfile.mkdtemp(prefix=prefix, suffix=suffix)
         self.addCleanup(shutil.rmtree, self.dir)
@@ -1580,7 +2374,7 @@ class TestNonAsciiResults(TestCase):
             "        %s\n" % (coding, modulelevel, testline))
 
     def _run_external_case(self):
-        """Run the prepared test case in a separate module"""
+        """Run the prepared test case in a seperate module"""
         sys.path.insert(0, self.dir)
         self.addCleanup(sys.path.remove, self.dir)
         module = __import__(self.modname)
@@ -1589,11 +2383,6 @@ class TestNonAsciiResults(TestCase):
         self._run(stream, module.Test())
         return stream.getvalue()
 
-    def _silence_deprecation_warnings(self):
-        """Shut up DeprecationWarning for this test only"""
-        warnings.simplefilter("ignore", DeprecationWarning)
-        self.addCleanup(warnings.filters.remove, warnings.filters[0])
-
     def _get_sample_text(self, encoding="unicode_internal"):
         if encoding is None and str_is_unicode:
            encoding = "unicode_internal"
@@ -1635,7 +2424,7 @@ class TestNonAsciiResults(TestCase):
         if sys.version_info > (3, 3):
             return MatchesAny(Contains("FileExistsError: "),
                               Contains("PermissionError: "))
-        elif os.name != "nt" or sys.version_info < (2, 5):
+        elif os.name != "nt":
             return Contains(self._as_output("OSError: "))
         else:
             return Contains(self._as_output("WindowsError: "))
@@ -1699,15 +2488,6 @@ class TestNonAsciiResults(TestCase):
             "UnprintableError: <unprintable UnprintableError object>\n"),
             textoutput)
 
-    def test_string_exception(self):
-        """Raise a string rather than an exception instance if supported"""
-        if sys.version_info > (2, 6):
-            self.skip("No string exceptions in Python 2.6 or later")
-        elif sys.version_info > (2, 5):
-            self._silence_deprecation_warnings()
-        textoutput = self._test_external_case(testline="raise 'plain str'")
-        self.assertIn(self._as_output("\nplain str\n"), textoutput)
-
     def test_non_ascii_dirname(self):
         """Script paths in the traceback can be non-ascii"""
         text, raw = self._get_sample_text(sys.getfilesystemencoding())
@@ -1737,9 +2517,6 @@ class TestNonAsciiResults(TestCase):
 
     def test_syntax_error_import_binary(self):
         """Importing a binary file shouldn't break SyntaxError formatting"""
-        if sys.version_info < (2, 5):
-            # Python 2.4 assumes the file is latin-1 and tells you off
-            self._silence_deprecation_warnings()
         self._setup_external_case("import bad")
         f = open(os.path.join(self.dir, "bad.py"), "wb")
         try:
@@ -1772,13 +2549,18 @@ class TestNonAsciiResults(TestCase):
         self._write_module("bad", "iso-8859-5",
             "# coding: iso-8859-5\n%% = 0 # %s\n" % text)
         textoutput = self._run_external_case()
-        self.assertIn(self._as_output(_u(
-            #'bad.py", line 2\n'
-            '    %% = 0 # %s\n'
-            + ' ' * self._error_on_character +
-            '   ^\n'
-            'SyntaxError: ') %
-            (text,)), textoutput)
+        self.assertThat(
+            textoutput,
+            MatchesRegex(
+                self._as_output(_u(
+                #'bad.py", line 2\n'
+                '.*%% = 0 # %s\n'
+                + ' ' * self._error_on_character +
+                '\\s*\\^\n'
+                'SyntaxError:.*') %
+                (text,)),
+            re.MULTILINE | re.DOTALL)
+        )
 
     def test_syntax_error_line_euc_jp(self):
         """Syntax error on a euc_jp line shows the line decoded"""
@@ -1804,13 +2586,17 @@ class TestNonAsciiResults(TestCase):
         textoutput = self._setup_external_case("import bad")
         self._write_module("bad", "utf-8", _u("\ufeff^ = 0 # %s\n") % text)
         textoutput = self._run_external_case()
-        self.assertIn(self._as_output(_u(
-            'bad.py", line 1\n'
-            '    ^ = 0 # %s\n'
-            + ' ' * self._error_on_character +
-            '   ^\n'
-            'SyntaxError: ') %
-            text), textoutput)
+        self.assertThat(
+            textoutput,
+            MatchesRegex(
+                self._as_output(_u(
+                    '.*bad.py", line 1\n'
+                    '\\s*\\^ = 0 # %s\n'
+                    + ' ' * self._error_on_character +
+                    '\\s*\\^\n'
+                    'SyntaxError:.*') % text),
+                re.M | re.S)
+        )
 
 
 class TestNonAsciiResultsWithUnittest(TestNonAsciiResults):
@@ -2090,6 +2876,38 @@ class TestTagger(TestCase):
              ], result._events)
 
 
+class TestTimestampingStreamResult(TestCase):
+
+    def test_startTestRun(self):
+        result = TimestampingStreamResult(LoggingStreamResult())
+        result.startTestRun()
+        self.assertEqual([('startTestRun',)], result.targets[0]._events)
+
+    def test_stopTestRun(self):
+        result = TimestampingStreamResult(LoggingStreamResult())
+        result.stopTestRun()
+        self.assertEqual([('stopTestRun',)], result.targets[0]._events)
+
+    def test_status_no_timestamp(self):
+        result = TimestampingStreamResult(LoggingStreamResult())
+        result.status(test_id="A", test_status="B", test_tags="C",
+            runnable="D", file_name="E", file_bytes=b"F", eof=True,
+            mime_type="G", route_code="H")
+        events = result.targets[0]._events
+        self.assertThat(events, HasLength(1))
+        self.assertThat(events[0], HasLength(11))
+        self.assertEqual(
+            ("status", "A", "B", "C", "D", "E", b"F", True, "G", "H"),
+            events[0][:10])
+        self.assertNotEqual(None, events[0][10])
+        self.assertIsInstance(events[0][10], datetime.datetime)
+
+    def test_status_timestamp(self):
+        result = TimestampingStreamResult(LoggingStreamResult())
+        result.status(timestamp="F")
+        self.assertEqual("F", result.targets[0]._events[0][10])
+
+
 def test_suite():
     from unittest import TestLoader
     return TestLoader().loadTestsFromName(__name__)
diff --git a/lib/testtools/testtools/tests/test_testsuite.py b/lib/testtools/testtools/tests/test_testsuite.py
index 3fc837c..08cd777 100644
--- a/lib/testtools/testtools/tests/test_testsuite.py
+++ b/lib/testtools/testtools/tests/test_testsuite.py
@@ -4,17 +4,27 @@
 
 __metaclass__ = type
 
+import doctest
+from functools import partial
+import sys
 import unittest
+import unittest2
+
+from extras import try_import
 
 from testtools import (
     ConcurrentTestSuite,
+    ConcurrentStreamTestSuite,
     iterate_tests,
     PlaceHolder,
+    TestByTestResult,
     TestCase,
     )
-from testtools.helpers import try_import
+from testtools.compat import _b, _u
+from testtools.matchers import DocTestMatches
 from testtools.testsuite import FixtureSuite, iterate_tests, sorted_tests
 from testtools.tests.helpers import LoggingResult
+from testtools.testresult.doubles import StreamResult as LoggingStream
 
 FunctionFixture = try_import('fixtures.FunctionFixture')
 
@@ -26,8 +36,23 @@ class Sample(TestCase):
     def test_method2(self):
         pass
 
+
 class TestConcurrentTestSuiteRun(TestCase):
 
+    def test_broken_test(self):
+        log = []
+        def on_test(test, status, start_time, stop_time, tags, details):
+            log.append((test.id(), status, set(details.keys())))
+        class BrokenTest(object):
+            # Simple break - no result parameter to run()
+            def __call__(self):
+                pass
+            run = __call__
+        original_suite = unittest.TestSuite([BrokenTest()])
+        suite = ConcurrentTestSuite(original_suite, self.split_suite)
+        suite.run(TestByTestResult(on_test))
+        self.assertEqual([('broken-runner', 'error', set(['traceback']))], log)
+
     def test_trivial(self):
         log = []
         result = LoggingResult(log)
@@ -68,8 +93,149 @@ class TestConcurrentTestSuiteRun(TestCase):
         self.assertNotEqual([], result_log)
 
     def split_suite(self, suite):
-        tests = list(iterate_tests(suite))
-        return tests[0], tests[1]
+        return list(iterate_tests(suite))
+
+
+class TestConcurrentStreamTestSuiteRun(TestCase):
+
+    def test_trivial(self):
+        result = LoggingStream()
+        test1 = Sample('test_method1')
+        test2 = Sample('test_method2')
+        cases = lambda:[(test1, '0'), (test2, '1')]
+        suite = ConcurrentStreamTestSuite(cases)
+        suite.run(result)
+        def freeze(set_or_none):
+            if set_or_none is None:
+                return set_or_none
+            return frozenset(set_or_none)
+        # Ignore event order: we're testing the code is all glued together,
+        # which just means we can pump events through and they get route codes
+        # added appropriately.
+        self.assertEqual(set([
+            ('status',
+             'testtools.tests.test_testsuite.Sample.test_method1',
+             'inprogress',
+             None,
+             True,
+             None,
+             None,
+             False,
+             None,
+             '0',
+             None,
+             ),
+            ('status',
+             'testtools.tests.test_testsuite.Sample.test_method1',
+             'success',
+             frozenset(),
+             True,
+             None,
+             None,
+             False,
+             None,
+             '0',
+             None,
+             ),
+            ('status',
+             'testtools.tests.test_testsuite.Sample.test_method2',
+             'inprogress',
+             None,
+             True,
+             None,
+             None,
+             False,
+             None,
+             '1',
+             None,
+             ),
+            ('status',
+             'testtools.tests.test_testsuite.Sample.test_method2',
+             'success',
+             frozenset(),
+             True,
+             None,
+             None,
+             False,
+             None,
+             '1',
+             None,
+             ),
+            ]), set(event[0:3] + (freeze(event[3]),) + event[4:10] + (None,)
+                for event in result._events))
+
+    def test_broken_runner(self):
+        # If the object called breaks, the stream is informed about it
+        # regardless.
+        class BrokenTest(object):
+            # broken - no result parameter!
+            def __call__(self):
+                pass
+            def run(self):
+                pass
+        result = LoggingStream()
+        cases = lambda:[(BrokenTest(), '0')]
+        suite = ConcurrentStreamTestSuite(cases)
+        suite.run(result)
+        events = result._events
+        # Check the traceback loosely.
+        self.assertThat(events[1][6].decode('utf8'), DocTestMatches("""\
+Traceback (most recent call last):
+  File "...testtools/testsuite.py", line ..., in _run_test
+    test.run(process_result)
+TypeError: run() takes ...1 ...argument...2...given...
+""", doctest.ELLIPSIS))
+        events = [event[0:10] + (None,) for event in events]
+        events[1] = events[1][:6] + (None,) + events[1][7:]
+        self.assertEqual([
+            ('status', "broken-runner-'0'", 'inprogress', None, True, None, None, False, None, _u('0'), None),
+            ('status', "broken-runner-'0'", None, None, True, 'traceback', None,
+             True,
+             'text/x-traceback; charset="utf8"; language="python"',
+             '0',
+             None),
+             ('status', "broken-runner-'0'", 'fail', set(), True, None, None, False, None, _u('0'), None)
+            ], events)
+
+    def split_suite(self, suite):
+        tests = list(enumerate(iterate_tests(suite)))
+        return [(test, _u(str(pos))) for pos, test in tests]
+
+    def test_setupclass_skip(self):
+        # We should support setupclass skipping using cls.skipException.
+        # Because folk have used that.
+        class Skips(TestCase):
+            @classmethod
+            def setUpClass(cls):
+                raise cls.skipException('foo')
+            def test_notrun(self):
+                pass
+        # Test discovery uses the default suite from unittest2 (unless users
+        # deliberately change things, in which case they keep both pieces).
+        suite = unittest2.TestSuite([Skips("test_notrun")])
+        log = []
+        result = LoggingResult(log)
+        suite.run(result)
+        self.assertEqual(['addSkip'], [item[0] for item in log])
+
+    def test_setupclass_upcall(self):
+        # Note that this is kindof-a-case-test, kindof-suite, because
+        # setUpClass is linked between them.
+        class Simples(TestCase):
+            @classmethod
+            def setUpClass(cls):
+                super(Simples, cls).setUpClass()
+            def test_simple(self):
+                pass
+        # Test discovery uses the default suite from unittest2 (unless users
+        # deliberately change things, in which case they keep both pieces).
+        suite = unittest2.TestSuite([Simples("test_simple")])
+        log = []
+        result = LoggingResult(log)
+        suite.run(result)
+        self.assertEqual(
+            ['startTest', 'addSuccess', 'stopTest'],
+            [item[0] for item in log])
 
 
 class TestFixtureSuite(TestCase):
@@ -93,6 +259,19 @@ class TestFixtureSuite(TestCase):
         suite.run(LoggingResult([]))
         self.assertEqual(['setUp', 1, 2, 'tearDown'], log)
 
+    def test_fixture_suite_sort(self):
+        log = []
+        class Sample(TestCase):
+            def test_one(self):
+                log.append(1)
+            def test_two(self):
+                log.append(2)
+        fixture = FunctionFixture(
+            lambda: log.append('setUp'),
+            lambda fixture: log.append('tearDown'))
+        suite = FixtureSuite(fixture, [Sample('test_one'), Sample('test_one')])
+        self.assertRaises(ValueError, suite.sort_tests)
+
 
 class TestSortedTests(TestCase):
 
@@ -122,6 +301,13 @@ class TestSortedTests(TestCase):
         suite = sorted_tests(unittest.TestSuite([b, a]))
         self.assertEqual([a, b], list(iterate_tests(suite)))
 
+    def test_duplicate_simple_suites(self):
+        a = PlaceHolder('a')
+        b = PlaceHolder('b')
+        c = PlaceHolder('a')
+        self.assertRaises(
+            ValueError, sorted_tests, unittest.TestSuite([a, b, c]))
+
 
 def test_suite():
     from unittest import TestLoader
diff --git a/lib/testtools/testtools/tests/test_with_with.py b/lib/testtools/testtools/tests/test_with_with.py
index e06adeb..277b4d9 100644
--- a/lib/testtools/testtools/tests/test_with_with.py
+++ b/lib/testtools/testtools/tests/test_with_with.py
@@ -11,6 +11,7 @@ from testtools import (
 from testtools.matchers import (
     AfterPreprocessing,
     Equals,
+    EndsWith,
     )
 
 
@@ -71,3 +72,22 @@ class TestExpectedException(TestCase):
     def test_pass_on_raise_any_message(self):
         with ExpectedException(ValueError):
             raise ValueError('whatever')
+    
+    def test_annotate(self):
+        def die():
+            with ExpectedException(ValueError, msg="foo"):
+                pass
+        exc = self.assertRaises(AssertionError, die)
+        self.assertThat(exc.args[0], EndsWith(': foo'))
+
+    def test_annotated_matcher(self):
+        def die():
+            with ExpectedException(ValueError, 'bar', msg="foo"):
+                pass
+        exc = self.assertRaises(AssertionError, die)
+        self.assertThat(exc.args[0], EndsWith(': foo'))
+
+
+def test_suite():
+    from unittest import TestLoader
+    return TestLoader().loadTestsFromName(__name__)
diff --git a/lib/testtools/testtools/testsuite.py b/lib/testtools/testtools/testsuite.py
index 67ace56..ff8f878 100644
--- a/lib/testtools/testtools/testsuite.py
+++ b/lib/testtools/testtools/testsuite.py
@@ -5,16 +5,20 @@
 __metaclass__ = type
 __all__ = [
   'ConcurrentTestSuite',
+  'ConcurrentStreamTestSuite',
+  'filter_by_ids',
   'iterate_tests',
   'sorted_tests',
   ]
 
-from testtools.helpers import safe_hasattr, try_imports
-
-Queue = try_imports(['Queue.Queue', 'queue.Queue'])
-
+import sys
 import threading
 import unittest
+import unittest2
+
+from extras import safe_hasattr, try_imports
+
+Queue = try_imports(['Queue.Queue', 'queue.Queue'])
 
 import testtools
 
@@ -31,7 +35,7 @@ def iterate_tests(test_suite_or_case):
                 yield subtest
 
 
-class ConcurrentTestSuite(unittest.TestSuite):
+class ConcurrentTestSuite(unittest2.TestSuite):
     """A TestSuite whose run() calls out to a concurrency strategy."""
 
     def __init__(self, suite, make_tests, wrap_result=None):
@@ -98,12 +102,103 @@ class ConcurrentTestSuite(unittest.TestSuite):
 
     def _run_test(self, test, process_result, queue):
         try:
-            test.run(process_result)
+            try:
+                test.run(process_result)
+            except Exception as e:
+                # The run logic itself failed.
+                case = testtools.ErrorHolder(
+                    "broken-runner",
+                    error=sys.exc_info())
+                case.run(process_result)
         finally:
             queue.put(test)
 
 
-class FixtureSuite(unittest.TestSuite):
+class ConcurrentStreamTestSuite(object):
+    """A TestSuite whose run() parallelises."""
+
+    def __init__(self, make_tests):
+        """Create a ConcurrentTestSuite to execute tests returned by make_tests.
+
+        :param make_tests: A helper function that should return some number
+            of concurrently executable test suite / test case objects.
+            make_tests must take no parameters and return an iterable of
+            tuples. Each tuple must be of the form (case, route_code), where
+            case is a TestCase-like object with a run(result) method, and
+            route_code is either None or a unicode string.
+        """
+        super(ConcurrentStreamTestSuite, self).__init__()
+        self.make_tests = make_tests
+
+    def run(self, result):
+        """Run the tests concurrently.
+
+        This calls out to the provided make_tests helper to determine the
+        concurrency to use and to assign routing codes to each worker.
+
+        ConcurrentTestSuite provides no special mechanism to stop the tests
+        returned by make_tests, it is up to the made tests to honour the
+        shouldStop attribute on the result object they are run with, which will
+        be set if the test run is to be aborted.
+
+        The tests are run with an ExtendedToStreamDecorator wrapped around a
+        StreamToQueue instance. ConcurrentStreamTestSuite dequeues events from
+        the queue and forwards them to result. Tests can therefore be either
+        original unittest tests (or compatible tests), or new tests that emit
+        StreamResult events directly.
+
+        :param result: A StreamResult instance. The caller is responsible for
+            calling startTestRun on this instance prior to invoking suite.run,
+            and stopTestRun subsequent to the run method returning.
+        """
+        tests = self.make_tests()
+        try:
+            threads = {}
+            queue = Queue()
+            for test, route_code in tests:
+                to_queue = testtools.StreamToQueue(queue, route_code)
+                process_result = testtools.ExtendedToStreamDecorator(
+                    testtools.TimestampingStreamResult(to_queue))
+                runner_thread = threading.Thread(
+                    target=self._run_test,
+                    args=(test, process_result, route_code))
+                threads[to_queue] = runner_thread, process_result
+                runner_thread.start()
+            while threads:
+                event_dict = queue.get()
+                event = event_dict.pop('event')
+                if event == 'status':
+                    result.status(**event_dict)
+                elif event == 'stopTestRun':
+                    thread = threads.pop(event_dict['result'])[0]
+                    thread.join()
+                elif event == 'startTestRun':
+                    pass
+                else:
+                    raise ValueError('unknown event type %r' % (event,))
+        except:
+            for thread, process_result in threads.values():
+                # Signal to each TestControl in the ExtendedToStreamDecorator
+                # that the thread should stop running tests and cleanup
+                process_result.stop()
+            raise
+
+    def _run_test(self, test, process_result, route_code):
+        process_result.startTestRun()
+        try:
+            try:
+                test.run(process_result)
+            except Exception as e:
+                # The run logic itself failed.
+                case = testtools.ErrorHolder(
+                    "broken-runner-'%s'" % (route_code,),
+                    error=sys.exc_info())
+                case.run(process_result)
+        finally:
+            process_result.stopTestRun()
+
+
+class FixtureSuite(unittest2.TestSuite):
 
     def __init__(self, fixture, tests):
         super(FixtureSuite, self).__init__(tests)
@@ -147,8 +242,77 @@ def _flatten_tests(suite_or_case, unpack_outer=False):
         return [(suite_id, suite_or_case)]
 
 
+def filter_by_ids(suite_or_case, test_ids):
+    """Remove tests from suite_or_case where their id is not in test_ids.
+    
+    :param suite_or_case: A test suite or test case.
+    :param test_ids: Something that supports the __contains__ protocol.
+    :return: suite_or_case, unless suite_or_case was a case that itself
+        fails the predicate when it will return a new unittest.TestSuite with
+        no contents.
+
+    This helper exists to provide backwards compatability with older versions
+    of Python (currently all versions :)) that don't have a native
+    filter_by_ids() method on Test(Case|Suite).
+
+    For subclasses of TestSuite, filtering is done by:
+        - attempting to call suite.filter_by_ids(test_ids)
+        - if there is no method, iterating the suite and identifying tests to
+          remove, then removing them from _tests, manually recursing into
+          each entry.
+
+    For objects with an id() method - TestCases, filtering is done by:
+        - attempting to return case.filter_by_ids(test_ids)
+        - if there is no such method, checking for case.id() in test_ids
+          and returning case if it is, or TestSuite() if it is not.
+
+    For anything else, it is not filtered - it is returned as-is.
+
+    To provide compatability with this routine for a custom TestSuite, just
+    define a filter_by_ids() method that will return a TestSuite equivalent to
+    the original minus any tests not in test_ids.
+    Similarly to provide compatability for a custom TestCase that does
+    something unusual define filter_by_ids to return a new TestCase object
+    that will only run test_ids that are in the provided container. If none
+    would run, return an empty TestSuite().
+
+    The contract for this function does not require mutation - each filtered
+    object can choose to return a new object with the filtered tests. However
+    because existing custom TestSuite classes in the wild do not have this
+    method, we need a way to copy their state correctly which is tricky:
+    thus the backwards-compatible code paths attempt to mutate in place rather
+    than guessing how to reconstruct a new suite.
+    """
+    # Compatible objects
+    if safe_hasattr(suite_or_case, 'filter_by_ids'):
+        return suite_or_case.filter_by_ids(test_ids)
+    # TestCase objects.
+    if safe_hasattr(suite_or_case, 'id'):
+        if suite_or_case.id() in test_ids:
+            return suite_or_case
+        else:
+            return unittest.TestSuite()
+    # Standard TestSuites or derived classes [assumed to be mutable].
+    if isinstance(suite_or_case, unittest.TestSuite):
+        filtered = []
+        for item in suite_or_case:
+            filtered.append(filter_by_ids(item, test_ids))
+        suite_or_case._tests[:] = filtered
+    # Everything else:
+    return suite_or_case
+
+
 def sorted_tests(suite_or_case, unpack_outer=False):
     """Sort suite_or_case while preserving non-vanilla TestSuites."""
+    # Duplicate test id can induce TypeError in Python 3.3.
+    # Detect the duplicate test id, raise exception when found.
+    seen = set()
+    for test_case in iterate_tests(suite_or_case):
+        test_id = test_case.id()
+        if test_id not in seen:
+            seen.add(test_id)
+        else:
+            raise ValueError('Duplicate test id detected: %s' % (test_id,))
     tests = _flatten_tests(suite_or_case, unpack_outer=unpack_outer)
     tests.sort()
     return unittest.TestSuite([test for (sort_key, test) in tests])
diff --git a/third_party/pexpect/.gitignore b/third_party/pexpect/.gitignore
new file mode 100644
index 0000000..8777ca7
--- /dev/null
+++ b/third_party/pexpect/.gitignore
@@ -0,0 +1,9 @@
+*.pyc
+doc/_build
+tests/log
+build/
+dist/
+MANIFEST
+*~
+.coverage*
+htmlcov
diff --git a/third_party/pexpect/.travis.yml b/third_party/pexpect/.travis.yml
new file mode 100644
index 0000000..51c967d
--- /dev/null
+++ b/third_party/pexpect/.travis.yml
@@ -0,0 +1,23 @@
+language: python
+
+python:
+  - 2.7
+  - 3.3
+  - 3.4
+  - pypy
+
+install:
+  - export PYTHONIOENCODING=UTF8
+  - pip install coveralls pytest-cov ptyprocess
+
+script:
+    - ./tools/display-sighandlers.py
+    - ./tools/display-terminalinfo.py
+    - py.test --cov pexpect --cov-config .coveragerc
+
+after_success:
+  - coverage combine
+  - coveralls
+
+# Use new Travis stack, should be faster
+sudo: false
diff --git a/third_party/pexpect/ANSI.py b/third_party/pexpect/ANSI.py
new file mode 100644
index 0000000..ca1673b
--- /dev/null
+++ b/third_party/pexpect/ANSI.py
@@ -0,0 +1,7 @@
+import warnings
+
+warnings.warn("This module has been moved to pexpect.ANSI, please update imports.",
+                ImportWarning)
+del warnings
+
+from pexpect.ANSI import *  # analysis:ignore
\ No newline at end of file
diff --git a/third_party/pexpect/DEVELOPERS.rst b/third_party/pexpect/DEVELOPERS.rst
new file mode 100644
index 0000000..bf2bb9f
--- /dev/null
+++ b/third_party/pexpect/DEVELOPERS.rst
@@ -0,0 +1,12 @@
+To run the tests, use `py.test <http://pytest.org/latest/>`_::
+
+    py.test tests
+
+The tests are all located in the tests/ directory. To add a new unit
+test all you have to do is create the file in the tests/ directory with a
+filename in this format::
+
+    test_*.py
+
+New test case classes may wish to inherit from ``PexpectTestCase.PexpectTestCase``
+in the tests directory, which sets up some convenient functionality.
diff --git a/third_party/pexpect/FSM.py b/third_party/pexpect/FSM.py
new file mode 100644
index 0000000..4e1ab49
--- /dev/null
+++ b/third_party/pexpect/FSM.py
@@ -0,0 +1,7 @@
+import warnings
+
+warnings.warn("This module has been moved to pexpect.FSM, please update imports.",
+                ImportWarning)
+del warnings
+
+from pexpect.FSM import *  # analysis:ignore
\ No newline at end of file
diff --git a/third_party/pexpect/LICENSE b/third_party/pexpect/LICENSE
new file mode 100644
index 0000000..9e10acb
--- /dev/null
+++ b/third_party/pexpect/LICENSE
@@ -0,0 +1,19 @@
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2013-2014, Pexpect development team
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
diff --git a/third_party/pexpect/MANIFEST.in b/third_party/pexpect/MANIFEST.in
new file mode 100644
index 0000000..91fd411
--- /dev/null
+++ b/third_party/pexpect/MANIFEST.in
@@ -0,0 +1,8 @@
+recursive-include doc *
+prune doc/_build
+recursive-include examples *
+include README LICENSE INSTALL
+include setup.py pexpect.py fdpexpect.py pxssh.py screen.py ANSI.py FSM.py
+include test.env tools/testall.py
+recursive-include tests *
+global-exclude __pycache__ *.pyc *~
diff --git a/third_party/pexpect/README.rst b/third_party/pexpect/README.rst
new file mode 100644
index 0000000..dde7ade
--- /dev/null
+++ b/third_party/pexpect/README.rst
@@ -0,0 +1,53 @@
+.. image:: https://travis-ci.org/pexpect/pexpect.png?branch=master
+   :target: https://travis-ci.org/pexpect/pexpect
+   :align: right
+   :alt: Build status
+
+Pexpect is a Pure Python Expect-like module
+
+Pexpect makes Python a better tool for controlling other applications.
+
+Pexpect is a pure Python module for spawning child applications; controlling
+them; and responding to expected patterns in their output. Pexpect works like
+Don Libes' Expect. Pexpect allows your script to spawn a child application and
+control it as if a human were typing commands.
+
+Pexpect can be used for automating interactive applications such as ssh, ftp,
+passwd, telnet, etc. It can be used to a automate setup scripts for duplicating
+software package installations on different servers. It can be used for
+automated software testing. Pexpect is in the spirit of Don Libes' Expect, but
+Pexpect is pure Python. Unlike other Expect-like modules for Python, Pexpect
+does not require TCL or Expect nor does it require C extensions to be compiled.
+It should work on any platform that supports the standard Python pty module.
+The Pexpect interface was designed to be easy to use.
+
+If you want to work with the development version of the source code then please
+read the DEVELOPERS.rst document in the root of the source code tree.
+
+Free, open source, and all that good stuff.
+
+You can install Pexpect using pip::
+
+    pip install pexpect
+
+`Docs on ReadTheDocs <http://pexpect.readthedocs.org/>`_
+
+PEXPECT LICENSE
+
+    http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2013-2014, Pexpect development team
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+This license is approved by the OSI and FSF as GPL-compatible.
diff --git a/third_party/pexpect/doc/FAQ.rst b/third_party/pexpect/doc/FAQ.rst
new file mode 100644
index 0000000..bec1c35
--- /dev/null
+++ b/third_party/pexpect/doc/FAQ.rst
@@ -0,0 +1,136 @@
+FAQ
+===
+
+**Q: Why don't shell pipe and redirect (| and >) work when I spawn a command?**
+
+A: Remember that Pexpect does NOT interpret shell meta characters such as
+redirect, pipe, or wild cards (``>``, ``|``, or ``*``). That's done by a shell not
+the command you are spawning. This is a common mistake. If you want to run a
+command and pipe it through another command then you must also start a shell.
+For example::
+
+    child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > log_list.txt"')
+    child.expect(pexpect.EOF)
+
+The second form of spawn (where you pass a list of arguments) is useful in
+situations where you wish to spawn a command and pass it its own argument list.
+This can make syntax more clear. For example, the following is equivalent to the
+previous example::
+
+    shell_cmd = 'ls -l | grep LOG > log_list.txt'
+    child = pexpect.spawn('/bin/bash', ['-c', shell_cmd])
+    child.expect(pexpect.EOF)
+
+**Q: Isn't there already a Python Expect?**
+
+A: Yes, there are several of them. They usually require you to compile C.
+I wanted something that was pure Python and preferably a single module
+that was simple to install. I also wanted something that was easy to use.
+This pure Python expect only became possible with the introduction of
+the pty module in the standard Python library. Previously, C extensions
+were required.
+
+**Q: The `before` and `after` properties sound weird.**
+
+A: This is how the -B and -A options in grep works, so that made it
+easier for me to remember. Whatever makes my life easier is what's best.
+Originally I was going to model Pexpect after Expect, but then I found
+that I didn't actually like the way Expect did some things. It was more
+confusing. The `after` property can be a little confusing at first,
+because it will actually include the matched string. The `after` means
+after the point of match, not after the matched string.
+
+**Q: Why not just use Expect?**
+
+A: I love it. It's great. I has bailed me out of some real jams, but I
+wanted something that would do 90% of what I need from Expect; be 10% of
+the size; and allow me to write my code in Python instead of TCL.
+Pexpect is not nearly as big as Expect, but Pexpect does everything I
+have ever used Expect for.
+
+.. _whynotpipe:
+
+**Q: Why not just use a pipe (popen())?**
+
+A: A pipe works fine for getting the output to non-interactive programs.
+If you just want to get the output from ls, uname, or ping then this
+works. Pipes do not work very well for interactive programs and pipes
+will almost certainly fail for most applications that ask for passwords
+such as telnet, ftp, or ssh.
+
+There are two reasons for this.
+
+* First an application may bypass stdout and print directly to its
+  controlling TTY. Something like SSH will do this when it asks you for
+  a password. This is why you cannot redirect the password prompt because
+  it does not go through stdout or stderr.
+
+* The second reason is because most applications are built using the C
+  Standard IO Library (anything that uses ``#include <stdio.h>``). One
+  of the features of the stdio library is that it buffers all input and
+  output. Normally output is line buffered when a program is printing to
+  a TTY (your terminal screen). Everytime the program prints a line-feed
+  the currently buffered data will get printed to your screen. The
+  problem comes when you connect a pipe. The stdio library is smart and
+  can tell that it is printing to a pipe instead of a TTY. In that case
+  it switches from line buffer mode to block buffered. In this mode the
+  currently buffered data is flushed when the buffer is full. This
+  causes most interactive programs to deadlock. Block buffering is more
+  efficient when writing to disks and pipes. Take the situation where a
+  program prints a message ``"Enter your user name:\n"`` and then waits
+  for you type type something. In block buffered mode, the stdio library
+  will not put the message into the pipe even though a linefeed is
+  printed. The result is that you never receive the message, yet the
+  child application will sit and wait for you to type a response. Don't
+  confuse the stdio lib's buffer with the pipe's buffer. The pipe buffer
+  is another area that can cause problems. You could flush the input
+  side of a pipe, whereas you have no control over the stdio library buffer.
+
+More information: the Standard IO library has three states for a
+``FILE *``. These are: _IOFBF for block buffered; _IOLBF for line buffered;
+and _IONBF for unbuffered. The STDIO lib will use block buffering when
+talking to a block file descriptor such as a pipe. This is usually not
+helpful for interactive programs. Short of recompiling your program to
+include fflush() everywhere or recompiling a custom stdio library there
+is not much a controlling application can do about this if talking over
+a pipe.
+
+The program may have put data in its output that remains unflushed
+because the output buffer is not full; then the program will go and
+deadlock while waiting for input -- because you never send it any
+because you are still waiting for its output (still stuck in the STDIO's
+output buffer).
+
+The answer is to use a pseudo-tty. A TTY device will force line
+buffering (as opposed to block buffering). Line buffering means that you
+will get each line when the child program sends a line feed. This
+corresponds to the way most interactive programs operate -- send a line
+of output then wait for a line of input.
+
+I put "answer" in quotes because it's ugly solution and because there is
+no POSIX standard for pseudo-TTY devices (even though they have a TTY
+standard...). What would make more sense to me would be to have some way
+to set a mode on a file descriptor so that it will tell the STDIO to be
+line-buffered. I have investigated, and I don't think there is a way to
+set the buffered state of a child process. The STDIO Library does not
+maintain any external state in the kernel or whatnot, so I don't think
+there is any way for you to alter it. I'm not quite sure how this
+line-buffered/block-buffered state change happens internally in the
+STDIO library. I think the STDIO lib looks at the file descriptor and
+decides to change behavior based on whether it's a TTY or a block file
+(see isatty()).
+
+I hope that this qualifies as helpful. Don't use a pipe to control
+another application.
+
+**Q: Can I do screen scraping with this thing?**
+
+A: That depends. If your application just does line-oriented output then
+this is easy. If it does screen-oriented output then it may work, but it
+could be hard. For example, trying to scrape data from the 'top' command
+would be hard. The top command repaints the text window.
+
+I am working on an ANSI / VT100 terminal emulator that will have methods
+to get characters from an arbitrary X,Y coordinate of the virtual screen.
+It works and you can play with it (see :mod:`pexpect.ANSI`), but I have
+no working examples at this time. 
diff --git a/third_party/pexpect/doc/Makefile b/third_party/pexpect/doc/Makefile
new file mode 100644
index 0000000..ced8a68
--- /dev/null
+++ b/third_party/pexpect/doc/Makefile
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  texinfo    to make Texinfo files"
+	@echo "  info       to make Texinfo files and run them through makeinfo"
+	@echo "  gettext    to make PO message catalogs"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Pexpect.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Pexpect.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/Pexpect"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Pexpect"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo
+	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+	@echo "Run \`make' in that directory to run these through makeinfo" \
+	      "(use \`make info' here to do that automatically)."
+
+info:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo "Running Texinfo files through makeinfo..."
+	make -C $(BUILDDIR)/texinfo info
+	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+	@echo
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/third_party/pexpect/doc/api/ANSI.rst b/third_party/pexpect/doc/api/ANSI.rst
new file mode 100644
index 0000000..064563d
--- /dev/null
+++ b/third_party/pexpect/doc/api/ANSI.rst
@@ -0,0 +1,14 @@
+ANSI - ANSI (VT100) terminal emulator
+=====================================
+
+.. automodule:: pexpect.ANSI
+
+.. autoclass:: term
+   :show-inheritance:
+
+.. autoclass:: ANSI
+   :show-inheritance:
+
+   .. automethod:: write_ch
+   .. automethod:: write
+   .. automethod:: process
\ No newline at end of file
diff --git a/third_party/pexpect/doc/api/fdpexpect.rst b/third_party/pexpect/doc/api/fdpexpect.rst
new file mode 100644
index 0000000..8321454
--- /dev/null
+++ b/third_party/pexpect/doc/api/fdpexpect.rst
@@ -0,0 +1,22 @@
+fdpexpect - use pexpect with a file descriptor
+==============================================
+
+.. automodule:: pexpect.fdpexpect
+
+fdspawn class
+-------------
+
+.. autoclass:: fdspawn
+   :show-inheritance:
+
+   .. automethod:: __init__
+   .. automethod:: isalive
+   .. automethod:: close
+
+   .. note::
+      :class:`fdspawn` inherits all of the methods of :class:`~pexpect.spawn`, 
+      but not all of them can be used, especially if the file descriptor is not
+      a terminal. Some methods may do nothing (e.g. :meth:`~fdspawn.kill`), while
+      others will raise an exception (e.g. :meth:`~fdspawn.terminate`).
+      This behaviour might be made more consistent in the future, so try to
+      avoid relying on it.
\ No newline at end of file
diff --git a/third_party/pexpect/doc/api/index.rst b/third_party/pexpect/doc/api/index.rst
new file mode 100644
index 0000000..1a6a6ae
--- /dev/null
+++ b/third_party/pexpect/doc/api/index.rst
@@ -0,0 +1,12 @@
+API documentation
+=================
+
+.. toctree::
+   :maxdepth: 2
+
+   pexpect
+   fdpexpect
+   replwrap
+   pxssh
+   screen
+   ANSI
diff --git a/third_party/pexpect/doc/api/pexpect.rst b/third_party/pexpect/doc/api/pexpect.rst
new file mode 100644
index 0000000..565f0ef
--- /dev/null
+++ b/third_party/pexpect/doc/api/pexpect.rst
@@ -0,0 +1,111 @@
+Core pexpect components
+=======================
+
+.. automodule:: pexpect
+
+spawn class
+-----------
+
+.. autoclass:: spawn
+
+   .. automethod:: __init__
+   .. automethod:: expect
+   .. automethod:: expect_exact
+   .. automethod:: expect_list
+   .. automethod:: compile_pattern_list
+   .. automethod:: send
+   .. automethod:: sendline
+   .. automethod:: write
+   .. automethod:: writelines
+   .. automethod:: sendcontrol
+   .. automethod:: sendeof
+   .. automethod:: sendintr
+   .. automethod:: read
+   .. automethod:: readline
+   .. automethod:: read_nonblocking
+   .. automethod:: eof
+   .. automethod:: interact
+
+   .. attribute:: logfile
+                  logfile_read
+                  logfile_send
+
+      Set these to a Python file object (or :data:`sys.stdout`) to log all
+      communication, data read from the child process, or data sent to the child
+      process.
+
+      .. note::
+
+         With a :class:`spawn` instance, the log files should be open for
+         writing binary data. With a :class:`spawnu` instance, they should
+         be open for writing unicode text.
+
+Controlling the child process
+`````````````````````````````
+
+.. class:: spawn
+
+   .. automethod:: kill
+   .. automethod:: terminate
+   .. automethod:: isalive
+   .. automethod:: wait
+   .. automethod:: close
+   .. automethod:: getwinsize
+   .. automethod:: setwinsize
+   .. automethod:: getecho
+   .. automethod:: setecho
+   .. automethod:: waitnoecho
+
+   .. attribute:: pid
+
+      The process ID of the child process.
+
+   .. attribute:: child_fd
+
+      The file descriptor used to communicate with the child process.
+
+.. _unicode:
+
+Handling unicode
+````````````````
+
+For backwards compatibility, :class:`spawn` can handle some Unicode: its
+send methods will encode arbitrary unicode as UTF-8 before sending it to the
+child process, and its expect methods can accept ascii-only unicode strings.
+However, for a proper unicode API to a subprocess, use this subclass:
+
+.. autoclass:: spawnu
+   :show-inheritance:
+
+There is also a :func:`runu` function, the unicode counterpart to :func:`run`.
+
+.. note::
+
+   Unicode handling with pexpect works the same way on Python 2 and 3, despite
+   the difference in names. I.e.:
+
+   - :class:`spawn` works with ``str`` on Python 2, and :class:`bytes` on Python 3,
+   - :class:`spawnu` works with ``unicode`` on Python 2, and :class:`str` on Python 3.
+
+run function
+------------
+
+.. autofunction:: run
+
+.. autofunction:: runu
+
+Exceptions
+----------
+
+.. autoclass:: EOF
+
+.. autoclass:: TIMEOUT
+
+.. autoclass:: ExceptionPexpect
+
+Utility functions
+-----------------
+
+.. autofunction:: which
+
+.. autofunction:: split_command_line
diff --git a/third_party/pexpect/doc/api/pxssh.rst b/third_party/pexpect/doc/api/pxssh.rst
new file mode 100644
index 0000000..b947f4b
--- /dev/null
+++ b/third_party/pexpect/doc/api/pxssh.rst
@@ -0,0 +1,34 @@
+pxssh - control an SSH session
+==============================
+
+.. automodule:: pexpect.pxssh
+
+.. autoclass:: ExceptionPxssh
+
+pxssh class
+-----------
+
+.. autoclass:: pxssh
+
+   .. automethod:: __init__
+
+   .. attribute:: PROMPT
+
+      The regex pattern to search for to find the prompt. If you call :meth:`login`
+      with ``auto_prompt_reset=False``, you must set this attribute manually.
+
+   .. attribute:: force_password
+
+      If this is set to True, public key authentication is disabled, forcing the
+      server to ask for a password. Note that the sysadmin can disable password
+      logins, in which case this won't work.
+
+   .. attribute:: options
+
+      The dictionary of user specified SSH options, eg, ``options = dict(StrictHostKeyChecking="no", UserKnownHostsFile="/dev/null")``
+
+   .. automethod:: login
+   .. automethod:: logout
+   .. automethod:: prompt
+   .. automethod:: sync_original_prompt
+   .. automethod:: set_unique_prompt
diff --git a/third_party/pexpect/doc/api/replwrap.rst b/third_party/pexpect/doc/api/replwrap.rst
new file mode 100644
index 0000000..bf44a94
--- /dev/null
+++ b/third_party/pexpect/doc/api/replwrap.rst
@@ -0,0 +1,26 @@
+replwrap - Control read-eval-print-loops
+========================================
+
+.. automodule:: pexpect.replwrap
+
+.. versionadded:: 3.3
+
+.. autoclass:: REPLWrapper
+
+   .. automethod:: run_command
+
+.. data:: PEXPECT_PROMPT
+
+   A string that can be used as a prompt, and is unlikely to be found in output.
+
+Using the objects above, it is easy to wrap a REPL. For instance, to use a
+Python shell::
+
+    py = REPLWrapper("python", ">>> ", "import sys; sys.ps1={!r}; sys.ps2={!r}")
+    py.run_command("4+7")
+
+Convenience functions are provided for Python and bash shells:
+
+.. autofunction:: python
+
+.. autofunction:: bash
diff --git a/third_party/pexpect/doc/api/screen.rst b/third_party/pexpect/doc/api/screen.rst
new file mode 100644
index 0000000..8268fb9
--- /dev/null
+++ b/third_party/pexpect/doc/api/screen.rst
@@ -0,0 +1,10 @@
+screen - manage a virtual 'screen'
+==================================
+
+.. automodule:: pexpect.screen
+
+.. autoclass:: screen
+   :members:
+
+   .. automethod:: __init__
+   .. automethod:: __str__
\ No newline at end of file
diff --git a/third_party/pexpect/doc/clean.css b/third_party/pexpect/doc/clean.css
new file mode 100644
index 0000000..e8d98dd
--- /dev/null
+++ b/third_party/pexpect/doc/clean.css
@@ -0,0 +1,103 @@
+
+body {
+	margin:0px;
+	padding:0px;
+	font-family:verdana, arial, helvetica, sans-serif; 
+	color:#333;
+	background-color:white;
+	}
+pre {
+  background: #eeeeee;
+  border: 1px solid #888888;
+  color: black;
+  padding: 1em;
+  white-space: pre;
+}
+h1 {
+	margin:5px 0px 5px 0px;
+	padding:0px;
+	font-size:20px;
+	line-height:28px;
+	font-weight:900;
+	color:#44f;
+	}
+h2 {
+	margin:5px 0px 5px 0px;
+	padding:0px;
+	font-size:17px;
+	line-height:28px;
+	font-weight:900;
+	color:#226;
+	}
+h3 {
+	margin:5px 0px 5px 0px;
+	padding:0px;
+	font-size:15px;
+	line-height:28px;
+	font-weight:900;
+	}
+p
+{
+	margin:0px 0px 16px 0px;
+	font:11px/20px verdana, arial, helvetica, sans-serif;
+	padding:0px;
+}
+table 
+{
+    font-size: 10pt; 
+	color: #000000;
+}
+td{border:1px solid #999;}
+
+table.pymenu {color: #000000; background-color: #99ccff}
+th.pymenu {color: #ffffff; background-color: #003366}
+
+.code 
+{
+	font-family: "Lucida Console", monospace; font-weight: bold;
+	color: #007700; background-color: #eeeeee
+}
+
+#Content>p {margin:0px;}
+#Content>p+p {text-indent:30px;}
+
+a {
+	text-decoration:none;
+	font-weight:600;
+	font-family:verdana, arial, helvetica, sans-serif;
+	color: #900;
+}
+//a:link {color:#09c;}
+//a x:visited {color:#07a;}
+a:hover {background-color:#ee0;}
+
+#Header {
+	margin:10px 0px 10px 0px;
+	padding:10px 0px 10px 20px;
+	/* For IE5/Win's benefit height = [correct height] + [top padding] + [top and bottom border widths] */
+	height:33px; /* 14px + 17px + 2px = 33px */
+	border-style:solid;
+	border-color:black;
+	border-width:1px 0px; /* top and bottom borders: 1px; left and right borders: 0px */
+	line-height:33px;
+	background-color:#eee;
+	height:66px; /* the correct height */
+	}
+
+#Content {
+	margin:0px 210px 50px 10px;
+	padding:10px;
+	}
+
+#Menu {
+	position:absolute;
+	top:100px;
+	right:20px;
+	width:172px;
+	padding:10px;
+	background-color:#eee;
+	border:1px solid #999; // dashed #999;
+	line-height:17px;
+	width:150px;
+	font-size:11px;
+	}
diff --git a/third_party/pexpect/doc/commonissues.rst b/third_party/pexpect/doc/commonissues.rst
new file mode 100644
index 0000000..26d0e2b
--- /dev/null
+++ b/third_party/pexpect/doc/commonissues.rst
@@ -0,0 +1,115 @@
+Common problems
+===============
+
+Threads
+-------
+
+On Linux (RH 8) you cannot spawn a child from a different thread and pass the
+handle back to a worker thread. The child is successfully spawned but you can't
+interact with it. The only way to make it work is to spawn and interact with the
+child all in the same thread. [Adam Kerrison]
+
+Timing issue with send() and sendline()
+---------------------------------------
+
+This problem has been addressed and should not affect most users.
+
+It is sometimes possible to read an echo of the string sent with
+:meth:`~pexpect.spawn.send` and :meth:`~pexpect.spawn.sendline`. If you call
+:meth:`~pexpect.spawn.send` and then immediately call :meth:`~pexpect.spawn.readline`,
+you may get part of your output echoed back. You may read back what you just
+wrote even if the child application does not explicitly echo it. Timing is
+critical. This could be a security issue when talking to an application that
+asks for a password; otherwise, this does not seem like a big deal. But why do
+TTYs do this?
+
+People usually report this when they are trying to control SSH or some other
+login. For example, if your code looks something like this::
+
+    child.expect ('[pP]assword:')
+    child.sendline (my_password)
+
+
+1. SSH prints "password:" prompt to the user.
+2. SSH turns off echo on the TTY device.
+3. SSH waits for user to enter a password.
+
+When scripting with Pexpect what can happen is that Pexpect will respond to the
+"password:" prompt before SSH has had time to turn off TTY echo. In other words,
+Pexpect sends the password between steps 1. and 2., so the password gets echoed
+back to the TTY. I would call this an SSH bug.
+
+Pexpect now automatically adds a short delay before sending data to a child
+process. This more closely mimics what happens in the usual human-to-app
+interaction. The delay can be tuned with the ``delaybeforesend`` attribute of the
+spawn class. In general, this fixes the problem for everyone and so this should
+not be an issue for most users. For some applications you might with to turn it
+off::
+
+    child = pexpect.spawn ("ssh user at example.com")
+    child.delaybeforesend = 0
+
+Timing issue with isalive()
+---------------------------
+
+Reading the state of :meth:`~pexpect.spawn.isalive` immediately after a child
+exits may sometimes return 1. This is a race condition. The child has closed its
+file descriptor, but has not yet fully exited before Pexpect's
+:meth:`~pexpect.spawn.isalive` executes. Addings a slight delay before the
+:meth:`~pexpect.spawn.isalive` call will help. For example::
+
+    child = pexpect.spawn('ls')
+    child.expect(pexpect.EOF)
+    time.sleep(0.1)
+    print child.isalive()
+
+Truncated output just before child exits
+----------------------------------------
+
+So far I have seen this only on older versions of Apple's MacOS X. If the child
+application quits it may not flush its output buffer. This means that your
+Pexpect application will receive an EOF even though it should have received a
+little more data before the child died. This is not generally a problem when
+talking to interactive child applications. One example where it is a problem is
+when trying to read output from a program like *ls*. You may receive most of the
+directory listing, but the last few lines will get lost before you receive an EOF.
+The reason for this is that *ls* runs; completes its task; and then exits. The
+buffer is not flushed before exit so the last few lines are lost. The following
+example demonstrates the problem::
+
+    child = pexpect.spawn('ls -l')
+    child.expect(pexpect.EOF)
+    print child.before       
+
+Controlling SSH on Solaris
+--------------------------
+
+Pexpect does not yet work perfectly on Solaris. One common problem is that SSH
+sometimes will not allow TTY password authentication. For example, you may
+expect SSH to ask you for a password using code like this::
+
+    child = pexpect.spawn('ssh user at example.com')
+    child.expect('password')
+    child.sendline('mypassword')
+
+You may see the following error come back from a spawned child SSH::
+
+    Permission denied (publickey,keyboard-interactive). 
+
+This means that SSH thinks it can't access the TTY to ask you for your password.
+The only solution I have found is to use public key authentication with SSH.
+This bypasses the need for a password. I'm not happy with this solution. The
+problem is due to poor support for Solaris Pseudo TTYs in the Python Standard
+Library.
+
+child does not receive full input, emits BEL
+--------------------------------------------
+
+You may notice when running for example cat(1) or base64(1), when sending a
+very long input line, that it is not fully received, and the BEL ('\a') may
+be found in output.
+
+By default the child terminal matches the parent, which is often in "canonical
+mode processing". You may wish to disable this mode. The exact limit of a line
+varies by operating system, and details of disabling canonical mode may be
+found in the docstring of :meth:`~pexpect.spawn.send`.
diff --git a/third_party/pexpect/doc/conf.py b/third_party/pexpect/doc/conf.py
new file mode 100644
index 0000000..3dd5d3e
--- /dev/null
+++ b/third_party/pexpect/doc/conf.py
@@ -0,0 +1,250 @@
+# -*- coding: utf-8 -*-
+#
+# Pexpect documentation build configuration file, created by
+# sphinx-quickstart on Tue Sep 17 11:05:11 2013.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('sphinxext'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx',
+              'sphinx.ext.viewcode', 'github',  # for easy GitHub links
+              ]
+
+github_project_url = "https://github.com/pexpect/pexpect"
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Pexpect'
+copyright = u'2013, Noah Spurrier and contributors'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '3.3'
+# The full version, including alpha/beta/rc tags.
+release = '3.3'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Pexpectdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'Pexpect.tex', u'Pexpect Documentation',
+   u'Noah Spurrier and contributors', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'pexpect', u'Pexpect Documentation',
+     [u'Noah Spurrier and contributors'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'Pexpect', u'Pexpect Documentation',
+   u'Noah Spurrier and contributors', 'Pexpect', 'One line description of project.',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/3/': None}
diff --git a/third_party/pexpect/doc/examples.rst b/third_party/pexpect/doc/examples.rst
new file mode 100644
index 0000000..6338b5c
--- /dev/null
+++ b/third_party/pexpect/doc/examples.rst
@@ -0,0 +1,63 @@
+Examples
+========
+
+Under the distribution tarball directory you should find an "examples" directory.
+This is the best way to learn to use Pexpect. See the descriptions of Pexpect
+Examples.
+
+`topip.py <https://github.com/pexpect/pexpect/blob/master/examples/topip.py>`_
+  This runs `netstat` on a local or remote server. It calculates some simple
+  statistical information on the number of external inet connections. This can
+  be used to detect if one IP address is taking up an excessive number of
+  connections. It can also send an email alert if a given IP address exceeds a
+  threshold between runs of the script. This script can be used as a drop-in
+  Munin plugin or it can be used stand-alone from cron. I used this on a busy
+  web server that would sometimes get hit with denial of service attacks. This
+  made it easy to see if a script was opening many multiple connections. A
+  typical browser would open fewer than 10 connections at once. A script might
+  open over 100 simultaneous connections.
+
+`hive.py <https://github.com/pexpect/pexpect/blob/master/examples/hive.py>`_
+  This script creates SSH connections to a list of hosts that you provide.
+  Then you are given a command line prompt. Each shell command that you
+  enter is sent to all the hosts. The response from each host is collected
+  and printed. For example, you could connect to a dozen different
+  machines and reboot them all at once.
+
+`script.py <https://github.com/pexpect/pexpect/blob/master/examples/script.py>`_
+  This implements a command similar to the classic BSD "script" command.
+  This will start a subshell and log all input and output to a file.
+  This demonstrates the :meth:`~pexpect.spawn.interact` method of Pexpect.
+
+`ftp.py <https://github.com/pexpect/pexpect/blob/master/examples/ftp.py>`_
+  This demonstrates an FTP "bookmark". This connects to an ftp site;
+  does a few ftp tasks; and then gives the user interactive control over
+  the session. In this case the "bookmark" is to a directory on the
+  OpenBSD ftp server. It puts you in the i386 packages directory. You
+  can easily modify this for other sites. This demonstrates the
+  :meth:`~pexpect.spawn.interact` method of Pexpect.
+
+`monitor.py <https://github.com/pexpect/pexpect/blob/master/examples/monitor.py>`_
+  This runs a sequence of commands on a remote host using SSH. It runs a
+  simple system checks such as uptime and free to monitor the state of
+  the remote host.
+
+`passmass.py <https://github.com/pexpect/pexpect/blob/master/examples/passmass.py>`_
+  This will login to each given server and change the password of the
+  given user. This demonstrates scripting logins and passwords.
+
+`python.py <https://github.com/pexpect/pexpect/blob/master/examples/python.py>`_
+  This starts the python interpreter and prints the greeting message
+  backwards. It then gives the user iteractive control of Python. It's
+  pretty useless!
+
+`ssh_tunnel.py <https://github.com/pexpect/pexpect/blob/master/examples/ssh_tunnel.py>`_
+  This starts an SSH tunnel to a remote machine. It monitors the
+  connection and restarts the tunnel if it goes down.
+
+`uptime.py <https://github.com/pexpect/pexpect/blob/master/examples/uptime.py>`_
+  This will run the uptime command and parse the output into variables.
+  This demonstrates using a single regular expression to match the
+  output of a command and capturing different variable in match groups.
+  The grouping regular expression handles a wide variety of different
+  uptime formats. 
diff --git a/third_party/pexpect/doc/history.rst b/third_party/pexpect/doc/history.rst
new file mode 100644
index 0000000..c9d5640
--- /dev/null
+++ b/third_party/pexpect/doc/history.rst
@@ -0,0 +1,215 @@
+History
+=======
+
+Releases
+--------
+
+Version 4.0
+```````````
+
+* Integration with :mod:`asyncio`: passing ``async=True`` to :meth:`~.expect`,
+  :meth:`~.expect_exact` or :meth:`~.expect_list` will make them return a
+  coroutine. You can get the result using ``yield from``, or wrap it in an
+  :class:`asyncio.Task`. This allows the event loop to do other things while
+  waiting for output that matches a pattern.
+
+Version 3.4
+```````````
+* Fix regression that prevented executable, but unreadable files from
+  being found when not specified by absolute path -- such as
+  /usr/bin/sudo (:ghissue:`104`).
+* Fixed regression when executing pexpect with some prior releases of
+  the multiprocessing module where stdin has been closed (:ghissue:`86`).
+
+Version 3.3
+```````````
+
+* Added a mechanism to wrap REPLs, or shells, in an object which can conveniently
+  be used to send commands and wait for the output (:mod:`pexpect.replwrap`).
+* Fixed issue where pexpect would attempt to execute a directory because
+  it has the 'execute' bit set (:ghissue:`37`).
+* Removed the ``pexpect.psh`` module. This was never documented, and we found
+  no evidence that people use it. The new :mod:`pexpect.replwrap` module
+  provides a more flexible alternative.
+* Fixed ``TypeError: got <type 'str'> ('\r\n') as pattern`` in :meth:`spawnu.readline`
+  method (:ghissue:`67`).
+* Fixed issue where EOF was not correctly detected in :meth:`~.interact`, causing
+  a repeating loop of output on Linux, and blocking before EOF on BSD and
+  Solaris (:ghissue:`49`).
+* Several Solaris (SmartOS) bugfixes, preventing :exc:`IOError` exceptions, especially
+  when used with cron(1) (:ghissue:`44`).
+* Added new keyword argument ``echo=True`` for :class:`spawn`.  On SVR4-like
+  systems, the method :meth:`~.isatty` will always return *False*: the child pty
+  does not appear as a terminal.  Therefore, :meth:`~.setecho`, :meth:`~.getwinsize`,
+  :meth:`~.setwinsize`, and :meth:`~.waitnoecho` are not supported on those platforms.
+
+After this, we intend to start working on a bigger refactoring of the code, to
+be released as Pexpect 4. There may be more bugfix 3.x releases, however.
+
+Version 3.2
+```````````
+
+* Fix exception handling from :func:`select.select` on Python 2 (:ghpull:`38`).
+  This was accidentally broken in the previous release when it was fixed for
+  Python 3.
+* Removed a workaround for ``TIOCSWINSZ`` on very old systems, which was causing
+  issues on some BSD systems (:ghpull:`40`).
+* Fixed an issue with exception handling in :mod:`~pexpect.pxssh` (:ghpull:`43`)
+
+The documentation for :mod:`~pexpect.pxssh` was improved.
+
+Version 3.1
+```````````
+
+* Fix an issue that prevented importing pexpect on Python 3 when ``sys.stdout``
+  was reassigned (:ghissue:`30`).
+* Improve prompt synchronisation in :mod:`~pexpect.pxssh` (:ghpull:`28`).
+* Fix pickling exception instances (:ghpull:`34`).
+* Fix handling exceptions from :func:`select.select` on Python 3 (:ghpull:`33`).
+
+The examples have also been cleaned up somewhat - this will continue in future
+releases.
+
+Version 3.0
+```````````
+
+The new major version number doesn't indicate any deliberate API incompatibility.
+We have endeavoured to avoid breaking existing APIs. However, pexpect is under
+new maintenance after a long dormancy, so some caution is warranted.
+
+* A new :ref:`unicode API <unicode>` was introduced.
+* Python 3 is now supported, using a single codebase.
+* Pexpect now requires at least Python 2.6 or 3.2.
+* The modules other than pexpect, such as :mod:`pexpect.fdpexpect` and
+  :mod:`pexpect.pxssh`, were moved into the pexpect package. For now, wrapper
+  modules are installed to the old locations for backwards compatibility (e.g.
+  ``import pxssh`` will still work), but these will be removed at some point in
+  the future.
+* Ignoring ``SIGHUP`` is now optional - thanks to Kimmo Parviainen-Jalanko for
+  the patch.
+
+We also now have `docs on ReadTheDocs <http://pexpect.readthedocs.org/>`_,
+and `continuous integration on Travis CI <https://travis-ci.org/pexpect/pexpect>`_.
+
+Version 2.4
+```````````
+
+* Fix a bug regarding making the pty the controlling terminal when the process
+  spawning it is not, actually, a terminal (such as from cron)
+
+Version 2.3
+```````````
+
+* Fixed OSError exception when a pexpect object is cleaned up. Previously, you
+  might have seen this exception::
+
+      Exception exceptions.OSError: (10, 'No child processes')
+      in <bound method spawn.__del__ of <pexpect.spawn instance at 0xd248c>> ignored
+
+  You should not see that anymore. Thanks to Michael Surette.
+* Added support for buffering reads. This greatly improves speed when trying to
+  match long output from a child process. When you create an instance of the spawn
+  object you can then set a buffer size. For now you MUST do the following to turn
+  on buffering -- it may be on by default in future version::
+
+      child = pexpect.spawn ('my_command')
+      child.maxread=1000 # Sets buffer to 1000 characters.
+
+* I made a subtle change to the way TIMEOUT and EOF exceptions behave.
+  Previously you could either expect these states in which case pexpect
+  will not raise an exception, or you could just let pexpect raise an
+  exception when these states were encountered. If you expected the
+  states then the ``before`` property was set to everything before the
+  state was encountered, but if you let pexpect raise the exception then
+  ``before`` was not set. Now, the ``before`` property will get set either
+  way you choose to handle these states.
+* The spawn object now provides iterators for a *file-like interface*.
+  This makes Pexpect a more complete file-like object. You can now write
+  code like this::
+
+      child = pexpect.spawn ('ls -l')
+      for line in child:
+          print line
+
+* write and writelines() no longer return a value. Use send() if you need that
+  functionality. I did this to make the Spawn object more closely match a
+  file-like object.
+* Added the attribute ``exitstatus``. This will give the exit code returned
+  by the child process. This will be set to ``None`` while the child is still
+  alive. When ``isalive()`` returns 0 then ``exitstatus`` will be set.
+* Made a few more tweaks to ``isalive()`` so that it will operate more
+  consistently on different platforms. Solaris is the most difficult to support.
+* You can now put ``TIMEOUT`` in a list of expected patterns. This is just like
+  putting ``EOF`` in the pattern list. Expecting for a ``TIMEOUT`` may not be
+  used as often as ``EOF``, but this makes Pexpect more consistent.
+* Thanks to a suggestion and sample code from Chad J. Schroeder I added the ability
+  for Pexpect to operate on a file descriptor that is already open. This means that
+  Pexpect can be used to control streams such as those from serial port devices. Now,
+  you just pass the integer file descriptor as the "command" when constructing a
+  spawn open. For example on a Linux box with a modem on ttyS1::
+
+      fd = os.open("/dev/ttyS1", os.O_RDWR|os.O_NONBLOCK|os.O_NOCTTY)
+      m = pexpect.spawn(fd) # Note integer fd is used instead of usual string.
+      m.send("+++") # Escape sequence
+      m.send("ATZ0\r") # Reset modem to profile 0
+      rval = m.expect(["OK", "ERROR"])
+
+* ``read()`` was renamed to ``read_nonblocking()``. Added new ``read()`` method
+  that matches file-like object interface. In general, you should not notice
+  the difference except that ``read()`` no longer allows you to directly set the
+  timeout value. I hope this will not effect any existing code. Switching to
+  ``read_nonblocking()`` should fix existing code.
+* Changed the name of ``set_echo()`` to ``setecho()``.
+* Changed the name of ``send_eof()`` to ``sendeof()``.
+* Modified ``kill()`` so that it checks to make sure the pid ``isalive()``.
+* modified ``spawn()`` (really called from ``__spawn()``) so that it does not
+  raise an expection if ``setwinsize()`` fails. Some platforms such as Cygwin
+  do not like setwinsize. This was a constant problem and since it is not a
+  critical feature I decided to just silence the error.  Normally I don't like
+  to do that, but in this case I'm making an exception.
+* Added a method ``close()`` that does what you think. It closes the file
+  descriptor of the child application. It makes no attempt to actually kill the
+  child or wait for its status.
+* Add variables ``__version__`` and ``__revision__`` (from cvs) to the pexpect
+  modules.  This is mainly helpful to me so that I can make sure that I'm testing
+  with the right version instead of one already installed.
+* ``log_open()`` and ``log_close(`` have been removed. Now use ``setlog()``.
+  The ``setlog()`` method takes a file object. This is far more flexible than
+  the previous log method. Each time data is written to the file object it will
+  be flushed. To turn logging off simply call ``setlog()`` with None.
+* renamed the ``isAlive()`` method to ``isalive()`` to match the more typical
+  naming style in Python. Also the technique used to detect child process
+  status has been drastically modified. Previously I did some funky stuff
+  with signals which caused indigestion in other Python modules on some
+  platforms. It was a big headache. It still is, but I think it works
+  better now.
+* attribute ``matched`` renamed to ``after``
+* new attribute ``match``
+* The ``expect_eof()`` method is gone. You can now simply use the
+  ``expect()`` method to look for EOF.
+* **Pexpect works on OS X**, but the nature of the quirks cause many of the
+  tests to fail. See bugs. (Incomplete Child Output). The problem is more
+  than minor, but Pexpect is still more than useful for most tasks.
+* **Solaris**: For some reason, the *second* time a pty file descriptor is created and
+  deleted it never gets returned for use. It does not effect the first time
+  or the third time or any time after that. It's only the second time. This
+  is weird... This could be a file descriptor leak, or it could be some
+  peculiarity of how Solaris recycles them. I thought it was a UNIX requirement
+  for the OS to give you the lowest available filedescriptor number. In any case,
+  this should not be a problem unless you create hundreds of pexpect instances...
+  It may also be a pty module bug.
+
+
+Moves and forks
+---------------
+
+* Pexpect development used to be hosted on Sourceforge.
+* In 2011, Thomas Kluyver forked pexpect as 'pexpect-u', to support
+  Python 3. He later decided he had taken the wrong approach with this.
+* In 2012, Noah Spurrier, the original author of Pexpect, moved the
+  project to Github, but was still too busy to develop it much.
+* In 2013, Thomas Kluyver and Jeff Quast forked Pexpect again, intending
+  to call the new fork Pexpected. Noah Spurrier agreed to let them use
+  the name Pexpect, so Pexpect versions 3 and above are based on this
+  fork, which now lives `here on Github <https://github.com/pexpect/pexpect>`_.
+
diff --git a/third_party/pexpect/doc/index.rst b/third_party/pexpect/doc/index.rst
new file mode 100644
index 0000000..0bcf862
--- /dev/null
+++ b/third_party/pexpect/doc/index.rst
@@ -0,0 +1,50 @@
+Pexpect version |version|
+=========================
+
+.. image:: https://travis-ci.org/pexpect/pexpect.png?branch=master
+   :target: https://travis-ci.org/pexpect/pexpect
+   :align: right
+   :alt: Build status
+
+Pexpect makes Python a better tool for controlling other
+applications.
+
+Pexpect is a pure Python module for spawning child applications;
+controlling them; and responding to expected patterns in their output.
+Pexpect works like Don Libes' Expect. Pexpect allows your script to
+spawn a child application and control it as if a human were typing
+commands.
+
+Pexpect can be used for automating interactive applications such as
+ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
+scripts for duplicating software package installations on different
+servers. It can be used for automated software testing. Pexpect is in
+the spirit of Don Libes' Expect, but Pexpect is pure Python. Unlike
+other Expect-like modules for Python, Pexpect does not require TCL or
+Expect nor does it require C extensions to be compiled. It should work
+on any platform that supports the standard Python pty module. The
+Pexpect interface was designed to be easy to use.
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+
+   install
+   overview
+   api/index
+   examples
+   FAQ
+   commonissues
+   history
+
+Pexpect is developed `on Github <http://github.com/pexpect/pexpect>`_. Please
+report `issues <https://github.com/pexpect/pexpect/issues>`_ there as well.
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/third_party/pexpect/doc/install.rst b/third_party/pexpect/doc/install.rst
new file mode 100644
index 0000000..297acf3
--- /dev/null
+++ b/third_party/pexpect/doc/install.rst
@@ -0,0 +1,20 @@
+Installation
+============
+
+Pexpect is on PyPI, and can be installed with standard tools::
+
+    pip install pexpect
+
+Or::
+
+    easy_install pexpect
+
+Requirements
+------------
+
+This version of Pexpect requires Python 2.6 or 3.2 or above. For older
+versions of Python, continue using Pexpect 2.4.
+
+Pexpect only works on POSIX systems, where the :mod:`pty` module
+is present in the standard library. It may be possible to run it on Windows
+using `Cygwin <http://www.cygwin.com/>`_.
diff --git a/third_party/pexpect/doc/make.bat b/third_party/pexpect/doc/make.bat
new file mode 100644
index 0000000..448f147
--- /dev/null
+++ b/third_party/pexpect/doc/make.bat
@@ -0,0 +1,190 @@
+ at ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+	set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	echo.  html       to make standalone HTML files
+	echo.  dirhtml    to make HTML files named index.html in directories
+	echo.  singlehtml to make a single large HTML file
+	echo.  pickle     to make pickle files
+	echo.  json       to make JSON files
+	echo.  htmlhelp   to make HTML files and a HTML help project
+	echo.  qthelp     to make HTML files and a qthelp project
+	echo.  devhelp    to make HTML files and a Devhelp project
+	echo.  epub       to make an epub
+	echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+	echo.  text       to make text files
+	echo.  man        to make manual pages
+	echo.  texinfo    to make Texinfo files
+	echo.  gettext    to make PO message catalogs
+	echo.  changes    to make an overview over all changed/added/deprecated items
+	echo.  linkcheck  to check all external links for integrity
+	echo.  doctest    to run all doctests embedded in the documentation if enabled
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+	del /q /s %BUILDDIR%\*
+	goto end
+)
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+	goto end
+)
+
+if "%1" == "singlehtml" (
+	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Pexpect.qhcp
+	echo.To view the help file:
+	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Pexpect.ghc
+	goto end
+)
+
+if "%1" == "devhelp" (
+	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished.
+	goto end
+)
+
+if "%1" == "epub" (
+	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The epub file is in %BUILDDIR%/epub.
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "text" (
+	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The text files are in %BUILDDIR%/text.
+	goto end
+)
+
+if "%1" == "man" (
+	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The manual pages are in %BUILDDIR%/man.
+	goto end
+)
+
+if "%1" == "texinfo" (
+	%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+	goto end
+)
+
+if "%1" == "gettext" (
+	%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.The overview file is in %BUILDDIR%/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+	goto end
+)
+
+:end
diff --git a/third_party/pexpect/doc/overview.rst b/third_party/pexpect/doc/overview.rst
new file mode 100644
index 0000000..a04e389
--- /dev/null
+++ b/third_party/pexpect/doc/overview.rst
@@ -0,0 +1,240 @@
+API Overview
+============
+
+Pexpect can be used for automating interactive applications such as ssh, ftp,
+mencoder, passwd, etc. The Pexpect interface was designed to be easy to use.
+
+Here is an example of Pexpect in action::
+
+    # This connects to the openbsd ftp site and
+    # downloads the recursive directory listing.
+    import pexpect
+    child = pexpect.spawn('ftp ftp.openbsd.org')
+    child.expect('Name .*: ')
+    child.sendline('anonymous')
+    child.expect('Password:')
+    child.sendline('noah at example.com')
+    child.expect('ftp> ')
+    child.sendline('lcd /tmp')
+    child.expect('ftp> ')
+    child.sendline('cd pub/OpenBSD')
+    child.expect('ftp> ')
+    child.sendline('get README')
+    child.expect('ftp> ')
+    child.sendline('bye')
+
+Obviously you could write an ftp client using Python's own :mod:`ftplib` module,
+but this is just a demonstration. You can use this technique with any application.
+This is especially handy if you are writing automated test tools.
+
+There are two important methods in Pexpect -- :meth:`~pexpect.spawn.expect` and
+:meth:`~pexpect.spawn.send` (or :meth:`~pexpect.spawn.sendline` which is
+like :meth:`~pexpect.spawn.send` with a linefeed). The :meth:`~pexpect.spawn.expect`
+method waits for the child application to return a given string. The string you
+specify is a regular expression, so you can match complicated patterns. The
+:meth:`~pexpect.spawn.send` method writes a string to the child application.
+From the child's point of view it looks just like someone typed the text from a
+terminal. After each call to :meth:`~pexpect.spawn.expect` the ``before`` and ``after``
+properties will be set to the text printed by child application. The ``before``
+property will contain all text up to the expected string pattern. The ``after``
+string will contain the text that was matched by the expected pattern.
+The match property is set to the `re match object <http://docs.python.org/3/library/re#match-objects>`_.
+
+An example of Pexpect in action may make things more clear. This example uses
+ftp to login to the OpenBSD site; list files in a directory; and then pass
+interactive control of the ftp session to the human user::
+
+    import pexpect
+    child = pexpect.spawn ('ftp ftp.openbsd.org')
+    child.expect ('Name .*: ')
+    child.sendline ('anonymous')
+    child.expect ('Password:')
+    child.sendline ('noah at example.com')
+    child.expect ('ftp> ')
+    child.sendline ('ls /pub/OpenBSD/')
+    child.expect ('ftp> ')
+    print child.before   # Print the result of the ls command.
+    child.interact()     # Give control of the child to the user.
+
+Special EOF and TIMEOUT patterns
+--------------------------------
+
+There are two special patterns to match the End Of File (:class:`~pexpect.EOF`)
+or a Timeout condition (:class:`~pexpect.TIMEOUT`). You you can pass these
+patterns to :meth:`~pexpect.spawn.expect`. These patterns are not regular
+expressions. Use them like predefined constants.
+
+If the child has died and you have read all the child's output then ordinarily
+:meth:`~pexpect.spawn.expect` will raise an :class:`~pexpect.EOF` exception.
+You can read everything up to the EOF without generating an exception by using
+the EOF pattern expect. In this case everything the child has output will be
+available in the ``before`` property.
+
+The pattern given to :meth:`~pexpect.spawn.expect` may be a regular expression
+or it may also be a list of regular expressions. This allows you to match
+multiple optional responses. The :meth:`~pexpect.spawn.expect` method returns
+the index of the pattern that was matched. For example, say you wanted to login
+to a server. After entering a password you could get various responses from the
+server -- your password could be rejected; or you could be allowed in and asked
+for your terminal type; or you could be let right in and given a command prompt.
+The following code fragment gives an example of this::
+
+    child.expect('password:')
+    child.sendline(my_secret_password)
+    # We expect any of these three patterns...
+    i = child.expect (['Permission denied', 'Terminal type', '[#\$] '])
+    if i==0:
+        print('Permission denied on host. Can't login')
+        child.kill(0)
+    elif i==2:
+        print('Login OK... need to send terminal type.')
+        child.sendline('vt100')
+        child.expect('[#\$] ')
+    elif i==3:
+        print('Login OK.')
+        print('Shell command prompt', child.after)
+
+If nothing matches an expected pattern then :meth:`~pexpect.spawn.expect` will
+eventually raise a :class:`~pexpect.TIMEOUT` exception. The default time is 30
+seconds, but you can change this by passing a timeout argument to
+:meth:`~pexpect.spawn.expect`::
+
+    # Wait no more than 2 minutes (120 seconds) for password prompt.
+    child.expect('password:', timeout=120)
+
+Find the end of line -- CR/LF conventions
+-----------------------------------------
+
+Pexpect matches regular expressions a little differently than what you might be
+used to.
+
+The :regexp:`$` pattern for end of line match is useless. The :regexp:`$`
+matches the end of string, but Pexpect reads from the child one character at a
+time, so each character looks like the end of a line. Pexpect can't do a
+look-ahead into the child's output stream. In general you would have this
+situation when using regular expressions with any stream.
+
+.. note::
+
+  Pexpect does have an internal buffer, so reads are faster than one character
+  at a time, but from the user's perspective the regex patterns test happens
+  one character at a time.
+
+The best way to match the end of a line is to look for the newline: ``"\r\n"``
+(CR/LF). Yes, that does appear to be DOS-style. It may surprise some UNIX people
+to learn that terminal TTY device drivers (dumb, vt100, ANSI, xterm, etc.) all
+use the CR/LF combination to signify the end of line. Pexpect uses a Pseudo-TTY
+device to talk to the child application, so when the child app prints ``"\n"``
+you actually see ``"\r\n"``.
+
+UNIX uses just linefeeds to end lines of text, but not when it comes to TTY
+devices! TTY devices are more like the Windows world. Each line of text ends
+with a CR/LF combination. When you intercept data from a UNIX command from a
+TTY device you will find that the TTY device outputs a CR/LF combination. A
+UNIX command may only write a linefeed (``\n``), but the TTY device driver
+converts it to CR/LF. This means that your terminal will see lines end with
+CR/LF (hex ``0D 0A``). Since Pexpect emulates a terminal, to match ends of
+lines you have to expect the CR/LF combination::
+
+    child.expect('\r\n')
+
+If you just need to skip past a new line then ``expect('\n')`` by itself will
+work, but if you are expecting a specific pattern before the end of line then
+you need to explicitly look for the ``\r``. For example the following expects a
+word at the end of a line::
+
+    child.expect('\w+\r\n')
+
+But the following would both fail::
+
+    child.expect('\w+\n')
+
+And as explained before, trying to use :regexp:`$` to match the end of line
+would not work either::
+
+    child.expect ('\w+$')
+
+So if you need to explicitly look for the END OF LINE, you want to look for the
+CR/LF combination -- not just the LF and not the $ pattern.
+
+This problem is not limited to Pexpect. This problem happens any time you try
+to perform a regular expression match on a stream. Regular expressions need to
+look ahead. With a stream it is hard to look ahead because the process
+generating the stream may not be finished. There is no way to know if the
+process has paused momentarily or is finished and waiting for you. Pexpect must
+implicitly always do a NON greedy match (minimal) at the end of a input.
+
+Pexpect compiles all regular expressions with the :data:`re.DOTALL` flag.
+With the :data:`~re.DOTALL` flag, a ``"."`` will match a newline.
+
+Beware of + and * at the end of patterns
+----------------------------------------
+
+Remember that any time you try to match a pattern that needs look-ahead that
+you will always get a minimal match (non greedy). For example, the following
+will always return just one character::
+
+    child.expect ('.+')
+
+This example will match successfully, but will always return no characters::
+
+    child.expect ('.*')
+
+Generally any star * expression will match as little as possible.
+
+One thing you can do is to try to force a non-ambiguous character at the end of
+your :regexp:`\\d+` pattern. Expect that character to delimit the string. For
+example, you might try making the end of your pattern be :regexp:`\\D+` instead
+of :regexp:`\\D*`. Number digits alone would not satisfy the :regexp:`(\\d+)\\D+`
+pattern. You would need some numbers and at least one non-number at the end.
+
+
+Debugging
+---------
+
+If you get the string value of a :class:`pexpect.spawn` object you will get lots
+of useful debugging information. For debugging it's very useful to use the
+following pattern::
+
+    try:
+        i = child.expect ([pattern1, pattern2, pattern3, etc])
+    except:
+        print("Exception was thrown")
+        print("debug information:")
+        print(str(child))
+
+It is also useful to log the child's input and out to a file or the screen. The
+following will turn on logging and send output to stdout (the screen)::
+
+    child = pexpect.spawn(foo)
+    child.logfile = sys.stdout
+
+Exceptions
+----------
+
+:class:`~pexpect.EOF`
+
+Note that two flavors of EOF Exception may be thrown. They are virtually
+identical except for the message string. For practical purposes you should have
+no need to distinguish between them, but they do give a little extra information
+about what type of platform you are running. The two messages are:
+
+- "End Of File (EOF) in read(). Exception style platform."
+- "End Of File (EOF) in read(). Empty string style platform."
+
+Some UNIX platforms will throw an exception when you try to read from a file
+descriptor in the EOF state. Other UNIX platforms instead quietly return an
+empty string to indicate that the EOF state has been reached.
+
+If you wish to read up to the end of the child's output without generating an
+:class:`~pexpect.EOF` exception then use the ``expect(pexpect.EOF)`` method.
+
+:class:`~pexpect.TIMEOUT`
+
+The :meth:`~pexpect.spawn.expect` and :meth:`~pexpect.spawn.read` methods will
+also timeout if the child does not generate any output for a given amount of
+time. If this happens they will raise a :class:`~pexpect.TIMEOUT` exception.
+You can have these method ignore a timeout and block indefinitely by passing 
+``None`` for the timeout parameter::
+
+    child.expect(pexpect.EOF, timeout=None)
diff --git a/third_party/pexpect/doc/requirements.txt b/third_party/pexpect/doc/requirements.txt
new file mode 100644
index 0000000..57ebb2d
--- /dev/null
+++ b/third_party/pexpect/doc/requirements.txt
@@ -0,0 +1 @@
+ptyprocess
diff --git a/third_party/pexpect/doc/sphinxext/github.py b/third_party/pexpect/doc/sphinxext/github.py
new file mode 100644
index 0000000..519e146
--- /dev/null
+++ b/third_party/pexpect/doc/sphinxext/github.py
@@ -0,0 +1,155 @@
+"""Define text roles for GitHub
+
+* ghissue - Issue
+* ghpull - Pull Request
+* ghuser - User
+
+Adapted from bitbucket example here:
+https://bitbucket.org/birkenfeld/sphinx-contrib/src/tip/bitbucket/sphinxcontrib/bitbucket.py
+
+Authors
+-------
+
+* Doug Hellmann
+* Min RK
+"""
+#
+# Original Copyright (c) 2010 Doug Hellmann.  All rights reserved.
+#
+
+from docutils import nodes, utils
+from docutils.parsers.rst.roles import set_classes
+
+def make_link_node(rawtext, app, type, slug, options):
+    """Create a link to a github resource.
+
+    :param rawtext: Text being replaced with link node.
+    :param app: Sphinx application context
+    :param type: Link type (issues, changeset, etc.)
+    :param slug: ID of the thing to link to
+    :param options: Options dictionary passed to role func.
+    """
+
+    try:
+        base = app.config.github_project_url
+        if not base:
+            raise AttributeError
+        if not base.endswith('/'):
+            base += '/'
+    except AttributeError as err:
+        raise ValueError('github_project_url configuration value is not set (%s)' % str(err))
+
+    ref = base + type + '/' + slug + '/'
+    set_classes(options)
+    prefix = "#"
+    if type == 'pull':
+        prefix = "PR " + prefix
+    node = nodes.reference(rawtext, prefix + utils.unescape(slug), refuri=ref,
+                           **options)
+    return node
+
+def ghissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
+    """Link to a GitHub issue.
+
+    Returns 2 part tuple containing list of nodes to insert into the
+    document and a list of system messages.  Both are allowed to be
+    empty.
+
+    :param name: The role name used in the document.
+    :param rawtext: The entire markup snippet, with role.
+    :param text: The text marked with the role.
+    :param lineno: The line number where rawtext appears in the input.
+    :param inliner: The inliner instance that called us.
+    :param options: Directive options for customization.
+    :param content: The directive content for customization.
+    """
+
+    try:
+        issue_num = int(text)
+        if issue_num <= 0:
+            raise ValueError
+    except ValueError:
+        msg = inliner.reporter.error(
+            'GitHub issue number must be a number greater than or equal to 1; '
+            '"%s" is invalid.' % text, line=lineno)
+        prb = inliner.problematic(rawtext, rawtext, msg)
+        return [prb], [msg]
+    app = inliner.document.settings.env.app
+    #app.info('issue %r' % text)
+    if 'pull' in name.lower():
+        category = 'pull'
+    elif 'issue' in name.lower():
+        category = 'issues'
+    else:
+        msg = inliner.reporter.error(
+            'GitHub roles include "ghpull" and "ghissue", '
+            '"%s" is invalid.' % name, line=lineno)
+        prb = inliner.problematic(rawtext, rawtext, msg)
+        return [prb], [msg]
+    node = make_link_node(rawtext, app, category, str(issue_num), options)
+    return [node], []
+
+def ghuser_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
+    """Link to a GitHub user.
+
+    Returns 2 part tuple containing list of nodes to insert into the
+    document and a list of system messages.  Both are allowed to be
+    empty.
+
+    :param name: The role name used in the document.
+    :param rawtext: The entire markup snippet, with role.
+    :param text: The text marked with the role.
+    :param lineno: The line number where rawtext appears in the input.
+    :param inliner: The inliner instance that called us.
+    :param options: Directive options for customization.
+    :param content: The directive content for customization.
+    """
+    app = inliner.document.settings.env.app
+    #app.info('user link %r' % text)
+    ref = 'https://www.github.com/' + text
+    node = nodes.reference(rawtext, text, refuri=ref, **options)
+    return [node], []
+
+def ghcommit_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
+    """Link to a GitHub commit.
+
+    Returns 2 part tuple containing list of nodes to insert into the
+    document and a list of system messages.  Both are allowed to be
+    empty.
+
+    :param name: The role name used in the document.
+    :param rawtext: The entire markup snippet, with role.
+    :param text: The text marked with the role.
+    :param lineno: The line number where rawtext appears in the input.
+    :param inliner: The inliner instance that called us.
+    :param options: Directive options for customization.
+    :param content: The directive content for customization.
+    """
+    app = inliner.document.settings.env.app
+    #app.info('user link %r' % text)
+    try:
+        base = app.config.github_project_url
+        if not base:
+            raise AttributeError
+        if not base.endswith('/'):
+            base += '/'
+    except AttributeError as err:
+        raise ValueError('github_project_url configuration value is not set (%s)' % str(err))
+
+    ref = base + text
+    node = nodes.reference(rawtext, text[:6], refuri=ref, **options)
+    return [node], []
+
+
+def setup(app):
+    """Install the plugin.
+    
+    :param app: Sphinx application context.
+    """
+    app.info('Initializing GitHub plugin')
+    app.add_role('ghissue', ghissue_role)
+    app.add_role('ghpull', ghissue_role)
+    app.add_role('ghuser', ghuser_role)
+    app.add_role('ghcommit', ghcommit_role)
+    app.add_config_value('github_project_url', None, 'env')
+    return
diff --git a/third_party/pexpect/examples/README b/third_party/pexpect/examples/README
new file mode 100644
index 0000000..be21e96
--- /dev/null
+++ b/third_party/pexpect/examples/README
@@ -0,0 +1,89 @@
+This directory contains scripts that give examples of using Pexpect.
+
+hive.py
+    This script creates SSH connections to a list of hosts that
+    you provide. Then you are given a command line prompt. Each
+    shell command that you enter is sent to all the hosts. The
+    response from each host is collected and printed. For example,
+    you could connect to a dozen different machines and reboot
+    them all at once.
+
+script.py
+    This implements a command similar to the classic BSD "script" command.
+    This will start a subshell and log all input and output to a file.
+    This demonstrates the interact() method of Pexpect.
+
+fix_cvs_files.py
+    This is for cleaning up binary files improperly added to
+    CVS. This script scans the given path to find binary files;
+    checks with CVS to see if the sticky options are set to -kb;
+    finally if sticky options are not -kb then uses 'cvs admin'
+    to set the -kb option. 
+
+ftp.py
+    This demonstrates an FTP "bookmark".
+    This connects to an ftp site; does a few ftp commands; and then gives the user
+    interactive control over the session. In this case the "bookmark" is to a
+    directory on the OpenBSD ftp server. It puts you in the i386 packages
+    directory. You can easily modify this for other sites.
+    This demonstrates the interact() method of Pexpect.
+
+monitor.py
+    This runs a sequence of system status commands on a remote host using SSH.
+    It runs a simple system checks such as uptime and free to monitor
+    the state of the remote host.
+
+passmass.py
+    This will login to a list of hosts and change the password of the
+    given user. This demonstrates scripting logins; although, you could
+    more easily do this using the pxssh subclass of Pexpect.
+    See also the "hive.py" example script for a more general example
+    of scripting a collection of servers.
+
+python.py
+    This starts the python interpreter and prints the greeting message backwards.
+    It then gives the user interactive control of Python. It's pretty useless!
+
+rippy.py
+    This is a wizard for mencoder. It greatly simplifies the process of
+    ripping a DVD to mpeg4 format (XviD, DivX). It can transcode from any
+    video file to another. It has options for resampling the audio stream;
+    removing interlace artifacts, fitting to a target file size, etc.
+    There are lots of options, but the process is simple and easy to use.
+
+sshls.py
+    This lists a directory on a remote machine.
+
+ssh_tunnel.py
+    This starts an SSH tunnel to a remote machine. It monitors the connection
+    and restarts the tunnel if it goes down.
+
+uptime.py
+    This will run the uptime command and parse the output into python variables.
+    This demonstrates using a single regular expression to match the output
+    of a command and capturing different variable in match groups.
+    The regular expression takes into account a wide variety of different
+    formats for uptime output.
+
+df.py
+    This collects filesystem capacity info using the 'df' command.
+    Tuples of filesystem name and percentage are stored in a list.
+    A simple report is printed. Filesystems over 95% capacity are highlighted.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
diff --git a/third_party/pexpect/examples/astat.py b/third_party/pexpect/examples/astat.py
new file mode 100755
index 0000000..a083fe1
--- /dev/null
+++ b/third_party/pexpect/examples/astat.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+
+'''This runs Apache Status on the remote host and returns the number of requests per second.
+
+./astat.py [-s server_hostname] [-u username] [-p password]
+    -s : hostname of the remote server to login to.
+    -u : username to user for login.
+    -p : Password to user for login.
+
+Example:
+    This will print information about the given host:
+        ./astat.py -s www.example.com -u mylogin -p mypassword
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import os
+import sys
+import getopt
+import getpass
+import pxssh
+
+
+try:
+    raw_input
+except NameError:
+    raw_input = input
+
+
+def exit_with_usage():
+
+    print(globals()['__doc__'])
+    os._exit(1)
+
+
+def main():
+
+    ######################################################################
+    ## Parse the options, arguments, get ready, etc.
+    ######################################################################
+    try:
+        optlist, args = getopt.getopt(sys.argv[1:], 'h?s:u:p:', ['help','h','?'])
+    except Exception as e:
+        print(str(e))
+        exit_with_usage()
+    options = dict(optlist)
+    if len(args) > 1:
+        exit_with_usage()
+
+    if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]:
+        print("Help:")
+        exit_with_usage()
+
+    if '-s' in options:
+        hostname = options['-s']
+    else:
+        hostname = raw_input('hostname: ')
+    if '-u' in options:
+        username = options['-u']
+    else:
+        username = raw_input('username: ')
+    if '-p' in options:
+        password = options['-p']
+    else:
+        password = getpass.getpass('password: ')
+
+    #
+    # Login via SSH
+    #
+    p = pxssh.pxssh()
+    p.login(hostname, username, password)
+    p.sendline('apachectl status')
+    p.expect('([0-9]+\.[0-9]+)\s*requests/sec')
+    requests_per_second = p.match.groups()[0]
+    p.logout()
+    print(requests_per_second)
+
+if __name__ == "__main__":
+    main()
diff --git a/third_party/pexpect/examples/cgishell.cgi b/third_party/pexpect/examples/cgishell.cgi
new file mode 100755
index 0000000..23bef5f
--- /dev/null
+++ b/third_party/pexpect/examples/cgishell.cgi
@@ -0,0 +1,766 @@
+#!/usr/bin/python
+##!/usr/bin/env python
+"""CGI shell server
+
+This exposes a shell terminal on a web page.
+It uses AJAX to send keys and receive screen updates.
+The client web browser needs nothing but CSS and Javascript.
+
+    --hostname : sets the remote host name to open an ssh connection to.
+    --username : sets the user name to login with
+    --password : (optional) sets the password to login with
+    --port     : set the local port for the server to listen on
+    --watch    : show the virtual screen after each client request
+
+This project is probably not the most security concious thing I've ever built.
+This should be considered an experimental tool -- at best.
+"""
+
+from __future__ import absolute_import
+from __future__ import print_function
+
+import sys,os
+sys.path.insert (0,os.getcwd()) # let local modules precede any installed modules
+import socket, random, string, traceback, cgi, time, getopt, getpass, threading, resource, signal
+import pxssh, pexpect, ANSI
+
+def exit_with_usage(exit_code=1):
+    print(globals()['__doc__'])
+    os._exit(exit_code)
+
+def client (command, host='localhost', port=-1):
+    """This sends a request to the server and returns the response.
+    If port <= 0 then host is assumed to be the filename of a Unix domain socket.
+    If port > 0 then host is an inet hostname.
+    """
+    if port <= 0:
+        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        s.connect(host)
+    else:
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        s.connect((host, port))
+    s.send(command)
+    data = s.recv (2500)
+    s.close()
+    return data
+
+def server (hostname, username, password, socket_filename='/tmp/server_sock', daemon_mode = True, verbose=False):
+    """This starts and services requests from a client.
+        If daemon_mode is True then this forks off a separate daemon process and returns the daemon's pid.
+        If daemon_mode is False then this does not return until the server is done.
+    """
+    if daemon_mode:
+        mypid_name = '/tmp/%d.pid' % os.getpid()
+        daemon_pid = daemonize(daemon_pid_filename=mypid_name)
+        time.sleep(1)
+        if daemon_pid != 0:
+            os.unlink(mypid_name)
+            return daemon_pid
+
+    virtual_screen = ANSI.ANSI (24,80) 
+    child = pxssh.pxssh()
+    try:
+        child.login (hostname, username, password, login_naked=True)
+    except:
+        return   
+    if verbose: print('login OK')
+    virtual_screen.write (child.before)
+    virtual_screen.write (child.after)
+
+    if os.path.exists(socket_filename): os.remove(socket_filename)
+    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+    s.bind(socket_filename)
+    os.chmod(socket_filename, 0o777)
+    if verbose: print('Listen')
+    s.listen(1)
+
+    r = roller (endless_poll, (child, child.PROMPT, virtual_screen))
+    r.start()
+    if verbose: print("started screen-poll-updater in background thread")
+    sys.stdout.flush()
+    try:
+        while True:
+            conn, addr = s.accept()
+            if verbose: print('Connected by', addr)
+            data = conn.recv(1024)
+            request = data.split(' ', 1)
+            if len(request)>1:
+                cmd = request[0].strip()
+                arg = request[1].strip()
+            else:
+                cmd = request[0].strip()
+                arg = ''
+
+            if cmd == 'exit':
+                r.cancel()
+                break
+            elif cmd == 'sendline':
+                child.sendline (arg)
+                time.sleep(0.1)
+                shell_window = str(virtual_screen)
+            elif cmd == 'send' or cmd=='xsend':
+                if cmd=='xsend':
+                    arg = arg.decode("hex")
+                child.send (arg)
+                time.sleep(0.1)
+                shell_window = str(virtual_screen)
+            elif cmd == 'cursor':
+                shell_window = '%x,%x' % (virtual_screen.cur_r, virtual_screen.cur_c)
+            elif cmd == 'refresh':
+                shell_window = str(virtual_screen)
+            elif cmd == 'hash':
+                shell_window = str(hash(str(virtual_screen)))
+
+            response = []
+            response.append (shell_window)
+            if verbose: print('\n'.join(response))
+            sent = conn.send('\n'.join(response))
+            if sent < len (response):
+                if verbose: print("Sent is too short. Some data was cut off.")
+            conn.close()
+    except e:
+        pass
+    r.cancel()
+    if verbose: print("cleaning up socket")
+    s.close()
+    if os.path.exists(socket_filename): os.remove(socket_filename)
+    if verbose: print("server done!")
+
+class roller (threading.Thread):
+    """This class continuously loops a function in a thread.
+        This is basically a thin layer around Thread with a
+        while loop and a cancel.
+    """
+    def __init__(self, function, args=[], kwargs={}):
+        threading.Thread.__init__(self)
+        self.function = function
+        self.args = args
+        self.kwargs = kwargs
+        self.finished = threading.Event()
+    def cancel(self):
+        """Stop the roller."""
+        self.finished.set()
+    def run(self):
+        while not self.finished.isSet():
+            self.function(*self.args, **self.kwargs)
+
+def endless_poll (child, prompt, screen, refresh_timeout=0.1):
+    """This keeps the screen updated with the output of the child.
+        This will be run in a separate thread. See roller class.
+    """
+    #child.logfile_read = screen
+    try:
+        s = child.read_nonblocking(4000, 0.1)
+        screen.write(s)
+    except:
+        pass
+
+def daemonize (stdin=None, stdout=None, stderr=None, daemon_pid_filename=None):
+    """This runs the current process in the background as a daemon.
+    The arguments stdin, stdout, stderr allow you to set the filename that the daemon reads and writes to.
+    If they are set to None then all stdio for the daemon will be directed to /dev/null.
+    If daemon_pid_filename is set then the pid of the daemon will be written to it as plain text
+    and the pid will be returned. If daemon_pid_filename is None then this will return None.
+    """
+    UMASK = 0
+    WORKINGDIR = "/"
+    MAXFD = 1024
+
+    # The stdio file descriptors are redirected to /dev/null by default.
+    if hasattr(os, "devnull"):
+        DEVNULL = os.devnull
+    else:
+        DEVNULL = "/dev/null"
+    if stdin is None: stdin = DEVNULL
+    if stdout is None: stdout = DEVNULL
+    if stderr is None: stderr = DEVNULL
+
+    try:
+        pid = os.fork() # fork first child
+    except OSError as e:
+        raise Exception("%s [%d]" % (e.strerror, e.errno))
+
+    if pid != 0: 
+        os.waitpid(pid,0)
+        if daemon_pid_filename is not None:
+            daemon_pid = int(file(daemon_pid_filename,'r').read())
+            return daemon_pid
+        else:
+            return None
+
+    # first child
+    os.setsid()
+    signal.signal(signal.SIGHUP, signal.SIG_IGN)
+
+    try:
+        pid = os.fork() # fork second child
+    except OSError as e:
+        raise Exception("%s [%d]" % (e.strerror, e.errno))
+
+    if pid != 0:
+        if daemon_pid_filename is not None:
+            file(daemon_pid_filename,'w').write(str(pid))
+        os._exit(0) # exit parent (the first child) of the second child.
+
+    # second child
+    os.chdir(WORKINGDIR)
+    os.umask(UMASK)
+
+    maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
+    if maxfd == resource.RLIM_INFINITY:
+        maxfd = MAXFD
+  
+    # close all file descriptors
+    for fd in range(0, maxfd):
+        try:
+            os.close(fd)
+        except OSError:   # fd wasn't open to begin with (ignored)
+            pass
+
+    os.open (DEVNULL, os.O_RDWR)  # standard input
+
+    # redirect standard file descriptors
+    si = open(stdin, 'r')
+    so = open(stdout, 'a+')
+    se = open(stderr, 'a+', 0)
+    os.dup2(si.fileno(), sys.stdin.fileno())
+    os.dup2(so.fileno(), sys.stdout.fileno())
+    os.dup2(se.fileno(), sys.stderr.fileno())
+
+    return 0
+
+def client_cgi ():
+    """This handles the request if this script was called as a cgi.
+    """
+    sys.stderr = sys.stdout
+    ajax_mode = False
+    TITLE="Shell"
+    SHELL_OUTPUT=""
+    SID="NOT"
+    print("Content-type: text/html;charset=utf-8\r\n")
+    try:
+        form = cgi.FieldStorage()
+        if 'ajax' in form:
+            ajax_mode = True
+            ajax_cmd = form['ajax'].value
+            SID=form['sid'].value
+            if ajax_cmd == 'send':
+                command = 'xsend'
+                arg = form['arg'].value.encode('hex')
+                result = client (command + ' ' + arg, '/tmp/'+SID)
+                print(result)
+            elif ajax_cmd == 'refresh':
+                command = 'refresh'
+                result = client (command, '/tmp/'+SID)
+                print(result)
+            elif ajax_cmd == 'cursor':
+                command = 'cursor'
+                result = client (command, '/tmp/'+SID)
+                print(result)
+            elif ajax_cmd == 'exit':
+                command = 'exit'
+                result = client (command, '/tmp/'+SID)
+                print(result)
+            elif ajax_cmd == 'hash':
+                command = 'hash'
+                result = client (command, '/tmp/'+SID)
+                print(result)
+        elif 'sid' not in form:
+            SID=random_sid()
+            print(LOGIN_HTML % locals());
+        else:
+            SID=form['sid'].value
+            if 'start_server' in form:
+                USERNAME = form['username'].value
+                PASSWORD = form['password'].value
+                dpid = server ('127.0.0.1', USERNAME, PASSWORD, '/tmp/'+SID)
+                SHELL_OUTPUT="daemon pid: " + str(dpid)
+            else:
+                if 'cli' in form:
+                    command = 'sendline ' + form['cli'].value
+                else:
+                    command = 'sendline'
+                SHELL_OUTPUT = client (command, '/tmp/'+SID)
+            print(CGISH_HTML % locals())
+    except:
+        tb_dump = traceback.format_exc()
+        if ajax_mode:
+            print(str(tb_dump))
+        else:
+            SHELL_OUTPUT=str(tb_dump)
+            print(CGISH_HTML % locals())
+
+def server_cli():
+    """This is the command line interface to starting the server.
+    This handles things if the script was not called as a CGI
+    (if you run it from the command line).
+    """
+    try:
+        optlist, args = getopt.getopt(sys.argv[1:], 'h?d', ['help','h','?', 'hostname=', 'username=', 'password=', 'port=', 'watch'])
+    except Exception as e:
+        print(str(e))
+        exit_with_usage()
+
+    command_line_options = dict(optlist)
+    options = dict(optlist)
+    # There are a million ways to cry for help. These are but a few of them.
+    if [elem for elem in command_line_options if elem in ['-h','--h','-?','--?','--help']]:
+        exit_with_usage(0)
+  
+    hostname = "127.0.0.1"
+    #port = 1664
+    username = os.getenv('USER')
+    password = ""
+    daemon_mode = False
+    if '-d' in options:
+        daemon_mode = True
+    if '--watch' in options:
+        watch_mode = True
+    else:
+        watch_mode = False
+    if '--hostname' in options:
+        hostname = options['--hostname']
+    if '--port' in options:
+        port = int(options['--port'])
+    if '--username' in options:
+        username = options['--username']
+    if '--password' in options:
+        password = options['--password']
+    else:
+        password = getpass.getpass('password: ')
+   
+    server (hostname, username, password, '/tmp/mysock', daemon_mode)
+
+def random_sid ():
+    a=random.randint(0,65535)
+    b=random.randint(0,65535)
+    return '%04x%04x.sid' % (a,b)
+
+def parse_host_connect_string (hcs):
+    """This parses a host connection string in the form
+    username:password at hostname:port. All fields are options expcet hostname. A
+    dictionary is returned with all four keys. Keys that were not included are
+    set to empty strings ''. Note that if your password has the '@' character
+    then you must backslash escape it.
+    """
+    if '@' in hcs:
+        p = re.compile (r'(?P<username>[^@:]*)(:?)(?P<password>.*)(?!\\)@(?P<hostname>[^:]*):?(?P<port>[0-9]*)')
+    else:
+        p = re.compile (r'(?P<username>)(?P<password>)(?P<hostname>[^:]*):?(?P<port>[0-9]*)')
+    m = p.search (hcs)
+    d = m.groupdict()
+    d['password'] = d['password'].replace('\\@','@')
+    return d
+     
+def pretty_box (s, rows=24, cols=80):
+    """This puts an ASCII text box around the given string.
+    """
+    top_bot = '+' + '-'*cols + '+\n'
+    return top_bot + '\n'.join(['|'+line+'|' for line in s.split('\n')]) + '\n' + top_bot
+
+def main ():
+    if os.getenv('REQUEST_METHOD') is None:
+        server_cli()
+    else:
+        client_cgi()
+
+# It's mostly HTML and Javascript from here on out.
+CGISH_HTML="""<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>%(TITLE)s %(SID)s</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<style type=text/css>
+a {color: #9f9; text-decoration: none}
+a:hover {color: #0f0}
+hr {color: #0f0}
+html,body,textarea,input,form
+{
+font-family: "Courier New", Courier, mono; 
+font-size: 8pt; 
+color: #0c0;
+background-color: #020;
+margin:0;
+padding:0;
+border:0;
+}
+input { background-color: #010; }
+textarea {
+border-width:1;
+border-style:solid;
+border-color:#0c0;
+padding:3;
+margin:3;
+}
+</style>
+
+<script language="JavaScript">
+function focus_first()
+{if (document.forms.length > 0)
+{var TForm = document.forms[0];
+for (i=0;i<TForm.length;i++){
+if ((TForm.elements[i].type=="text")||
+(TForm.elements[i].type=="textarea")||
+(TForm.elements[i].type.toString().charAt(0)=="s"))
+{document.forms[0].elements[i].focus();break;}}}}
+
+// JavaScript Virtual Keyboard
+// If you like this code then buy me a sandwich.
+// Noah Spurrier <noah at noah.org>
+var flag_shift=0;
+var flag_shiftlock=0;
+var flag_ctrl=0;
+var ButtonOnColor="#ee0";
+
+function init ()
+{
+    // hack to set quote key to show both single quote and double quote
+    document.form['quote'].value = "'" + '  "';
+    //refresh_screen();
+    poll();
+    document.form["cli"].focus();
+}
+function get_password ()
+{
+    var username = prompt("username?","");
+    var password = prompt("password?","");
+    start_server (username, password);
+}
+function multibrowser_ajax ()
+{
+    var xmlHttp = false;
+/*@cc_on @*/
+/*@if (@_jscript_version >= 5)
+    try
+    {
+        xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
+    }
+    catch (e)
+    {
+        try
+        {
+            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
+        }
+        catch (e2)
+        {
+              xmlHttp = false;
+        }
+    }
+ at end @*/
+
+    if (!xmlHttp && typeof XMLHttpRequest != 'undefined')
+    {
+        xmlHttp = new XMLHttpRequest();
+    }
+    return xmlHttp;
+}
+function load_url_to_screen(url)
+{ 
+    xmlhttp = multibrowser_ajax();
+    //window.XMLHttpRequest?new XMLHttpRequest(): new ActiveXObject("Microsoft.XMLHTTP");
+    xmlhttp.onreadystatechange = update_virtual_screen;
+    xmlhttp.open("GET", url);
+    xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
+    xmlhttp.send(null);
+}
+function update_virtual_screen()
+{
+    if ((xmlhttp.readyState == 4) && (xmlhttp.status == 200))
+    {
+        var screen_text = xmlhttp.responseText;
+        document.form["screen_text"].value = screen_text;
+        //var json_data = json_parse(xmlhttp.responseText);
+    }
+}
+function poll()
+{
+    refresh_screen();
+    timerID  = setTimeout("poll()", 2000);
+    // clearTimeout(timerID);
+}
+//function start_server (username, password)
+//{
+//    load_url_to_screen('cgishell.cgi?ajax=serverstart&username=' + escape(username) + '&password=' + escape(password);
+//}
+function refresh_screen()
+{
+    load_url_to_screen('cgishell.cgi?ajax=refresh&sid=%(SID)s');
+}
+function query_hash()
+{
+    load_url_to_screen('cgishell.cgi?ajax=hash&sid=%(SID)s');
+}
+function query_cursor()
+{
+    load_url_to_screen('cgishell.cgi?ajax=cursor&sid=%(SID)s');
+}
+function exit_server()
+{
+    load_url_to_screen('cgishell.cgi?ajax=exit&sid=%(SID)s');
+}
+function type_key (chars)
+{
+    var ch = '?';
+    if (flag_shiftlock || flag_shift)
+    {
+        ch = chars.substr(1,1);
+    }
+    else if (flag_ctrl)
+    {
+        ch = chars.substr(2,1);
+    }
+    else
+    {
+        ch = chars.substr(0,1);
+    }
+    load_url_to_screen('cgishell.cgi?ajax=send&sid=%(SID)s&arg=' + escape(ch));
+    if (flag_shift || flag_ctrl)
+    {
+        flag_shift = 0;
+        flag_ctrl = 0;
+    }
+    update_button_colors();
+}
+
+function key_shiftlock()
+{
+    flag_ctrl = 0;
+    flag_shift = 0;
+    if (flag_shiftlock)
+    {
+        flag_shiftlock = 0;
+    }
+    else
+    {
+        flag_shiftlock = 1;
+    }
+    update_button_colors();
+}
+
+function key_shift()
+{
+    if (flag_shift)
+    {
+        flag_shift = 0;
+    }
+    else
+    {
+        flag_ctrl = 0;
+        flag_shiftlock = 0;
+        flag_shift = 1;
+    }
+    update_button_colors(); 
+}
+function key_ctrl ()
+{
+    if (flag_ctrl)
+    {
+        flag_ctrl = 0;
+    }
+    else
+    {
+        flag_ctrl = 1;
+        flag_shiftlock = 0;
+        flag_shift = 0;
+    }
+    
+    update_button_colors();
+}
+function update_button_colors ()
+{
+    if (flag_ctrl)
+    {
+        document.form['Ctrl'].style.backgroundColor = ButtonOnColor;
+        document.form['Ctrl2'].style.backgroundColor = ButtonOnColor;
+    }
+    else
+    {
+        document.form['Ctrl'].style.backgroundColor = document.form.style.backgroundColor;
+        document.form['Ctrl2'].style.backgroundColor = document.form.style.backgroundColor;
+    }
+    if (flag_shift)
+    {
+        document.form['Shift'].style.backgroundColor = ButtonOnColor;
+        document.form['Shift2'].style.backgroundColor = ButtonOnColor;
+    }
+    else
+    {
+        document.form['Shift'].style.backgroundColor = document.form.style.backgroundColor;
+        document.form['Shift2'].style.backgroundColor = document.form.style.backgroundColor;
+    }
+    if (flag_shiftlock)
+    {
+        document.form['ShiftLock'].style.backgroundColor = ButtonOnColor;
+    }
+    else
+    {
+        document.form['ShiftLock'].style.backgroundColor = document.form.style.backgroundColor;
+    }
+    
+}
+function keyHandler(e)
+{
+    var pressedKey;
+    if (document.all)    { e = window.event; }
+    if (document.layers) { pressedKey = e.which; }
+    if (document.all)    { pressedKey = e.keyCode; }
+    pressedCharacter = String.fromCharCode(pressedKey);
+    type_key(pressedCharacter+pressedCharacter+pressedCharacter);
+    alert(pressedCharacter);
+//    alert(' Character = ' + pressedCharacter + ' [Decimal value = ' + pressedKey + ']');
+}
+//document.onkeypress = keyHandler;
+//if (document.layers)
+//    document.captureEvents(Event.KEYPRESS);
+//http://sniptools.com/jskeys
+//document.onkeyup = KeyCheck;       
+function KeyCheck(e)
+{
+    var KeyID = (window.event) ? event.keyCode : e.keyCode;
+    type_key(String.fromCharCode(KeyID));
+    e.cancelBubble = true;
+    window.event.cancelBubble = true;
+}
+</script>
+
+</head>
+
+<body onload="init()">
+<form id="form" name="form" action="/cgi-bin/cgishell.cgi" method="POST">
+<input name="sid" value="%(SID)s" type="hidden">
+<textarea name="screen_text" cols="81" rows="25">%(SHELL_OUTPUT)s</textarea>
+<hr noshade="1">
+ <input name="cli" id="cli" type="text" size="80"><br>
+<table border="0" align="left">
+<tr>
+<td width="86%%" align="center">    
+    <input name="submit" type="submit" value="Submit">
+    <input name="refresh" type="button" value="REFRESH" onclick="refresh_screen()">
+    <input name="refresh" type="button" value="CURSOR" onclick="query_cursor()">
+    <input name="hash" type="button" value="HASH" onclick="query_hash()">
+    <input name="exit" type="button" value="EXIT" onclick="exit_server()">
+    <br>
+    <input type="button" value="Esc" onclick="type_key('\\x1b\\x1b')" />
+    <input type="button" value="` ~" onclick="type_key('`~')" />
+    <input type="button" value="1!" onclick="type_key('1!')" />
+    <input type="button" value="2@" onclick="type_key('2@\\x00')" />
+    <input type="button" value="3#" onclick="type_key('3#')" />
+    <input type="button" value="4$" onclick="type_key('4$')" />
+    <input type="button" value="5%%" onclick="type_key('5%%')" />
+    <input type="button" value="6^" onclick="type_key('6^\\x1E')" />
+    <input type="button" value="7&" onclick="type_key('7&')" />
+    <input type="button" value="8*" onclick="type_key('8*')" />
+    <input type="button" value="9(" onclick="type_key('9(')" />
+    <input type="button" value="0)" onclick="type_key('0)')" />
+    <input type="button" value="-_" onclick="type_key('-_\\x1F')" />
+    <input type="button" value="=+" onclick="type_key('=+')" />
+    <input type="button" value="BkSp" onclick="type_key('\\x08\\x08\\x08')" />
+    <br>
+    <input type="button" value="Tab" onclick="type_key('\\t\\t')" />
+    <input type="button" value="Q" onclick="type_key('qQ\\x11')" />
+    <input type="button" value="W" onclick="type_key('wW\\x17')" />
+    <input type="button" value="E" onclick="type_key('eE\\x05')" />
+    <input type="button" value="R" onclick="type_key('rR\\x12')" />
+    <input type="button" value="T" onclick="type_key('tT\\x14')" />
+    <input type="button" value="Y" onclick="type_key('yY\\x19')" />
+    <input type="button" value="U" onclick="type_key('uU\\x15')" />
+    <input type="button" value="I" onclick="type_key('iI\\x09')" />
+    <input type="button" value="O" onclick="type_key('oO\\x0F')" />
+    <input type="button" value="P" onclick="type_key('pP\\x10')" />
+    <input type="button" value="[ {" onclick="type_key('[{\\x1b')" />
+    <input type="button" value="] }" onclick="type_key(']}\\x1d')" />
+    <input type="button" value="\\ |" onclick="type_key('\\\\|\\x1c')" />
+    <br>
+    <input type="button" id="Ctrl" value="Ctrl" onclick="key_ctrl()" />
+    <input type="button" value="A" onclick="type_key('aA\\x01')" />
+    <input type="button" value="S" onclick="type_key('sS\\x13')" />
+    <input type="button" value="D" onclick="type_key('dD\\x04')" />
+    <input type="button" value="F" onclick="type_key('fF\\x06')" />
+    <input type="button" value="G" onclick="type_key('gG\\x07')" />
+    <input type="button" value="H" onclick="type_key('hH\\x08')" />
+    <input type="button" value="J" onclick="type_key('jJ\\x0A')" />
+    <input type="button" value="K" onclick="type_key('kK\\x0B')" />
+    <input type="button" value="L" onclick="type_key('lL\\x0C')" />
+    <input type="button" value="; :" onclick="type_key(';:')" />
+    <input type="button" id="quote" value="'" onclick="type_key('\\x27\\x22')" />
+    <input type="button" value="Enter" onclick="type_key('\\n\\n')" />
+    <br>
+    <input type="button" id="ShiftLock" value="Caps Lock" onclick="key_shiftlock()" />
+    <input type="button" id="Shift" value="Shift" onclick="key_shift()"  />
+    <input type="button" value="Z" onclick="type_key('zZ\\x1A')" />
+    <input type="button" value="X" onclick="type_key('xX\\x18')" />
+    <input type="button" value="C" onclick="type_key('cC\\x03')" />
+    <input type="button" value="V" onclick="type_key('vV\\x16')" />
+    <input type="button" value="B" onclick="type_key('bB\\x02')" />
+    <input type="button" value="N" onclick="type_key('nN\\x0E')" />
+    <input type="button" value="M" onclick="type_key('mM\\x0D')" />
+    <input type="button" value=", <" onclick="type_key(',<')" />
+    <input type="button" value=". >" onclick="type_key('.>')" />
+    <input type="button" value="/ ?" onclick="type_key('/?')" />
+    <input type="button" id="Shift2" value="Shift" onclick="key_shift()" />
+    <input type="button" id="Ctrl2" value="Ctrl" onclick="key_ctrl()" />
+    <br>
+    <input type="button" value="        FINAL FRONTIER        " onclick="type_key('  ')" />
+</td>
+</tr>
+</table>  
+</form>
+</body>
+</html>
+"""
+
+LOGIN_HTML="""<html>
+<head>
+<title>Shell Login</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<style type=text/css>
+a {color: #9f9; text-decoration: none}
+a:hover {color: #0f0}
+hr {color: #0f0}
+html,body,textarea,input,form
+{
+font-family: "Courier New", Courier, mono;
+font-size: 8pt;
+color: #0c0;
+background-color: #020;
+margin:3;
+padding:0;
+border:0;
+}
+input { background-color: #010; }
+input,textarea {
+border-width:1;
+border-style:solid;
+border-color:#0c0;
+padding:3;
+margin:3;
+}
+</style>
+<script language="JavaScript">
+function init ()
+{
+    document.login_form["username"].focus();
+}
+</script>
+</head>
+<body onload="init()">
+<form name="login_form" method="POST">
+<input name="start_server" value="1" type="hidden">
+<input name="sid" value="%(SID)s" type="hidden">
+username: <input name="username" type="text" size="30"><br>
+password: <input name="password" type="password" size="30"><br>
+<input name="submit" type="submit" value="enter">
+</form>
+<br>
+</body>
+</html>
+"""
+
+if __name__ == "__main__":
+    try:
+        main()
+    except Exception as e:
+        print(str(e))
+        tb_dump = traceback.format_exc()
+        print(str(tb_dump))
+
diff --git a/third_party/pexpect/examples/chess.py b/third_party/pexpect/examples/chess.py
new file mode 100755
index 0000000..421727d
--- /dev/null
+++ b/third_party/pexpect/examples/chess.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+
+'''This demonstrates controlling a screen oriented application (curses).
+It starts two instances of gnuchess and then pits them against each other.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import pexpect
+import ANSI
+
+REGEX_MOVE = '(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)'
+REGEX_MOVE_PART = '(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)'
+
+class Chess:
+
+    def __init__(self, engine = "/usr/local/bin/gnuchess -a -h 1"):
+        self.child = pexpect.spawn (engine)
+        self.term = ANSI.ANSI ()
+
+        self.child.expect ('Chess')
+        if self.child.after != 'Chess':
+            raise IOError('incompatible chess program')
+        self.term.process_list (self.before)
+        self.term.process_list (self.after)
+        self.last_computer_move = ''
+
+    def read_until_cursor (self, r,c):
+        while 1:
+            self.child.read(1, 60)
+            self.term.process (c)
+            if self.term.cur_r == r and self.term.cur_c == c:
+                return 1
+
+    def do_first_move (self, move):
+        self.child.expect ('Your move is')
+        self.child.sendline (move)
+        self.term.process_list (self.before)
+        self.term.process_list (self.after)
+        return move
+
+    def do_move (self, move):
+        self.read_until_cursor (19,60)
+        self.child.sendline (move)
+        return move
+
+    def get_first_computer_move (self):
+        self.child.expect ('My move is')
+        self.child.expect (REGEX_MOVE)
+        return self.child.after
+
+    def get_computer_move (self):
+        print('Here')
+        i = self.child.expect (['\[17;59H', '\[17;58H'])
+        print(i)
+        if i == 0:
+            self.child.expect (REGEX_MOVE)
+            if len(self.child.after) < 4:
+                self.child.after = self.child.after + self.last_computer_move[3]
+        if i == 1:
+            self.child.expect (REGEX_MOVE_PART)
+            self.child.after = self.last_computer_move[0] + self.child.after
+        print('', self.child.after)
+        self.last_computer_move = self.child.after
+        return self.child.after
+
+    def switch (self):
+        self.child.sendline ('switch')
+
+    def set_depth (self, depth):
+        self.child.sendline ('depth')
+        self.child.expect ('depth=')
+        self.child.sendline ('%d' % depth)
+
+    def quit(self):
+        self.child.sendline ('quit')
+import sys
+print('Starting...')
+white = Chess()
+white.child.echo = 1
+white.child.expect ('Your move is')
+white.set_depth(2)
+white.switch()
+
+move_white = white.get_first_computer_move()
+print('first move white:', move_white)
+
+white.do_move ('e7e5')
+move_white = white.get_computer_move()
+print('move white:', move_white)
+white.do_move ('f8c5')
+move_white = white.get_computer_move()
+print('move white:', move_white)
+white.do_move ('b8a6')
+move_white = white.get_computer_move()
+print('move white:', move_white)
+
+sys.exit(1)
+
+
+
+black = Chess()
+white = Chess()
+white.child.expect ('Your move is')
+white.switch()
+
+move_white = white.get_first_computer_move()
+print('first move white:', move_white)
+
+black.do_first_move (move_white)
+move_black = black.get_first_computer_move()
+print('first move black:', move_black)
+
+white.do_move (move_black)
+
+done = 0
+while not done:
+    move_white = white.get_computer_move()
+    print('move white:', move_white)
+
+    black.do_move (move_white)
+    move_black = black.get_computer_move()
+    print('move black:', move_black)
+
+    white.do_move (move_black)
+    print('tail of loop')
+
+g.quit()
diff --git a/third_party/pexpect/examples/chess2.py b/third_party/pexpect/examples/chess2.py
new file mode 100755
index 0000000..b92509e
--- /dev/null
+++ b/third_party/pexpect/examples/chess2.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+
+'''This demonstrates controlling a screen oriented application (curses).
+It starts two instances of gnuchess and then pits them against each other.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import pexpect
+import ANSI
+import sys
+import time
+
+class Chess:
+
+        def __init__(self, engine = "/usr/local/bin/gnuchess -a -h 1"):
+                self.child = pexpect.spawn (engine)
+                self.term = ANSI.ANSI ()
+
+                #self.child.expect ('Chess')
+                #if self.child.after != 'Chess':
+                #        raise IOError, 'incompatible chess program'
+                #self.term.process_list (self.child.before)
+                #self.term.process_list (self.child.after)
+
+                self.last_computer_move = ''
+
+        def read_until_cursor (self, r,c, e=0):
+            '''Eventually something like this should move into the screen class or
+            a subclass. Maybe a combination of pexpect and screen...
+            '''
+            fout = open ('log','a')
+            while self.term.cur_r != r or self.term.cur_c != c:
+                try:
+                    k = self.child.read(1, 10)
+                except Exception as e:
+                    print('EXCEPTION, (r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c))
+                    sys.stdout.flush()
+                self.term.process (k)
+                fout.write ('(r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c))
+                fout.flush()
+                if e:
+                    sys.stdout.write (k)
+                    sys.stdout.flush()
+                if self.term.cur_r == r and self.term.cur_c == c:
+                    fout.close()
+                    return 1
+            print('DIDNT EVEN HIT.')
+            fout.close()
+            return 1
+
+        def expect_region (self):
+            '''This is another method that would be moved into the
+            screen class.
+            '''
+            pass
+        def do_scan (self):
+            fout = open ('log','a')
+            while 1:
+                c = self.child.read(1,10)
+                self.term.process (c)
+                fout.write ('(r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c))
+                fout.flush()
+                sys.stdout.write (c)
+                sys.stdout.flush()
+
+        def do_move (self, move, e = 0):
+                time.sleep(1)
+                self.read_until_cursor (19,60, e)
+                self.child.sendline (move)
+
+        def wait (self, color):
+            while 1:
+                r = self.term.get_region (14,50,14,60)[0]
+                r = r.strip()
+                if r == color:
+                    return
+                time.sleep (1)
+
+        def parse_computer_move (self, s):
+                i = s.find ('is: ')
+                cm = s[i+3:i+9]
+                return cm
+        def get_computer_move (self, e = 0):
+                time.sleep(1)
+                self.read_until_cursor (19,60, e)
+                time.sleep(1)
+                r = self.term.get_region (17,50,17,62)[0]
+                cm = self.parse_computer_move (r)
+                return cm
+
+        def switch (self):
+                print('switching')
+                self.child.sendline ('switch')
+
+        def set_depth (self, depth):
+                self.child.sendline ('depth')
+                self.child.expect ('depth=')
+                self.child.sendline ('%d' % depth)
+
+        def quit(self):
+                self.child.sendline ('quit')
+
+def LOG (s):
+    print(s)
+    sys.stdout.flush ()
+    fout = open ('moves.log', 'a')
+    fout.write (s + '\n')
+    fout.close()
+
+print('Starting...')
+
+black = Chess()
+white = Chess()
+white.read_until_cursor (19,60,1)
+white.switch()
+
+done = 0
+while not done:
+    white.wait ('Black')
+    move_white = white.get_computer_move(1)
+    LOG ( 'move white:'+ move_white )
+
+    black.do_move (move_white)
+    black.wait ('White')
+    move_black = black.get_computer_move()
+    LOG ( 'move black:'+ move_black )
+
+    white.do_move (move_black, 1)
+
+g.quit()
+
+
diff --git a/third_party/pexpect/examples/chess3.py b/third_party/pexpect/examples/chess3.py
new file mode 100755
index 0000000..dc02663
--- /dev/null
+++ b/third_party/pexpect/examples/chess3.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+
+'''This demonstrates controlling a screen oriented application (curses).
+It starts two instances of gnuchess and then pits them against each other.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import pexpect
+import ANSI
+
+REGEX_MOVE = '(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)'
+REGEX_MOVE_PART = '(?:[0-9]|\x1b\[C)(?:[a-z]|\x1b\[C)(?:[0-9]|\x1b\[C)'
+
+class Chess:
+
+    def __init__(self, engine = "/usr/local/bin/gnuchess -a -h 1"):
+        self.child = pexpect.spawn (engine)
+        self.term = ANSI.ANSI ()
+
+#		self.child.expect ('Chess')
+    #	if self.child.after != 'Chess':
+    #		raise IOError, 'incompatible chess program'
+    #        self.term.process_list (self.before)
+    #        self.term.process_list (self.after)
+        self.last_computer_move = ''
+    def read_until_cursor (self, r,c):
+        fout = open ('log','a')
+        while 1:
+            k = self.child.read(1, 10)
+            self.term.process (k)
+            fout.write ('(r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c))
+            fout.flush()
+            if self.term.cur_r == r and self.term.cur_c == c:
+                fout.close()
+                return 1
+            sys.stdout.write (k)
+            sys.stdout.flush()
+
+    def do_scan (self):
+        fout = open ('log','a')
+        while 1:
+            c = self.child.read(1,10)
+            self.term.process (c)
+            fout.write ('(r,c):(%d,%d)\n' %(self.term.cur_r, self.term.cur_c))
+            fout.flush()
+            sys.stdout.write (c)
+            sys.stdout.flush()
+
+    def do_move (self, move):
+        self.read_until_cursor (19,60)
+        self.child.sendline (move)
+        return move
+
+    def get_computer_move (self):
+        print('Here')
+        i = self.child.expect (['\[17;59H', '\[17;58H'])
+        print(i)
+        if i == 0:
+            self.child.expect (REGEX_MOVE)
+            if len(self.child.after) < 4:
+                self.child.after = self.child.after + self.last_computer_move[3]
+        if i == 1:
+            self.child.expect (REGEX_MOVE_PART)
+            self.child.after = self.last_computer_move[0] + self.child.after
+        print('', self.child.after)
+        self.last_computer_move = self.child.after
+        return self.child.after
+
+    def switch (self):
+        self.child.sendline ('switch')
+
+    def set_depth (self, depth):
+        self.child.sendline ('depth')
+        self.child.expect ('depth=')
+        self.child.sendline ('%d' % depth)
+
+    def quit(self):
+        self.child.sendline ('quit')
+import sys
+print('Starting...')
+white = Chess()
+white.do_move('b2b4')
+white.read_until_cursor (19,60)
+c1 = white.term.get_abs(17,58)
+c2 = white.term.get_abs(17,59)
+c3 = white.term.get_abs(17,60)
+c4 = white.term.get_abs(17,61)
+fout = open ('log','a')
+fout.write ('Computer:%s%s%s%s\n' %(c1,c2,c3,c4))
+fout.close()
+white.do_move('c2c4')
+white.read_until_cursor (19,60)
+c1 = white.term.get_abs(17,58)
+c2 = white.term.get_abs(17,59)
+c3 = white.term.get_abs(17,60)
+c4 = white.term.get_abs(17,61)
+fout = open ('log','a')
+fout.write ('Computer:%s%s%s%s\n' %(c1,c2,c3,c4))
+fout.close()
+white.do_scan ()
+
+#white.do_move ('b8a6')
+#move_white = white.get_computer_move()
+#print 'move white:', move_white
+
+sys.exit(1)
+
+
+
+black = Chess()
+white = Chess()
+white.child.expect ('Your move is')
+white.switch()
+
+move_white = white.get_first_computer_move()
+print('first move white:', move_white)
+
+black.do_first_move (move_white)
+move_black = black.get_first_computer_move()
+print('first move black:', move_black)
+
+white.do_move (move_black)
+
+done = 0
+while not done:
+    move_white = white.get_computer_move()
+    print('move white:', move_white)
+
+    black.do_move (move_white)
+    move_black = black.get_computer_move()
+    print('move black:', move_black)
+
+    white.do_move (move_black)
+    print('tail of loop')
+
+g.quit()
diff --git a/third_party/pexpect/examples/df.py b/third_party/pexpect/examples/df.py
new file mode 100755
index 0000000..4faa038
--- /dev/null
+++ b/third_party/pexpect/examples/df.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+'''This collects filesystem capacity info using the 'df' command. Tuples of
+filesystem name and percentage are stored in a list. A simple report is
+printed. Filesystems over 95% capacity are highlighted. Note that this does not
+parse filesystem names after the first space, so names with spaces in them will
+be truncated. This will produce ambiguous results for automount filesystems on
+Apple OSX.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import pexpect
+
+child = pexpect.spawn ('df')
+
+# parse 'df' output into a list.
+pattern = "\n(\S+).*?([0-9]+)%"
+filesystem_list = []
+for dummy in range (0, 1000):
+    i = child.expect ([pattern, pexpect.EOF])
+    if i == 0:
+        filesystem_list.append (child.match.groups())
+    else:
+        break
+
+# Print report
+print()
+for m in filesystem_list:
+    s = "Filesystem %s is at %s%%" % (m[0], m[1])
+    # highlight filesystems over 95% capacity
+    if int(m[1]) > 95:
+        s = '! ' + s
+    else:
+        s = '  ' + s
+    print(s)
+
diff --git a/third_party/pexpect/examples/ftp.py b/third_party/pexpect/examples/ftp.py
new file mode 100755
index 0000000..a1c1343
--- /dev/null
+++ b/third_party/pexpect/examples/ftp.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+
+'''This demonstrates an FTP "bookmark". This connects to an ftp site; does a
+few ftp stuff; and then gives the user interactive control over the session. In
+this case the "bookmark" is to a directory on the OpenBSD ftp server. It puts
+you in the i386 packages directory. You can easily modify this for other sites.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import absolute_import
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import pexpect
+import sys
+
+# Note that, for Python 3 compatibility reasons, we are using spawnu and
+# importing unicode_literals (above). spawnu accepts Unicode input and
+# unicode_literals makes all string literals in this script Unicode by default.
+child = pexpect.spawnu('ftp ftp.openbsd.org')
+
+child.expect('(?i)name .*: ')
+child.sendline('anonymous')
+child.expect('(?i)password')
+child.sendline('pexpect at sourceforge.net')
+child.expect('ftp> ')
+child.sendline('cd /pub/OpenBSD/3.7/packages/i386')
+child.expect('ftp> ')
+child.sendline('bin')
+child.expect('ftp> ')
+child.sendline('prompt')
+child.expect('ftp> ')
+child.sendline('pwd')
+child.expect('ftp> ')
+print("Escape character is '^]'.\n")
+sys.stdout.write (child.after)
+sys.stdout.flush()
+child.interact() # Escape character defaults to ^]
+# At this point this script blocks until the user presses the escape character
+# or until the child exits. The human user and the child should be talking
+# to each other now.
+
+# At this point the script is running again.
+print('Left interactve mode.')
+
+# The rest is not strictly necessary. This just demonstrates a few functions.
+# This makes sure the child is dead; although it would be killed when Python exits.
+if child.isalive():
+    child.sendline('bye') # Try to ask ftp child to exit.
+    child.close()
+# Print the final state of the child. Normally isalive() should be FALSE.
+if child.isalive():
+    print('Child did not exit gracefully.')
+else:
+    print('Child exited gracefully.')
+
diff --git a/third_party/pexpect/examples/hive.py b/third_party/pexpect/examples/hive.py
new file mode 100755
index 0000000..00ddbea
--- /dev/null
+++ b/third_party/pexpect/examples/hive.py
@@ -0,0 +1,466 @@
+#!/usr/bin/env python
+
+'''hive -- Hive Shell
+
+This lets you ssh to a group of servers and control them as if they were one.
+Each command you enter is sent to each host in parallel. The response of each
+host is collected and printed. In normal synchronous mode Hive will wait for
+each host to return the shell command line prompt. The shell prompt is used to
+sync output.
+
+Example:
+
+    $ hive.py --sameuser --samepass host1.example.com host2.example.net
+    username: myusername
+    password:
+    connecting to host1.example.com - OK
+    connecting to host2.example.net - OK
+    targetting hosts: 192.168.1.104 192.168.1.107
+    CMD (? for help) > uptime
+    =======================================================================
+    host1.example.com
+    -----------------------------------------------------------------------
+    uptime
+    23:49:55 up 74 days,  5:14,  2 users,  load average: 0.15, 0.05, 0.01
+    =======================================================================
+    host2.example.net
+    -----------------------------------------------------------------------
+    uptime
+    23:53:02 up 1 day, 13:36,  2 users,  load average: 0.50, 0.40, 0.46
+    =======================================================================
+
+Other Usage Examples:
+
+1. You will be asked for your username and password for each host.
+
+    hive.py host1 host2 host3 ... hostN
+
+2. You will be asked once for your username and password.
+   This will be used for each host.
+
+    hive.py --sameuser --samepass host1 host2 host3 ... hostN
+
+3. Give a username and password on the command-line:
+
+    hive.py user1:pass2 at host1 user2:pass2 at host2 ... userN:passN at hostN
+
+You can use an extended host notation to specify username, password, and host
+instead of entering auth information interactively. Where you would enter a
+host name use this format:
+
+    username:password at host
+
+This assumes that ':' is not part of the password. If your password contains a
+':' then you can use '\\:' to indicate a ':' and '\\\\' to indicate a single
+'\\'. Remember that this information will appear in the process listing. Anyone
+on your machine can see this auth information. This is not secure.
+
+This is a crude script that begs to be multithreaded. But it serves its
+purpose.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+# TODO add feature to support username:password at host combination
+# TODO add feature to log each host output in separate file
+
+import sys
+import os
+import re
+import optparse
+import time
+import getpass
+import readline
+import atexit
+try:
+    import pexpect
+    import pxssh
+except ImportError:
+    sys.stderr.write("You do not have 'pexpect' installed.\n")
+    sys.stderr.write("On Ubuntu you need the 'python-pexpect' package.\n")
+    sys.stderr.write("    aptitude -y install python-pexpect\n")
+    exit(1)
+
+
+try:
+    raw_input
+except NameError:
+    raw_input = input
+
+
+histfile = os.path.join(os.environ["HOME"], ".hive_history")
+try:
+    readline.read_history_file(histfile)
+except IOError:
+    pass
+atexit.register(readline.write_history_file, histfile)
+
+CMD_HELP='''Hive commands are preceded by a colon : (just think of vi).
+
+:target name1 name2 name3 ...
+
+    set list of hosts to target commands
+
+:target all
+
+    reset list of hosts to target all hosts in the hive.
+
+:to name command
+
+    send a command line to the named host. This is similar to :target, but
+    sends only one command and does not change the list of targets for future
+    commands.
+
+:sync
+
+    set mode to wait for shell prompts after commands are run. This is the
+    default. When Hive first logs into a host it sets a special shell prompt
+    pattern that it can later look for to synchronize output of the hosts. If
+    you 'su' to another user then it can upset the synchronization. If you need
+    to run something like 'su' then use the following pattern:
+
+    CMD (? for help) > :async
+    CMD (? for help) > sudo su - root
+    CMD (? for help) > :prompt
+    CMD (? for help) > :sync
+
+:async
+
+    set mode to not expect command line prompts (see :sync). Afterwards
+    commands are send to target hosts, but their responses are not read back
+    until :sync is run. This is useful to run before commands that will not
+    return with the special shell prompt pattern that Hive uses to synchronize.
+
+:refresh
+
+    refresh the display. This shows the last few lines of output from all hosts.
+    This is similar to resync, but does not expect the promt. This is useful
+    for seeing what hosts are doing during long running commands.
+
+:resync
+
+    This is similar to :sync, but it does not change the mode. It looks for the
+    prompt and thus consumes all input from all targetted hosts.
+
+:prompt
+
+    force each host to reset command line prompt to the special pattern used to
+    synchronize all the hosts. This is useful if you 'su' to a different user
+    where Hive would not know the prompt to match.
+
+:send my text
+
+    This will send the 'my text' wihtout a line feed to the targetted hosts.
+    This output of the hosts is not automatically synchronized.
+
+:control X
+
+    This will send the given control character to the targetted hosts.
+    For example, ":control c" will send ASCII 3.
+
+:exit
+
+    This will exit the hive shell.
+
+'''
+
+def login (args, cli_username=None, cli_password=None):
+
+    # I have to keep a separate list of host names because Python dicts are not ordered.
+    # I want to keep the same order as in the args list.
+    host_names = []
+    hive_connect_info = {}
+    hive = {}
+    # build up the list of connection information (hostname, username, password, port)
+    for host_connect_string in args:
+        hcd = parse_host_connect_string (host_connect_string)
+        hostname = hcd['hostname']
+        port     = hcd['port']
+        if port == '':
+            port = None
+        if len(hcd['username']) > 0:
+            username = hcd['username']
+        elif cli_username is not None:
+            username = cli_username
+        else:
+            username = raw_input('%s username: ' % hostname)
+        if len(hcd['password']) > 0:
+            password = hcd['password']
+        elif cli_password is not None:
+            password = cli_password
+        else:
+            password = getpass.getpass('%s password: ' % hostname)
+        host_names.append(hostname)
+        hive_connect_info[hostname] = (hostname, username, password, port)
+    # build up the list of hive connections using the connection information.
+    for hostname in host_names:
+        print('connecting to', hostname)
+        try:
+            fout = file("log_"+hostname, "w")
+            hive[hostname] = pxssh.pxssh()
+            # Disable host key checking.
+            hive[hostname].SSH_OPTS = (hive[hostname].SSH_OPTS
+                    + " -o 'StrictHostKeyChecking=no'"
+                    + " -o 'UserKnownHostsFile /dev/null' ")
+            hive[hostname].force_password = True
+            hive[hostname].login(*hive_connect_info[hostname])
+            print(hive[hostname].before)
+            hive[hostname].logfile = fout
+            print('- OK')
+        except Exception as e:
+            print('- ERROR', end=' ')
+            print(str(e))
+            print('Skipping', hostname)
+            hive[hostname] = None
+    return host_names, hive
+
+def main ():
+
+    global options, args, CMD_HELP
+
+    rows = 24
+    cols = 80
+
+    if options.sameuser:
+        cli_username = raw_input('username: ')
+    else:
+        cli_username = None
+
+    if options.samepass:
+        cli_password = getpass.getpass('password: ')
+    else:
+        cli_password = None
+
+    host_names, hive = login(args, cli_username, cli_password)
+
+    synchronous_mode = True
+    target_hostnames = host_names[:]
+    print('targetting hosts:', ' '.join(target_hostnames))
+    while True:
+        cmd = raw_input('CMD (? for help) > ')
+        cmd = cmd.strip()
+        if cmd=='?' or cmd==':help' or cmd==':h':
+            print(CMD_HELP)
+            continue
+        elif cmd==':refresh':
+            refresh (hive, target_hostnames, timeout=0.5)
+            for hostname in target_hostnames:
+                print('/' + '=' * (cols - 2))
+                print('| ' + hostname)
+                print('\\' + '-' * (cols - 2))
+                if hive[hostname] is None:
+                    print('# DEAD: %s' % hostname)
+                else:
+                    print(hive[hostname].before)
+            print('#' * 79)
+            continue
+        elif cmd==':resync':
+            resync (hive, target_hostnames, timeout=0.5)
+            for hostname in target_hostnames:
+                print('/' + '=' * (cols - 2))
+                print('| ' + hostname)
+                print('\\' + '-' * (cols - 2))
+                if hive[hostname] is None:
+                    print('# DEAD: %s' % hostname)
+                else:
+                    print(hive[hostname].before)
+            print('#' * 79)
+            continue
+        elif cmd==':sync':
+            synchronous_mode = True
+            resync (hive, target_hostnames, timeout=0.5)
+            continue
+        elif cmd==':async':
+            synchronous_mode = False
+            continue
+        elif cmd==':prompt':
+            for hostname in target_hostnames:
+                try:
+                    if hive[hostname] is not None:
+                        hive[hostname].set_unique_prompt()
+                except Exception as e:
+                    print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+                    print(str(e))
+                    hive[hostname] = None
+            continue
+        elif cmd[:5] == ':send':
+            cmd, txt = cmd.split(None,1)
+            for hostname in target_hostnames:
+                try:
+                    if hive[hostname] is not None:
+                        hive[hostname].send(txt)
+                except Exception as e:
+                    print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+                    print(str(e))
+                    hive[hostname] = None
+            continue
+        elif cmd[:3] == ':to':
+            cmd, hostname, txt = cmd.split(None,2)
+            print('/' + '=' * (cols - 2))
+            print('| ' + hostname)
+            print('\\' + '-' * (cols - 2))
+            if hive[hostname] is None:
+                print('# DEAD: %s' % hostname)
+                continue
+            try:
+                hive[hostname].sendline (txt)
+                hive[hostname].prompt(timeout=2)
+                print(hive[hostname].before)
+            except Exception as e:
+                print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+                print(str(e))
+                hive[hostname] = None
+            continue
+        elif cmd[:7] == ':expect':
+            cmd, pattern = cmd.split(None,1)
+            print('looking for', pattern)
+            try:
+                for hostname in target_hostnames:
+                    if hive[hostname] is not None:
+                        hive[hostname].expect(pattern)
+                        print(hive[hostname].before)
+            except Exception as e:
+                print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+                print(str(e))
+                hive[hostname] = None
+            continue
+        elif cmd[:7] == ':target':
+            target_hostnames = cmd.split()[1:]
+            if len(target_hostnames) == 0 or target_hostnames[0] == all:
+                target_hostnames = host_names[:]
+            print('targetting hosts:', ' '.join(target_hostnames))
+            continue
+        elif cmd == ':exit' or cmd == ':q' or cmd == ':quit':
+            break
+        elif cmd[:8] == ':control' or cmd[:5] == ':ctrl' :
+            cmd, c = cmd.split(None,1)
+            if ord(c)-96 < 0 or ord(c)-96 > 255:
+                print('/' + '=' * (cols - 2))
+                print('| Invalid character. Must be [a-zA-Z], @, [, ], \\, ^, _, or ?')
+                print('\\' + '-' * (cols - 2))
+                continue
+            for hostname in target_hostnames:
+                try:
+                    if hive[hostname] is not None:
+                        hive[hostname].sendcontrol(c)
+                except Exception as e:
+                    print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+                    print(str(e))
+                    hive[hostname] = None
+            continue
+        elif cmd == ':esc':
+            for hostname in target_hostnames:
+                if hive[hostname] is not None:
+                    hive[hostname].send(chr(27))
+            continue
+        #
+        # Run the command on all targets in parallel
+        #
+        for hostname in target_hostnames:
+            try:
+                if hive[hostname] is not None:
+                    hive[hostname].sendline (cmd)
+            except Exception as e:
+                print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+                print(str(e))
+                hive[hostname] = None
+
+        #
+        # print the response for each targeted host.
+        #
+        if synchronous_mode:
+            for hostname in target_hostnames:
+                try:
+                    print('/' + '=' * (cols - 2))
+                    print('| ' + hostname)
+                    print('\\' + '-' * (cols - 2))
+                    if hive[hostname] is None:
+                        print('# DEAD: %s' % hostname)
+                    else:
+                        hive[hostname].prompt(timeout=2)
+                        print(hive[hostname].before)
+                except Exception as e:
+                    print("Had trouble communicating with %s, so removing it from the target list." % hostname)
+                    print(str(e))
+                    hive[hostname] = None
+            print('#' * 79)
+
+def refresh (hive, hive_names, timeout=0.5):
+
+    '''This waits for the TIMEOUT on each host.
+    '''
+
+    # TODO This is ideal for threading.
+    for hostname in hive_names:
+        if hive[hostname] is not None:
+            hive[hostname].expect([pexpect.TIMEOUT,pexpect.EOF],timeout=timeout)
+
+def resync (hive, hive_names, timeout=2, max_attempts=5):
+
+    '''This waits for the shell prompt for each host in an effort to try to get
+    them all to the same state. The timeout is set low so that hosts that are
+    already at the prompt will not slow things down too much. If a prompt match
+    is made for a hosts then keep asking until it stops matching. This is a
+    best effort to consume all input if it printed more than one prompt. It's
+    kind of kludgy. Note that this will always introduce a delay equal to the
+    timeout for each machine. So for 10 machines with a 2 second delay you will
+    get AT LEAST a 20 second delay if not more. '''
+
+    # TODO This is ideal for threading.
+    for hostname in hive_names:
+        if hive[hostname] is not None:
+            for attempts in range(0, max_attempts):
+                if not hive[hostname].prompt(timeout=timeout):
+                    break
+
+def parse_host_connect_string (hcs):
+
+    '''This parses a host connection string in the form
+    username:password at hostname:port. All fields are options expcet hostname. A
+    dictionary is returned with all four keys. Keys that were not included are
+    set to empty strings ''. Note that if your password has the '@' character
+    then you must backslash escape it. '''
+
+    if '@' in hcs:
+        p = re.compile (r'(?P<username>[^@:]*)(:?)(?P<password>.*)(?!\\)@(?P<hostname>[^:]*):?(?P<port>[0-9]*)')
+    else:
+        p = re.compile (r'(?P<username>)(?P<password>)(?P<hostname>[^:]*):?(?P<port>[0-9]*)')
+    m = p.search (hcs)
+    d = m.groupdict()
+    d['password'] = d['password'].replace('\\@','@')
+    return d
+
+if __name__ == '__main__':
+    start_time = time.time()
+    parser = optparse.OptionParser(formatter=optparse.TitledHelpFormatter(), usage=globals()['__doc__'], version='$Id: hive.py 533 2012-10-20 02:19:33Z noah $',conflict_handler="resolve")
+    parser.add_option ('-v', '--verbose', action='store_true', default=False, help='verbose output')
+    parser.add_option ('--samepass', action='store_true', default=False, help='Use same password for each login.')
+    parser.add_option ('--sameuser', action='store_true', default=False, help='Use same username for each login.')
+    (options, args) = parser.parse_args()
+    if len(args) < 1:
+        parser.error ('missing argument')
+    if options.verbose: print(time.asctime())
+    main()
+    if options.verbose: print(time.asctime())
+    if options.verbose: print('TOTAL TIME IN MINUTES:', end=' ')
+    if options.verbose: print((time.time() - start_time) / 60.0)
diff --git a/third_party/pexpect/examples/monitor.py b/third_party/pexpect/examples/monitor.py
new file mode 100755
index 0000000..9cb0eaf
--- /dev/null
+++ b/third_party/pexpect/examples/monitor.py
@@ -0,0 +1,229 @@
+#!/usr/bin/env python
+
+''' This runs a sequence of commands on a remote host using SSH. It runs a
+simple system checks such as uptime and free to monitor the state of the remote
+host.
+
+./monitor.py [-s server_hostname] [-u username] [-p password]
+    -s : hostname of the remote server to login to.
+    -u : username to user for login.
+    -p : Password to user for login.
+
+Example:
+    This will print information about the given host:
+        ./monitor.py -s www.example.com -u mylogin -p mypassword
+
+It works like this:
+    Login via SSH (This is the hardest part).
+    Run and parse 'uptime'.
+    Run 'iostat'.
+    Run 'vmstat'.
+    Run 'netstat'
+    Run 'free'.
+    Exit the remote host.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import os, sys, re, getopt, getpass
+import pexpect
+
+
+try:
+    raw_input
+except NameError:
+    raw_input = input
+
+
+#
+# Some constants.
+#
+COMMAND_PROMPT = '[#$] ' ### This is way too simple for industrial use -- we will change is ASAP.
+TERMINAL_PROMPT = '(?i)terminal type\?'
+TERMINAL_TYPE = 'vt100'
+# This is the prompt we get if SSH does not have the remote host's public key stored in the cache.
+SSH_NEWKEY = '(?i)are you sure you want to continue connecting'
+
+def exit_with_usage():
+
+    print(globals()['__doc__'])
+    os._exit(1)
+
+def main():
+
+    global COMMAND_PROMPT, TERMINAL_PROMPT, TERMINAL_TYPE, SSH_NEWKEY
+    ######################################################################
+    ## Parse the options, arguments, get ready, etc.
+    ######################################################################
+    try:
+        optlist, args = getopt.getopt(sys.argv[1:], 'h?s:u:p:', ['help','h','?'])
+    except Exception as e:
+        print(str(e))
+        exit_with_usage()
+    options = dict(optlist)
+    if len(args) > 1:
+        exit_with_usage()
+
+    if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]:
+        print("Help:")
+        exit_with_usage()
+
+    if '-s' in options:
+        host = options['-s']
+    else:
+        host = raw_input('hostname: ')
+    if '-u' in options:
+        user = options['-u']
+    else:
+        user = raw_input('username: ')
+    if '-p' in options:
+        password = options['-p']
+    else:
+        password = getpass.getpass('password: ')
+
+    #
+    # Login via SSH
+    #
+    child = pexpect.spawn('ssh -l %s %s'%(user, host))
+    i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY, COMMAND_PROMPT, '(?i)password'])
+    if i == 0: # Timeout
+        print('ERROR! could not login with SSH. Here is what SSH said:')
+        print(child.before, child.after)
+        print(str(child))
+        sys.exit (1)
+    if i == 1: # In this case SSH does not have the public key cached.
+        child.sendline ('yes')
+        child.expect ('(?i)password')
+    if i == 2:
+        # This may happen if a public key was setup to automatically login.
+        # But beware, the COMMAND_PROMPT at this point is very trivial and
+        # could be fooled by some output in the MOTD or login message.
+        pass
+    if i == 3:
+        child.sendline(password)
+        # Now we are either at the command prompt or
+        # the login process is asking for our terminal type.
+        i = child.expect ([COMMAND_PROMPT, TERMINAL_PROMPT])
+        if i == 1:
+            child.sendline (TERMINAL_TYPE)
+            child.expect (COMMAND_PROMPT)
+    #
+    # Set command prompt to something more unique.
+    #
+    COMMAND_PROMPT = "\[PEXPECT\]\$ "
+    child.sendline ("PS1='[PEXPECT]\$ '") # In case of sh-style
+    i = child.expect ([pexpect.TIMEOUT, COMMAND_PROMPT], timeout=10)
+    if i == 0:
+        print("# Couldn't set sh-style prompt -- trying csh-style.")
+        child.sendline ("set prompt='[PEXPECT]\$ '")
+        i = child.expect ([pexpect.TIMEOUT, COMMAND_PROMPT], timeout=10)
+        if i == 0:
+            print("Failed to set command prompt using sh or csh style.")
+            print("Response was:")
+            print(child.before)
+            sys.exit (1)
+
+    # Now we should be at the command prompt and ready to run some commands.
+    print('---------------------------------------')
+    print('Report of commands run on remote host.')
+    print('---------------------------------------')
+
+    # Run uname.
+    child.sendline ('uname -a')
+    child.expect (COMMAND_PROMPT)
+    print(child.before)
+    if 'linux' in child.before.lower():
+        LINUX_MODE = 1
+    else:
+        LINUX_MODE = 0
+
+    # Run and parse 'uptime'.
+    child.sendline ('uptime')
+    child.expect('up\s+(.*?),\s+([0-9]+) users?,\s+load averages?: ([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9])')
+    duration, users, av1, av5, av15 = child.match.groups()
+    days = '0'
+    hours = '0'
+    mins = '0'
+    if 'day' in duration:
+        child.match = re.search('([0-9]+)\s+day',duration)
+        days = str(int(child.match.group(1)))
+    if ':' in duration:
+        child.match = re.search('([0-9]+):([0-9]+)',duration)
+        hours = str(int(child.match.group(1)))
+        mins = str(int(child.match.group(2)))
+    if 'min' in duration:
+        child.match = re.search('([0-9]+)\s+min',duration)
+        mins = str(int(child.match.group(1)))
+    print()
+    print('Uptime: %s days, %s users, %s (1 min), %s (5 min), %s (15 min)' % (
+        duration, users, av1, av5, av15))
+    child.expect (COMMAND_PROMPT)
+
+    # Run iostat.
+    child.sendline ('iostat')
+    child.expect (COMMAND_PROMPT)
+    print(child.before)
+
+    # Run vmstat.
+    child.sendline ('vmstat')
+    child.expect (COMMAND_PROMPT)
+    print(child.before)
+
+    # Run free.
+    if LINUX_MODE:
+        child.sendline ('free') # Linux systems only.
+        child.expect (COMMAND_PROMPT)
+        print(child.before)
+
+    # Run df.
+    child.sendline ('df')
+    child.expect (COMMAND_PROMPT)
+    print(child.before)
+
+    # Run lsof.
+    child.sendline ('lsof')
+    child.expect (COMMAND_PROMPT)
+    print(child.before)
+
+#    # Run netstat
+#    child.sendline ('netstat')
+#    child.expect (COMMAND_PROMPT)
+#    print child.before
+
+#    # Run MySQL show status.
+#    child.sendline ('mysql -p -e "SHOW STATUS;"')
+#    child.expect (PASSWORD_PROMPT_MYSQL)
+#    child.sendline (password_mysql)
+#    child.expect (COMMAND_PROMPT)
+#    print
+#    print child.before
+
+    # Now exit the remote host.
+    child.sendline ('exit')
+    index = child.expect([pexpect.EOF, "(?i)there are stopped jobs"])
+    if index==1:
+        child.sendline("exit")
+        child.expect(EOF)
+
+if __name__ == "__main__":
+    main()
diff --git a/third_party/pexpect/examples/passmass.py b/third_party/pexpect/examples/passmass.py
new file mode 100755
index 0000000..8f5e21d
--- /dev/null
+++ b/third_party/pexpect/examples/passmass.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+
+'''Change passwords on the named machines. passmass host1 host2 host3 . . .
+Note that login shell prompt on remote machine must end in # or $.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import pexpect
+import sys, getpass
+
+
+try:
+    raw_input
+except NameError:
+    raw_input = input
+
+
+USAGE = '''passmass host1 host2 host3 . . .'''
+COMMAND_PROMPT = '[$#] '
+TERMINAL_PROMPT = r'Terminal type\?'
+TERMINAL_TYPE = 'vt100'
+SSH_NEWKEY = r'Are you sure you want to continue connecting \(yes/no\)\?'
+
+def login(host, user, password):
+
+    child = pexpect.spawn('ssh -l %s %s'%(user, host))
+    fout = file ("LOG.TXT","wb")
+    child.setlog (fout)
+
+    i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY, '[Pp]assword: '])
+    if i == 0: # Timeout
+        print('ERROR!')
+        print('SSH could not login. Here is what SSH said:')
+        print(child.before, child.after)
+        sys.exit (1)
+    if i == 1: # SSH does not have the public key. Just accept it.
+        child.sendline ('yes')
+        child.expect ('[Pp]assword: ')
+    child.sendline(password)
+    # Now we are either at the command prompt or
+    # the login process is asking for our terminal type.
+    i = child.expect (['Permission denied', TERMINAL_PROMPT, COMMAND_PROMPT])
+    if i == 0:
+        print('Permission denied on host:', host)
+        sys.exit (1)
+    if i == 1:
+        child.sendline (TERMINAL_TYPE)
+        child.expect (COMMAND_PROMPT)
+    return child
+
+# (current) UNIX password:
+def change_password(child, user, oldpassword, newpassword):
+
+    child.sendline('passwd')
+    i = child.expect(['[Oo]ld [Pp]assword', '.current.*password', '[Nn]ew [Pp]assword'])
+    # Root does not require old password, so it gets to bypass the next step.
+    if i == 0 or i == 1:
+        child.sendline(oldpassword)
+        child.expect('[Nn]ew [Pp]assword')
+    child.sendline(newpassword)
+    i = child.expect(['[Nn]ew [Pp]assword', '[Rr]etype', '[Rr]e-enter'])
+    if i == 0:
+        print('Host did not like new password. Here is what it said...')
+        print(child.before)
+        child.send (chr(3)) # Ctrl-C
+        child.sendline('') # This should tell remote passwd command to quit.
+        return
+    child.sendline(newpassword)
+
+def main():
+
+    if len(sys.argv) <= 1:
+        print(USAGE)
+        return 1
+
+    user = raw_input('Username: ')
+    password = getpass.getpass('Current Password: ')
+    newpassword = getpass.getpass('New Password: ')
+    newpasswordconfirm = getpass.getpass('Confirm New Password: ')
+    if newpassword != newpasswordconfirm:
+        print('New Passwords do not match.')
+        return 1
+
+    for host in sys.argv[1:]:
+        child = login(host, user, password)
+        if child == None:
+            print('Could not login to host:', host)
+            continue
+        print('Changing password on host:', host)
+        change_password(child, user, password, newpassword)
+        child.expect(COMMAND_PROMPT)
+        child.sendline('exit')
+
+if __name__ == '__main__':
+    main()
diff --git a/third_party/pexpect/examples/python.py b/third_party/pexpect/examples/python.py
new file mode 100755
index 0000000..44c15e1
--- /dev/null
+++ b/third_party/pexpect/examples/python.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+'''This starts the python interpreter; captures the startup message; then gives
+the user interactive control over the session. Why? For fun...
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import absolute_import
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import pexpect
+
+# Don't do this unless you like being John Malkovich
+# c = pexpect.spawnu('/usr/bin/env python ./python.py')
+
+# Note that, for Python 3 compatibility reasons, we are using spawnu and
+# importing unicode_literals (above). spawnu accepts Unicode input and
+# unicode_literals makes all string literals in this script Unicode by default.
+c = pexpect.spawnu('/usr/bin/env python')
+
+c.expect('>>>')
+print('And now for something completely different...')
+print(''.join(reversed((c.before))))
+print('Yes, it\'s python, but it\'s backwards.')
+print()
+print('Escape character is \'^]\'.')
+print(c.after, end=' ')
+c.interact()
+c.kill(1)
+print('is alive:', c.isalive())
+
diff --git a/third_party/pexpect/examples/script.py b/third_party/pexpect/examples/script.py
new file mode 100755
index 0000000..c8b9496
--- /dev/null
+++ b/third_party/pexpect/examples/script.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+
+'''This spawns a sub-shell (bash) and gives the user interactive control. The
+entire shell session is logged to a file called script.log. This behaves much
+like the classic BSD command 'script'.
+
+./script.py [-a] [-c command] {logfilename}
+
+    logfilename : This is the name of the log file. Default is script.log.
+    -a : Append to log file. Default is to overwrite log file.
+    -c : spawn command. Default is to spawn the sh shell.
+
+Example:
+
+    This will start a bash shell and append to the log named my_session.log:
+
+        ./script.py -a -c bash my_session.log
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import os, sys, time, getopt
+import signal, fcntl, termios, struct
+import pexpect
+
+global_pexpect_instance = None # Used by signal handler
+
+def exit_with_usage():
+
+    print(globals()['__doc__'])
+    os._exit(1)
+
+def main():
+
+    ######################################################################
+    # Parse the options, arguments, get ready, etc.
+    ######################################################################
+    try:
+        optlist, args = getopt.getopt(sys.argv[1:], 'h?ac:', ['help','h','?'])
+    except Exception as e:
+        print(str(e))
+        exit_with_usage()
+    options = dict(optlist)
+    if len(args) > 1:
+        exit_with_usage()
+
+    if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]:
+        print("Help:")
+        exit_with_usage()
+
+    if len(args) == 1:
+        script_filename = args[0]
+    else:
+        script_filename = "script.log"
+    if '-a' in options:
+        fout = open(script_filename, "ab")
+    else:
+        fout = open(script_filename, "wb")
+    if '-c' in options:
+        command = options['-c']
+    else:
+        command = "sh"
+
+    # Begin log with date/time in the form CCCCyymm.hhmmss
+    fout.write ('# %4d%02d%02d.%02d%02d%02d \n' % time.localtime()[:-3])
+
+    ######################################################################
+    # Start the interactive session
+    ######################################################################
+    p = pexpect.spawn(command)
+    p.logfile = fout
+    global global_pexpect_instance
+    global_pexpect_instance = p
+    signal.signal(signal.SIGWINCH, sigwinch_passthrough)
+
+    print("Script recording started. Type ^] (ASCII 29) to escape from the script shell.")
+    p.interact(chr(29))
+    fout.close()
+    return 0
+
+def sigwinch_passthrough (sig, data):
+
+    # Check for buggy platforms (see pexpect.setwinsize()).
+    if 'TIOCGWINSZ' in dir(termios):
+        TIOCGWINSZ = termios.TIOCGWINSZ
+    else:
+        TIOCGWINSZ = 1074295912 # assume
+    s = struct.pack ("HHHH", 0, 0, 0, 0)
+    a = struct.unpack ('HHHH', fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ , s))
+    global global_pexpect_instance
+    global_pexpect_instance.setwinsize(a[0],a[1])
+
+if __name__ == "__main__":
+    main()
diff --git a/third_party/pexpect/examples/ssh_tunnel.py b/third_party/pexpect/examples/ssh_tunnel.py
new file mode 100755
index 0000000..d761911
--- /dev/null
+++ b/third_party/pexpect/examples/ssh_tunnel.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+
+'''This starts an SSH tunnel to a given host. If the SSH process ever dies then
+this script will detect that and restart it. I use this under Cygwin to keep
+open encrypted tunnels to port 25 (SMTP), port 143 (IMAP4), and port 110
+(POP3). I set my mail client to talk to localhost and I keep this script
+running in the background.
+
+Note that this is a rather stupid script at the moment because it just looks to
+see if any ssh process is running. It should really make sure that our specific
+ssh process is running. The problem is that ssh is missing a very useful
+feature. It has no way to report the process id of the background daemon that
+it creates with the -f command. This would be a really useful script if I could
+figure a way around this problem.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import print_function
+
+from __future__ import absolute_import
+
+import pexpect
+import getpass
+import time
+
+
+try:
+    raw_input
+except NameError:
+    raw_input = input
+
+
+# SMTP:25 IMAP4:143 POP3:110
+tunnel_command = 'ssh -C -N -f -L 25:127.0.0.1:25 -L 143:127.0.0.1:143 -L 110:127.0.0.1:110 %(user)@%(host)'
+host = raw_input('Hostname: ')
+user = raw_input('Username: ')
+X = getpass.getpass('Password: ')
+
+def get_process_info ():
+
+    # This seems to work on both Linux and BSD, but should otherwise be considered highly UNportable.
+
+    ps = pexpect.run ('ps ax -O ppid')
+    pass
+
+def start_tunnel ():
+
+    try:
+        ssh_tunnel = pexpect.spawn (tunnel_command % globals())
+        ssh_tunnel.expect ('password:')
+        time.sleep (0.1)
+        ssh_tunnel.sendline (X)
+        time.sleep (60) # Cygwin is slow to update process status.
+        ssh_tunnel.expect (pexpect.EOF)
+
+    except Exception as e:
+        print(str(e))
+
+def main ():
+
+    while True:
+        ps = pexpect.spawn ('ps')
+        time.sleep (1)
+        index = ps.expect (['/usr/bin/ssh', pexpect.EOF, pexpect.TIMEOUT])
+        if index == 2:
+            print('TIMEOUT in ps command...')
+            print(str(ps))
+            time.sleep (13)
+        if index == 1:
+            print(time.asctime(), end=' ')
+            print('restarting tunnel')
+            start_tunnel ()
+            time.sleep (11)
+            print('tunnel OK')
+        else:
+            # print 'tunnel OK'
+            time.sleep (7)
+
+if __name__ == '__main__':
+
+    main ()
+
+# This was for older SSH versions that didn't have -f option
+#tunnel_command = 'ssh -C -n -L 25:%(host)s:25 -L 110:%(host)s:110 %(user)s@%(host)s -f nothing.sh'
+#nothing_script = '''#!/bin/sh
+#while true; do sleep 53; done
+#'''
+
diff --git a/third_party/pexpect/examples/table_test.html b/third_party/pexpect/examples/table_test.html
new file mode 100644
index 0000000..5dba0ec
--- /dev/null
+++ b/third_party/pexpect/examples/table_test.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<title>TEST</title>
+</head>
+<style type="text/css">
+a {color: #9f9; text-decoration: none}
+a:hover {color: #0f0}
+hr {color: #0f0}
+html,table,body,textarea,input,form
+{
+font-family: "Courier New", Courier, mono; 
+font-size: 8pt; 
+color: #0c0;
+background-color: #020;
+margin:0;
+padding:0;
+border:0;
+}
+input { background-color: #010; }
+textarea {
+border-width:1;
+border-style:solid;
+border-color:#0c0;
+padding:3;
+margin:3;
+}
+</style>
+<script>
+var foo="" +
+" 123456789012345678901234567890123456789012345 789012345678901234567890123456789"+
+"0 2345678901234567890123456789012345678901234 6 89012345678901234567890123456789"+
+"01 34567890123456789012345678901234567890123 567 9012345678901234567890123456789"+
+"012 456789012345678901234567890123456789012 45678 012345678901234567890123456789"+
+"0123 5678901234567890123456789012345678901 3456789 12345678901234567890123456789"+
+"01234 67890123456789012345678901234567890 234567890 2345678901234567890123456789"+
+"012345 789012345678901234567890123456789 12345678901 345678901234567890123456789"+
+"0123456 8901234567890123456789012345678 0123456789012 45678901234567890123456789"+
+"01234567 90123456789012345678901234567 901234567890123 5678901234567890123456789"+
+"012345678 012345678901234567890123456 89012345678901234 678901234567890123456789"+
+"0123456789 1234567890123456789012345 7890123456789012345 78901234567890123456789"+
+"01234567890 23456789012345678901234 678901234567890123456 8901234567890123456789"+
+"012345678901 345678901234567890123 56789012345678901234567 901234567890123456789"+
+"0123456789012 4567890123456789012 4567890123456789012345678 0123456789012345678 "+
+"01234567890123 56789012345678901 345678901234567890123456789 12345678901234567 9"+
+"012345678901234 678901234567890 23456789012  567  01234567890 234567890123456 89"+
+"0123456789012345 7890123456789 123457789012  567  012345678901 3456789012345 789"+
+"01234567890123456 89012345678 012345678901234567890123456789012 45678901234 6789"+
+"012345678901234567 901234567 90123456789 12345678901 34567890123 567890123 56789"+
+"0123456789012345678 0123456 8901234567890  3456789  2345678901234 6789012 456789"+
+"01234567890123456789 12345 7890123456789012       0123456789012345 78901 3456789"+
+"012345678901234567890 234 67890123456789012345678901234567890123456 890 23456789"+
+"0123456789012345678901 3 5678901234567890123456789012345678901234567 9 123456789"+
+"01234567890123456789012 456789012345678901234567890123456789012345678 0123456789";
+function start2()
+{
+    // get the reference for the body
+    //var mybody = document.getElementsByTagName("body")[0];
+    var mybody = document.getElementById("replace_me");
+    var myroot = document.getElementById("a_parent");
+    mytable = document.createElement("table");
+    mytablebody = document.createElement("tbody");
+    mytable.setAttribute("border","0");
+    mytable.setAttribute("cellspacing","0");
+    mytable.setAttribute("cellpadding","0");
+    for(var j = 0; j < 24; j++)
+    {
+        mycurrent_row = document.createElement("tr");
+        for(var i = 0; i < 80; i++)
+        {
+            mycurrent_cell = document.createElement("td");
+            offset = (j*80)+i;
+            currenttext = document.createTextNode(foo.substring(offset,offset+1));
+            mycurrent_cell.appendChild(currenttext);
+            mycurrent_row.appendChild(mycurrent_cell);
+        }
+        mytablebody.appendChild(mycurrent_row);
+    }
+    mytable.appendChild(mytablebody);
+    myroot.replaceChild(mytable,mybody);
+    //mybody.appendChild(mytable);
+}
+</script>
+<body onload="start2();">
+<table align="LEFT" border="0" cellspacing="0" cellpadding="0">
+<div id="a_parent">
+<span id="replace_me">
+<tr align="left" valign="left">
+    <td>/</td>
+    <td>h</td>
+    <td>o</td>
+    <td>m</td>
+    <td>e</td>
+    <td>/</td>
+    <td>n</td>
+    <td>o</td>
+    <td>a</td>
+    <td>h</td>
+    <td>/</td>
+    <td> </td>
+</tr>
+</table>
+</span>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/pexpect/examples/topip.py b/third_party/pexpect/examples/topip.py
new file mode 100755
index 0000000..25bd100
--- /dev/null
+++ b/third_party/pexpect/examples/topip.py
@@ -0,0 +1,299 @@
+#!/usr/bin/env python
+
+''' This runs netstat on a local or remote server. It calculates some simple
+statistical information on the number of external inet connections. It groups
+by IP address. This can be used to detect if one IP address is taking up an
+excessive number of connections. It can also send an email alert if a given IP
+address exceeds a threshold between runs of the script. This script can be used
+as a drop-in Munin plugin or it can be used stand-alone from cron. I used this
+on a busy web server that would sometimes get hit with denial of service
+attacks. This made it easy to see if a script was opening many multiple
+connections. A typical browser would open fewer than 10 connections at once.
+A script might open over 100 simultaneous connections.
+
+./topip.py [-s server_hostname] [-u username] [-p password]
+        {-a from_addr,to_addr} {-n N} {-v} {--ipv6}
+
+    -s : hostname of the remote server to login to.
+    -u : username to user for login.
+    -p : password to user for login.
+    -n : print stddev for the the number of the top 'N' ipaddresses.
+    -v : verbose - print stats and list of top ipaddresses.
+    -a : send alert if stddev goes over 20.
+    -l : to log message to /var/log/topip.log
+    --ipv6 : this parses netstat output that includes ipv6 format.
+        Note that this actually only works with ipv4 addresses, but for
+        versions of netstat that print in ipv6 format.
+    --stdev=N : Where N is an integer. This sets the trigger point
+        for alerts and logs. Default is to trigger if the
+        max value is over 5 standard deviations.
+
+Example:
+
+    This will print stats for the top IP addresses connected to the given host:
+
+        ./topip.py -s www.example.com -u mylogin -p mypassword -n 10 -v
+
+    This will send an alert email if the maxip goes over the stddev trigger
+    value and the the current top ip is the same as the last top ip
+    (/tmp/topip.last):
+
+        ./topip.py -s www.example.com -u mylogin -p mypassword \\
+                -n 10 -v -a alert at example.com,user at example.com
+
+    This will print the connection stats for the localhost in Munin format:
+
+        ./topip.py
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import absolute_import
+from __future__ import print_function
+from __future__ import unicode_literals
+
+# See http://pexpect.sourceforge.net/
+import pexpect
+import pxssh
+import os
+import sys
+import time
+import getopt
+import pickle
+import getpass
+import smtplib
+from pprint import pprint
+
+
+try:
+    raw_input
+except NameError:
+    raw_input = input
+
+
+TOPIP_LOG_FILE = '/var/log/topip.log'
+TOPIP_LAST_RUN_STATS = '/var/run/topip.last'
+
+def exit_with_usage():
+
+    print(globals()['__doc__'])
+    os._exit(1)
+
+def stats(r):
+
+    '''This returns a dict of the median, average, standard deviation,
+    min and max of the given sequence.
+
+    >>> from topip import stats
+    >>> print stats([5,6,8,9])
+    {'med': 8, 'max': 9, 'avg': 7.0, 'stddev': 1.5811388300841898, 'min': 5}
+    >>> print stats([1000,1006,1008,1014])
+    {'med': 1008, 'max': 1014, 'avg': 1007.0, 'stddev': 5.0, 'min': 1000}
+    >>> print stats([1,3,4,5,18,16,4,3,3,5,13])
+    {'med': 4, 'max': 18, 'avg': 6.8181818181818183, 'stddev': 5.6216817577237475, 'min': 1}
+    >>> print stats([1,3,4,5,18,16,4,3,3,5,13,14,5,6,7,8,7,6,6,7,5,6,4,14,7])
+    {'med': 6, 'max': 18, 'avg': 7.0800000000000001, 'stddev': 4.3259218670706474, 'min': 1}
+    '''
+
+    total = sum(r)
+    avg = float(total)/float(len(r))
+    sdsq = sum([(i-avg)**2 for i in r])
+    s = sorted(list(r))
+    return dict(list(zip(['med', 'avg', 'stddev', 'min', 'max'],
+        (s[len(s)//2], avg, (sdsq/len(r))**.5, min(r), max(r)))))
+
+def send_alert (message, subject, addr_from, addr_to, smtp_server='localhost'):
+
+    '''This sends an email alert.
+    '''
+
+    message = ( 'From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n'
+            % (addr_from, addr_to, subject) + message )
+    server = smtplib.SMTP(smtp_server)
+    server.sendmail(addr_from, addr_to, message)
+    server.quit()
+
+def main():
+
+    # Parse the options, arguments, etc.
+    try:
+        optlist, args = getopt.getopt(sys.argv[1:],
+                'h?valqs:u:p:n:', ['help','h','?','ipv6','stddev='])
+    except Exception as e:
+        print(str(e))
+        exit_with_usage()
+    options = dict(optlist)
+
+    munin_flag = False
+    if len(args) > 0:
+        if args[0] == 'config':
+            print('graph_title Netstat Connections per IP')
+            print('graph_vlabel Socket connections per IP')
+            print('connections_max.label max')
+            print('connections_max.info Maximum number of connections per IP')
+            print('connections_avg.label avg')
+            print('connections_avg.info Average number of connections per IP')
+            print('connections_stddev.label stddev')
+            print('connections_stddev.info Standard deviation')
+            return 0
+        elif args[0] != '':
+            print(args, len(args))
+            return 0
+            exit_with_usage()
+    if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]:
+        print('Help:')
+        exit_with_usage()
+    if '-s' in options:
+        hostname = options['-s']
+    else:
+        # if host was not specified then assume localhost munin plugin.
+        munin_flag = True
+        hostname = 'localhost'
+    # If localhost then don't ask for username/password.
+    if hostname != 'localhost' and hostname != '127.0.0.1':
+        if '-u' in options:
+            username = options['-u']
+        else:
+            username = raw_input('username: ')
+        if '-p' in options:
+            password = options['-p']
+        else:
+            password = getpass.getpass('password: ')
+        use_localhost = False
+    else:
+        use_localhost = True
+
+    if '-l' in options:
+        log_flag = True
+    else:
+        log_flag = False
+    if '-n' in options:
+        average_n = int(options['-n'])
+    else:
+        average_n = None
+    if '-v' in options:
+        verbose = True
+    else:
+        verbose = False
+    if '-a' in options:
+        alert_flag = True
+        (alert_addr_from, alert_addr_to) = tuple(options['-a'].split(','))
+    else:
+        alert_flag = False
+    if '--ipv6' in options:
+        ipv6_flag = True
+    else:
+        ipv6_flag = False
+    if '--stddev' in options:
+        stddev_trigger = float(options['--stddev'])
+    else:
+        stddev_trigger = 5
+
+    if ipv6_flag:
+        netstat_pattern = '(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+::ffff:(\S+):(\S+)\s+.*?\r'
+    else:
+        netstat_pattern = '(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(?:::ffff:)*(\S+):(\S+)\s+.*?\r'
+        #netstat_pattern = '(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+):(\S+)\s+.*?\r'
+
+    # run netstat (either locally or via SSH).
+    if use_localhost:
+        p = pexpect.spawn('netstat -n -t')
+        PROMPT = pexpect.TIMEOUT
+    else:
+        p = pxssh.pxssh()
+        p.login(hostname, username, password)
+        p.sendline('netstat -n -t')
+        PROMPT = p.PROMPT
+
+    # For each matching netstat_pattern put the ip address in the list.
+    ip_list = {}
+    try:
+        while 1:
+            i = p.expect([PROMPT, netstat_pattern])
+            if i == 0:
+                break
+            k = p.match.groups()[4].decode('utf-8')
+            if k in ip_list:
+                ip_list[k] = ip_list[k] + 1
+            else:
+                ip_list[k] = 1
+    except:
+        pass
+
+    # remove a few common, uninteresting addresses from the dictionary.
+    ip_list = dict([ (key,value) for key,value in ip_list.items() if '192.168.' not in key])
+    ip_list = dict([ (key,value) for key,value in ip_list.items() if '127.0.0.1' not in key])
+
+    ip_list = list(ip_list.items())
+    if len(ip_list) < 1:
+        if verbose: print('Warning: no networks connections worth looking at.')
+        return 0
+    ip_list.sort(key=lambda x:x[1])
+
+    # generate some stats for the ip addresses found.
+    if average_n is not None and average_n <= 1:
+        average_n = None
+    # Reminder: the * unary operator treats the list elements as arguments.
+    zipped = zip(*ip_list[0:average_n])
+    s = stats(list(zipped)[1])
+    s['maxip'] = ip_list[0]
+
+    # print munin-style or verbose results for the stats.
+    if munin_flag:
+        print('connections_max.value', s['max'])
+        print('connections_avg.value', s['avg'])
+        print('connections_stddev.value', s['stddev'])
+        return 0
+    if verbose:
+        pprint (s)
+        print()
+        pprint (ip_list[0:average_n])
+
+    # load the stats from the last run.
+    try:
+        last_stats = pickle.load(file(TOPIP_LAST_RUN_STATS))
+    except:
+        last_stats = {'maxip':None}
+
+    if ( s['maxip'][1] > (s['stddev'] * stddev_trigger)
+            and s['maxip']==last_stats['maxip'] ):
+        if verbose: print('The maxip has been above trigger for two consecutive samples.')
+        if alert_flag:
+            if verbose: print('SENDING ALERT EMAIL')
+            send_alert(str(s), 'ALERT on %s'
+                    % hostname, alert_addr_from, alert_addr_to)
+        if log_flag:
+            if verbose: print('LOGGING THIS EVENT')
+            fout = file(TOPIP_LOG_FILE,'a')
+            #dts = time.strftime('%Y:%m:%d:%H:%M:%S', time.localtime())
+            dts = time.asctime()
+            fout.write ('%s - %d connections from %s\n'
+                    % (dts,s['maxip'][1],str(s['maxip'][0])))
+            fout.close()
+
+    # save state to TOPIP_LAST_RUN_STATS
+    try:
+        pickle.dump(s, file(TOPIP_LAST_RUN_STATS,'w'))
+        os.chmod (TOPIP_LAST_RUN_STATS, 0o664)
+    except:
+        pass
+    # p.logout()
+
+if __name__ == '__main__':
+    main()
diff --git a/third_party/pexpect/examples/uptime.py b/third_party/pexpect/examples/uptime.py
new file mode 100755
index 0000000..659edfc
--- /dev/null
+++ b/third_party/pexpect/examples/uptime.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+
+'''This displays uptime information using uptime. This is redundant,
+but it demonstrates expecting for a regular expression that uses subgroups.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from __future__ import absolute_import
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import pexpect
+import re
+
+# There are many different styles of uptime results. I try to parse them all. Yeee!
+# Examples from different machines:
+# [x86] Linux 2.4 (Redhat 7.3)
+#  2:06pm  up 63 days, 18 min,  3 users,  load average: 0.32, 0.08, 0.02
+# [x86] Linux 2.4.18-14 (Redhat 8.0)
+#  3:07pm  up 29 min,  1 user,  load average: 2.44, 2.51, 1.57
+# [PPC - G4] MacOS X 10.1 SERVER Edition
+# 2:11PM  up 3 days, 13:50, 3 users, load averages: 0.01, 0.00, 0.00
+# [powerpc] Darwin v1-58.corefa.com 8.2.0 Darwin Kernel Version 8.2.0
+# 10:35  up 18:06, 4 users, load averages: 0.52 0.47 0.36
+# [Sparc - R220] Sun Solaris (8)
+#  2:13pm  up 22 min(s),  1 user,  load average: 0.02, 0.01, 0.01
+# [x86] Linux 2.4.18-14 (Redhat 8)
+# 11:36pm  up 4 days, 17:58,  1 user,  load average: 0.03, 0.01, 0.00
+# AIX jwdir 2 5 0001DBFA4C00
+#  09:43AM   up  23:27,  1 user,  load average: 0.49, 0.32, 0.23
+# OpenBSD box3 2.9 GENERIC#653 i386
+#  6:08PM  up 4 days, 22:26, 1 user, load averages: 0.13, 0.09, 0.08
+
+# Note that, for Python 3 compatibility reasons, we are using spawnu and
+# importing unicode_literals (above). spawnu accepts Unicode input and
+# unicode_literals makes all string literals in this script Unicode by default.
+p = pexpect.spawnu('uptime')
+
+# This parses uptime output into the major groups using regex group matching.
+p.expect('up\s+(.*?),\s+([0-9]+) users?,\s+load averages?: ([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9])')
+duration, users, av1, av5, av15 = p.match.groups()
+
+# The duration is a little harder to parse because of all the different
+# styles of uptime. I'm sure there is a way to do this all at once with
+# one single regex, but I bet it would be hard to read and maintain.
+# If anyone wants to send me a version using a single regex I'd be happy to see it.
+days = '0'
+hours = '0'
+mins = '0'
+if 'day' in duration:
+    p.match = re.search('([0-9]+)\s+day',duration)
+    days = str(int(p.match.group(1)))
+if ':' in duration:
+    p.match = re.search('([0-9]+):([0-9]+)',duration)
+    hours = str(int(p.match.group(1)))
+    mins = str(int(p.match.group(2)))
+if 'min' in duration:
+    p.match = re.search('([0-9]+)\s+min',duration)
+    mins = str(int(p.match.group(1)))
+
+# Print the parsed fields in CSV format.
+print('days, hours, minutes, users, cpu avg 1 min, cpu avg 5 min, cpu avg 15 min')
+print('%s, %s, %s, %s, %s, %s, %s' % (days, hours, mins, users, av1, av5, av15))
+
diff --git a/third_party/pexpect/fdpexpect.py b/third_party/pexpect/fdpexpect.py
new file mode 100644
index 0000000..26db4c1
--- /dev/null
+++ b/third_party/pexpect/fdpexpect.py
@@ -0,0 +1,7 @@
+import warnings
+
+warnings.warn("This module has been moved to pexpect.fdpexpect, please update imports.",
+                ImportWarning)
+del warnings
+
+from pexpect.fdpexpect import *  # analysis:ignore
\ No newline at end of file
diff --git a/third_party/pexpect/notes/my_forkpty.py b/third_party/pexpect/notes/my_forkpty.py
new file mode 100644
index 0000000..f2bef23
--- /dev/null
+++ b/third_party/pexpect/notes/my_forkpty.py
@@ -0,0 +1,89 @@
+import os, fcntl, termios
+import time
+
+def my_forkpty():
+
+    (master_fd, slave_fd) = os.openpty()
+
+    if (master_fd < 0  or  slave_fd < 0):
+        raise ExceptionPexpect("Forkpty failed")
+
+    # slave_name = ptsname(master_fd);
+
+    pid = os.fork();
+    if pid == -1:
+        raise ExceptionPexpect("Forkpty failed")
+    elif pid == 0: # Child
+        if hasattr(termios, 'TIOCNOTTY'):
+        #        Some platforms require an explicit detach of the
+        #        current controlling tty before closing stdin, stdout, stderr.
+        #        OpenBSD says that this is obsolete, but doesn't hurt.
+            try:
+                fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
+            except:
+                pass
+            else: #if fd >= 0:
+                fcntl.ioctl(fd, termios.TIOCNOTTY, 0)
+                os.close(fd)
+
+        # The setsid() system call will place the process into its own session
+        # which has the effect of disassociating it from the controlling terminal.
+        # This is known to be true for OpenBSD.
+        os.setsid()
+        # except:            return posix_error();
+
+        # Verify that we are disconnected from the controlling tty.
+        try:
+            fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
+            os.close(fd)
+            raise ExceptionPexpect("Forkpty failed")
+        except:
+            pass
+        if 'TIOCSCTTY' in dir(termios):
+            # Make the pseudo terminal the controlling terminal for this process
+            # (the process must not currently have a controlling terminal).
+            if fcntl.ioctl(slave_fd, termios.TIOCSCTTY, '') < 0:
+                raise ExceptionPexpect("Forkpty failed")
+
+#        # Verify that we can open to the slave pty file. */
+#        fd = os.open(slave_name, os.O_RDWR);
+#        if fd < 0:
+#            raise ExceptionPexpect("Forkpty failed")
+#        else:
+#            os.close(fd);
+
+        # Verify that we now have a controlling tty.
+        fd = os.open("/dev/tty", os.O_WRONLY)
+        if fd < 0:
+            raise ExceptionPexpect("This process could not get a controlling tty.")
+        else:
+            os.close(fd)
+
+        os.close(master_fd)
+        os.dup2(slave_fd, 0)
+        os.dup2(slave_fd, 1)
+        os.dup2(slave_fd, 2)
+        if slave_fd > 2:
+            os.close(slave_fd)
+        pid = 0
+
+    else:
+        # PARENT 
+        os.close(slave_fd);
+
+    if pid == -1:
+        raise ExceptionPexpect("This process could not get a controlling tty.")
+#    if (pid == 0)
+#        PyOS_AfterFork();
+
+    return (pid, master_fd)
+
+pid, fd = my_forkpty ()
+if pid == 0: # child
+    print 'I am not a robot!'
+else:
+    print '(pid, fd) = (%d, %d)' % (pid, fd)
+    time.sleep(1) # Give the child a chance to print.
+    print 'Robots always say:', os.read(fd,100)
+    os.close(fd)
+
diff --git a/third_party/pexpect/notes/notes.txt b/third_party/pexpect/notes/notes.txt
new file mode 100644
index 0000000..a793587b
--- /dev/null
+++ b/third_party/pexpect/notes/notes.txt
@@ -0,0 +1,50 @@
+
+####################
+#
+#        NOTES
+#
+####################
+
+##    def send_human(self, text, delay_min = 0, delay_max = 1):
+##        pass
+##    def spawn2(self, command, args):
+##        """return pid, fd_stdio, fd_stderr
+##        """
+##        pass
+
+
+# Reason for double fork:
+# http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC15
+# Reason for ptys:
+# http://www.erlenstar.demon.co.uk/unix/faq_4.html#SEC52
+
+# Nonblocking on Win32?
+# Reasearch this as a way to maybe make pipe work for Win32.
+# http://groups.google.com/groups?q=setraw+tty&hl=en&selm=uvgpvisvk.fsf%40roundpoint.com&rnum=7
+# 
+#    if istty:
+#        if os.name=='posix':
+#            import tty
+#            tty.setraw(sys.stdin.fileno())
+#        elif os.name=='nt':
+#            import win32file, win32con
+#            hstdin = win32file._get_osfhandle(sys.stdin.fileno())
+#            modes = (win32file.GetConsoleMode(hstdin)
+#                     & ~(win32con.ENABLE_LINE_INPUT
+#                         |win32con.ENABLE_ECHO_INPUT))
+#            win32file.SetConsoleMode(hstdin, modes)
+
+# Basic documentation:
+#       Explain use of lists of patterns and return index.
+#       Explain exceptions for non-handled special cases like EOF
+
+# Test bad fork
+# Test ENOENT. In other words, no more TTY devices.
+
+#GLOBAL_SIGCHLD_RECEIVED = 0
+#def childdied (signum, frame):
+#    print 'Signal handler called with signal', signum
+#    frame.f_globals['pexpect'].GLOBAL_SIGCHLD_RECEIVED = 1
+#    print str(frame.f_globals['pexpect'].GLOBAL_SIGCHLD_RECEIVED)
+#    GLOBAL_SIGCHLD_RECEIVED = 1
+
diff --git a/third_party/pexpect/notes/posixmodule.c.diff b/third_party/pexpect/notes/posixmodule.c.diff
new file mode 100644
index 0000000..3bea1f9
--- /dev/null
+++ b/third_party/pexpect/notes/posixmodule.c.diff
@@ -0,0 +1,233 @@
+*** Python-2.2.1.orig/Modules/posixmodule.c	Tue Mar 12 16:38:31 2002
+--- Python-2.2.1/Modules/posixmodule.c	Tue May 21 01:16:29 2002
+***************
+*** 1904,1910 ****
+  }
+  #endif
+  
+! #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY)
+  #ifdef HAVE_PTY_H
+  #include <pty.h>
+  #else
+--- 1904,1913 ----
+  }
+  #endif
+  
+! #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(sun)
+! #ifdef sun
+! #include <sys/stropts.h>
+! #endif
+  #ifdef HAVE_PTY_H
+  #include <pty.h>
+  #else
+***************
+*** 1914,1920 ****
+  #endif /* HAVE_PTY_H */
+  #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) */
+  
+! #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY)
+  static char posix_openpty__doc__[] =
+  "openpty() -> (master_fd, slave_fd)\n\
+  Open a pseudo-terminal, returning open fd's for both master and slave end.\n";
+--- 1917,1923 ----
+  #endif /* HAVE_PTY_H */
+  #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) */
+  
+! #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(sun)
+  static char posix_openpty__doc__[] =
+  "openpty() -> (master_fd, slave_fd)\n\
+  Open a pseudo-terminal, returning open fd's for both master and slave end.\n";
+***************
+*** 1925,1932 ****
+  	int master_fd, slave_fd;
+  #ifndef HAVE_OPENPTY
+  	char * slave_name;
+  #endif
+! 
+  	if (!PyArg_ParseTuple(args, ":openpty"))
+  		return NULL;
+  
+--- 1928,1941 ----
+  	int master_fd, slave_fd;
+  #ifndef HAVE_OPENPTY
+  	char * slave_name;
++ #ifdef sun
++         void *sig_saved;
+  #endif
+! #endif
+! #if !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) && defined(sun)
+!         extern char *ptsname();
+! #endif
+!         
+  	if (!PyArg_ParseTuple(args, ":openpty"))
+  		return NULL;
+  
+***************
+*** 1933,1939 ****
+  #ifdef HAVE_OPENPTY
+  	if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
+  		return posix_error();
+! #else
+  	slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
+  	if (slave_name == NULL)
+  		return posix_error();
+--- 1942,1948 ----
+  #ifdef HAVE_OPENPTY
+  	if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
+  		return posix_error();
+! #elif HAVE__GETPTY
+  	slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
+  	if (slave_name == NULL)
+  		return posix_error();
+***************
+*** 1941,1946 ****
+--- 1950,1966 ----
+  	slave_fd = open(slave_name, O_RDWR);
+  	if (slave_fd < 0)
+  		return posix_error();
++ #else
++         master_fd = open("/dev/ptmx", O_RDWR|O_NOCTTY);  /* open master */
++         sig_saved = signal(SIGCHLD, SIG_DFL);
++         grantpt(master_fd);                     /* change permission of   slave */
++         unlockpt(master_fd);                    /* unlock slave */
++         signal(SIGCHLD,sig_saved);
++         slave_name = ptsname(master_fd);         /* get name of slave */
++         slave_fd = open(slave_name, O_RDWR);    /* open slave */
++         ioctl(slave_fd, I_PUSH, "ptem");       /* push ptem */
++         ioctl(slave_fd, I_PUSH, "ldterm");     /* push ldterm*/
++         ioctl(slave_fd, I_PUSH, "ttcompat");     /* push ttcompat*/
+  #endif /* HAVE_OPENPTY */
+  
+  	return Py_BuildValue("(ii)", master_fd, slave_fd);
+***************
+*** 1948,1954 ****
+  }
+  #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) */
+  
+! #ifdef HAVE_FORKPTY
+  static char posix_forkpty__doc__[] =
+  "forkpty() -> (pid, master_fd)\n\
+  Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
+--- 1968,1974 ----
+  }
+  #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) */
+  
+! #if defined(HAVE_FORKPTY) || defined(sun)
+  static char posix_forkpty__doc__[] =
+  "forkpty() -> (pid, master_fd)\n\
+  Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
+***************
+*** 1959,1968 ****
+--- 1979,2067 ----
+  posix_forkpty(PyObject *self, PyObject *args)
+  {
+  	int master_fd, pid;
++ #if defined(sun)
++         int slave;
++ 	char * slave_name;
++         void *sig_saved;
++         int fd;
++ #endif
+  	
+  	if (!PyArg_ParseTuple(args, ":forkpty"))
+  		return NULL;
++ #if defined(sun)
++         master_fd = open("/dev/ptmx", O_RDWR|O_NOCTTY);  /* open master */
++         sig_saved = signal(SIGCHLD, SIG_DFL);
++         grantpt(master_fd);                     /* change permission of   slave */
++         unlockpt(master_fd);                    /* unlock slave */
++         signal(SIGCHLD,sig_saved);
++         slave_name = ptsname(master_fd);         /* get name of slave */
++         slave = open(slave_name, O_RDWR);    /* open slave */
++         ioctl(slave, I_PUSH, "ptem");       /* push ptem */
++         ioctl(slave, I_PUSH, "ldterm");     /* push ldterm*/
++         ioctl(slave, I_PUSH, "ttcompat");     /* push ttcompat*/
++         if (master_fd < 0 || slave < 0)
++         {
++             return posix_error();
++         }
++ 	switch (pid = fork()) {
++ 	case -1:	
++             return posix_error();
++ 	case 0:
++             /* First disconnect from the old controlling tty. */
++ #ifdef TIOCNOTTY
++             fd = open("/dev/tty", O_RDWR | O_NOCTTY);
++             if (fd >= 0) {
++ 		(void) ioctl(fd, TIOCNOTTY, NULL);
++ 		close(fd);
++             }
++ #endif /* TIOCNOTTY */
++             if (setsid() < 0)
++ 		return posix_error();
++             
++             /*
++              * Verify that we are successfully disconnected from the controlling
++              * tty.
++              */
++             fd = open("/dev/tty", O_RDWR | O_NOCTTY);
++             if (fd >= 0) {
++ 		return posix_error();
++ 		close(fd);
++             }
++             /* Make it our controlling tty. */
++ #ifdef TIOCSCTTY
++             if (ioctl(slave, TIOCSCTTY, NULL) < 0)
++ 		return posix_error();
++ #endif /* TIOCSCTTY */
++             fd = open(slave_name, O_RDWR);
++             if (fd < 0) {
++ 		return posix_error();
++             } else {
++ 		close(fd);
++             }
++             /* Verify that we now have a controlling tty. */
++             fd = open("/dev/tty", O_WRONLY);
++             if (fd < 0)
++ 		return posix_error();
++             else {
++ 		close(fd);
++             }
++             (void) close(master_fd);
++             (void) dup2(slave, 0);
++             (void) dup2(slave, 1);
++             (void) dup2(slave, 2);
++             if (slave > 2)
++                 (void) close(slave);
++             pid = 0;
++             break;
++           defautlt:
++             /*
++              * parent
++              */
++             (void) close(slave);
++ 	}
++ #else
+  	pid = forkpty(&master_fd, NULL, NULL, NULL);
++ #endif
+  	if (pid == -1)
+  		return posix_error();
+  	if (pid == 0)
+***************
+*** 5607,5616 ****
+  #ifdef HAVE_FORK
+  	{"fork",	posix_fork, METH_VARARGS, posix_fork__doc__},
+  #endif /* HAVE_FORK */
+! #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY)
+  	{"openpty",	posix_openpty, METH_VARARGS, posix_openpty__doc__},
+  #endif /* HAVE_OPENPTY || HAVE__GETPTY */
+! #ifdef HAVE_FORKPTY
+  	{"forkpty",	posix_forkpty, METH_VARARGS, posix_forkpty__doc__},
+  #endif /* HAVE_FORKPTY */
+  #ifdef HAVE_GETEGID
+--- 5706,5715 ----
+  #ifdef HAVE_FORK
+  	{"fork",	posix_fork, METH_VARARGS, posix_fork__doc__},
+  #endif /* HAVE_FORK */
+! #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(sun)
+  	{"openpty",	posix_openpty, METH_VARARGS, posix_openpty__doc__},
+  #endif /* HAVE_OPENPTY || HAVE__GETPTY */
+! #if defined(HAVE_FORKPTY) || defined(sun)
+  	{"forkpty",	posix_forkpty, METH_VARARGS, posix_forkpty__doc__},
+  #endif /* HAVE_FORKPTY */
+  #ifdef HAVE_GETEGID
diff --git a/third_party/pexpect/pexpect/ANSI.py b/third_party/pexpect/pexpect/ANSI.py
new file mode 100644
index 0000000..1cd2e90
--- /dev/null
+++ b/third_party/pexpect/pexpect/ANSI.py
@@ -0,0 +1,351 @@
+'''This implements an ANSI (VT100) terminal emulator as a subclass of screen.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+# references:
+#     http://en.wikipedia.org/wiki/ANSI_escape_code
+#     http://www.retards.org/terminals/vt102.html
+#     http://vt100.net/docs/vt102-ug/contents.html
+#     http://vt100.net/docs/vt220-rm/
+#     http://www.termsys.demon.co.uk/vtansi.htm
+
+from . import screen
+from . import FSM
+import string
+
+#
+# The 'Do.*' functions are helper functions for the ANSI class.
+#
+def DoEmit (fsm):
+
+    screen = fsm.memory[0]
+    screen.write_ch(fsm.input_symbol)
+
+def DoStartNumber (fsm):
+
+    fsm.memory.append (fsm.input_symbol)
+
+def DoBuildNumber (fsm):
+
+    ns = fsm.memory.pop()
+    ns = ns + fsm.input_symbol
+    fsm.memory.append (ns)
+
+def DoBackOne (fsm):
+
+    screen = fsm.memory[0]
+    screen.cursor_back ()
+
+def DoBack (fsm):
+
+    count = int(fsm.memory.pop())
+    screen = fsm.memory[0]
+    screen.cursor_back (count)
+
+def DoDownOne (fsm):
+
+    screen = fsm.memory[0]
+    screen.cursor_down ()
+
+def DoDown (fsm):
+
+    count = int(fsm.memory.pop())
+    screen = fsm.memory[0]
+    screen.cursor_down (count)
+
+def DoForwardOne (fsm):
+
+    screen = fsm.memory[0]
+    screen.cursor_forward ()
+
+def DoForward (fsm):
+
+    count = int(fsm.memory.pop())
+    screen = fsm.memory[0]
+    screen.cursor_forward (count)
+
+def DoUpReverse (fsm):
+
+    screen = fsm.memory[0]
+    screen.cursor_up_reverse()
+
+def DoUpOne (fsm):
+
+    screen = fsm.memory[0]
+    screen.cursor_up ()
+
+def DoUp (fsm):
+
+    count = int(fsm.memory.pop())
+    screen = fsm.memory[0]
+    screen.cursor_up (count)
+
+def DoHome (fsm):
+
+    c = int(fsm.memory.pop())
+    r = int(fsm.memory.pop())
+    screen = fsm.memory[0]
+    screen.cursor_home (r,c)
+
+def DoHomeOrigin (fsm):
+
+    c = 1
+    r = 1
+    screen = fsm.memory[0]
+    screen.cursor_home (r,c)
+
+def DoEraseDown (fsm):
+
+    screen = fsm.memory[0]
+    screen.erase_down()
+
+def DoErase (fsm):
+
+    arg = int(fsm.memory.pop())
+    screen = fsm.memory[0]
+    if arg == 0:
+        screen.erase_down()
+    elif arg == 1:
+        screen.erase_up()
+    elif arg == 2:
+        screen.erase_screen()
+
+def DoEraseEndOfLine (fsm):
+
+    screen = fsm.memory[0]
+    screen.erase_end_of_line()
+
+def DoEraseLine (fsm):
+
+    arg = int(fsm.memory.pop())
+    screen = fsm.memory[0]
+    if arg == 0:
+        screen.erase_end_of_line()
+    elif arg == 1:
+        screen.erase_start_of_line()
+    elif arg == 2:
+        screen.erase_line()
+
+def DoEnableScroll (fsm):
+
+    screen = fsm.memory[0]
+    screen.scroll_screen()
+
+def DoCursorSave (fsm):
+
+    screen = fsm.memory[0]
+    screen.cursor_save_attrs()
+
+def DoCursorRestore (fsm):
+
+    screen = fsm.memory[0]
+    screen.cursor_restore_attrs()
+
+def DoScrollRegion (fsm):
+
+    screen = fsm.memory[0]
+    r2 = int(fsm.memory.pop())
+    r1 = int(fsm.memory.pop())
+    screen.scroll_screen_rows (r1,r2)
+
+def DoMode (fsm):
+
+    screen = fsm.memory[0]
+    mode = fsm.memory.pop() # Should be 4
+    # screen.setReplaceMode ()
+
+def DoLog (fsm):
+
+    screen = fsm.memory[0]
+    fsm.memory = [screen]
+    fout = open ('log', 'a')
+    fout.write (fsm.input_symbol + ',' + fsm.current_state + '\n')
+    fout.close()
+
+class term (screen.screen):
+
+    '''This class is an abstract, generic terminal.
+    This does nothing. This is a placeholder that
+    provides a common base class for other terminals
+    such as an ANSI terminal. '''
+
+    def __init__ (self, r=24, c=80, *args, **kwargs):
+
+        screen.screen.__init__(self, r,c,*args,**kwargs)
+
+class ANSI (term):
+    '''This class implements an ANSI (VT100) terminal.
+    It is a stream filter that recognizes ANSI terminal
+    escape sequences and maintains the state of a screen object. '''
+
+    def __init__ (self, r=24,c=80,*args,**kwargs):
+
+        term.__init__(self,r,c,*args,**kwargs)
+
+        #self.screen = screen (24,80)
+        self.state = FSM.FSM ('INIT',[self])
+        self.state.set_default_transition (DoLog, 'INIT')
+        self.state.add_transition_any ('INIT', DoEmit, 'INIT')
+        self.state.add_transition ('\x1b', 'INIT', None, 'ESC')
+        self.state.add_transition_any ('ESC', DoLog, 'INIT')
+        self.state.add_transition ('(', 'ESC', None, 'G0SCS')
+        self.state.add_transition (')', 'ESC', None, 'G1SCS')
+        self.state.add_transition_list ('AB012', 'G0SCS', None, 'INIT')
+        self.state.add_transition_list ('AB012', 'G1SCS', None, 'INIT')
+        self.state.add_transition ('7', 'ESC', DoCursorSave, 'INIT')
+        self.state.add_transition ('8', 'ESC', DoCursorRestore, 'INIT')
+        self.state.add_transition ('M', 'ESC', DoUpReverse, 'INIT')
+        self.state.add_transition ('>', 'ESC', DoUpReverse, 'INIT')
+        self.state.add_transition ('<', 'ESC', DoUpReverse, 'INIT')
+        self.state.add_transition ('=', 'ESC', None, 'INIT') # Selects application keypad.
+        self.state.add_transition ('#', 'ESC', None, 'GRAPHICS_POUND')
+        self.state.add_transition_any ('GRAPHICS_POUND', None, 'INIT')
+        self.state.add_transition ('[', 'ESC', None, 'ELB')
+        # ELB means Escape Left Bracket. That is ^[[
+        self.state.add_transition ('H', 'ELB', DoHomeOrigin, 'INIT')
+        self.state.add_transition ('D', 'ELB', DoBackOne, 'INIT')
+        self.state.add_transition ('B', 'ELB', DoDownOne, 'INIT')
+        self.state.add_transition ('C', 'ELB', DoForwardOne, 'INIT')
+        self.state.add_transition ('A', 'ELB', DoUpOne, 'INIT')
+        self.state.add_transition ('J', 'ELB', DoEraseDown, 'INIT')
+        self.state.add_transition ('K', 'ELB', DoEraseEndOfLine, 'INIT')
+        self.state.add_transition ('r', 'ELB', DoEnableScroll, 'INIT')
+        self.state.add_transition ('m', 'ELB', self.do_sgr, 'INIT')
+        self.state.add_transition ('?', 'ELB', None, 'MODECRAP')
+        self.state.add_transition_list (string.digits, 'ELB', DoStartNumber, 'NUMBER_1')
+        self.state.add_transition_list (string.digits, 'NUMBER_1', DoBuildNumber, 'NUMBER_1')
+        self.state.add_transition ('D', 'NUMBER_1', DoBack, 'INIT')
+        self.state.add_transition ('B', 'NUMBER_1', DoDown, 'INIT')
+        self.state.add_transition ('C', 'NUMBER_1', DoForward, 'INIT')
+        self.state.add_transition ('A', 'NUMBER_1', DoUp, 'INIT')
+        self.state.add_transition ('J', 'NUMBER_1', DoErase, 'INIT')
+        self.state.add_transition ('K', 'NUMBER_1', DoEraseLine, 'INIT')
+        self.state.add_transition ('l', 'NUMBER_1', DoMode, 'INIT')
+        ### It gets worse... the 'm' code can have infinite number of
+        ### number;number;number before it. I've never seen more than two,
+        ### but the specs say it's allowed. crap!
+        self.state.add_transition ('m', 'NUMBER_1', self.do_sgr, 'INIT')
+        ### LED control. Same implementation problem as 'm' code.
+        self.state.add_transition ('q', 'NUMBER_1', self.do_decsca, 'INIT')
+
+        # \E[?47h switch to alternate screen
+        # \E[?47l restores to normal screen from alternate screen.
+        self.state.add_transition_list (string.digits, 'MODECRAP', DoStartNumber, 'MODECRAP_NUM')
+        self.state.add_transition_list (string.digits, 'MODECRAP_NUM', DoBuildNumber, 'MODECRAP_NUM')
+        self.state.add_transition ('l', 'MODECRAP_NUM', self.do_modecrap, 'INIT')
+        self.state.add_transition ('h', 'MODECRAP_NUM', self.do_modecrap, 'INIT')
+
+#RM   Reset Mode                Esc [ Ps l                   none
+        self.state.add_transition (';', 'NUMBER_1', None, 'SEMICOLON')
+        self.state.add_transition_any ('SEMICOLON', DoLog, 'INIT')
+        self.state.add_transition_list (string.digits, 'SEMICOLON', DoStartNumber, 'NUMBER_2')
+        self.state.add_transition_list (string.digits, 'NUMBER_2', DoBuildNumber, 'NUMBER_2')
+        self.state.add_transition_any ('NUMBER_2', DoLog, 'INIT')
+        self.state.add_transition ('H', 'NUMBER_2', DoHome, 'INIT')
+        self.state.add_transition ('f', 'NUMBER_2', DoHome, 'INIT')
+        self.state.add_transition ('r', 'NUMBER_2', DoScrollRegion, 'INIT')
+        ### It gets worse... the 'm' code can have infinite number of
+        ### number;number;number before it. I've never seen more than two,
+        ### but the specs say it's allowed. crap!
+        self.state.add_transition ('m', 'NUMBER_2', self.do_sgr, 'INIT')
+        ### LED control. Same problem as 'm' code.
+        self.state.add_transition ('q', 'NUMBER_2', self.do_decsca, 'INIT')
+        self.state.add_transition (';', 'NUMBER_2', None, 'SEMICOLON_X')
+
+        # Create a state for 'q' and 'm' which allows an infinite number of ignored numbers
+        self.state.add_transition_any ('SEMICOLON_X', DoLog, 'INIT')
+        self.state.add_transition_list (string.digits, 'SEMICOLON_X', DoStartNumber, 'NUMBER_X')
+        self.state.add_transition_list (string.digits, 'NUMBER_X', DoBuildNumber, 'NUMBER_X')
+        self.state.add_transition_any ('NUMBER_X', DoLog, 'INIT')
+        self.state.add_transition ('m', 'NUMBER_X', self.do_sgr, 'INIT')
+        self.state.add_transition ('q', 'NUMBER_X', self.do_decsca, 'INIT')
+        self.state.add_transition (';', 'NUMBER_X', None, 'SEMICOLON_X')
+
+    def process (self, c):
+        """Process a single character. Called by :meth:`write`."""
+        if isinstance(c, bytes):
+            c = self._decode(c)
+        self.state.process(c)
+
+    def process_list (self, l):
+
+        self.write(l)
+
+    def write (self, s):
+        """Process text, writing it to the virtual screen while handling
+        ANSI escape codes.
+        """
+        if isinstance(s, bytes):
+            s = self._decode(s)
+        for c in s:
+            self.process(c)
+
+    def flush (self):
+        pass
+
+    def write_ch (self, ch):
+        '''This puts a character at the current cursor position. The cursor
+        position is moved forward with wrap-around, but no scrolling is done if
+        the cursor hits the lower-right corner of the screen. '''
+
+        if isinstance(ch, bytes):
+            ch = self._decode(ch)
+
+        #\r and \n both produce a call to cr() and lf(), respectively.
+        ch = ch[0]
+
+        if ch == u'\r':
+            self.cr()
+            return
+        if ch == u'\n':
+            self.crlf()
+            return
+        if ch == chr(screen.BS):
+            self.cursor_back()
+            return
+        self.put_abs(self.cur_r, self.cur_c, ch)
+        old_r = self.cur_r
+        old_c = self.cur_c
+        self.cursor_forward()
+        if old_c == self.cur_c:
+            self.cursor_down()
+            if old_r != self.cur_r:
+                self.cursor_home (self.cur_r, 1)
+            else:
+                self.scroll_up ()
+                self.cursor_home (self.cur_r, 1)
+                self.erase_line()
+
+    def do_sgr (self, fsm):
+        '''Select Graphic Rendition, e.g. color. '''
+        screen = fsm.memory[0]
+        fsm.memory = [screen]
+
+    def do_decsca (self, fsm):
+        '''Select character protection attribute. '''
+        screen = fsm.memory[0]
+        fsm.memory = [screen]
+
+    def do_modecrap (self, fsm):
+        '''Handler for \x1b[?<number>h and \x1b[?<number>l. If anyone
+        wanted to actually use these, they'd need to add more states to the
+        FSM rather than just improve or override this method. '''
+        screen = fsm.memory[0]
+        fsm.memory = [screen]
diff --git a/third_party/pexpect/pexpect/FSM.py b/third_party/pexpect/pexpect/FSM.py
new file mode 100644
index 0000000..46b392e
--- /dev/null
+++ b/third_party/pexpect/pexpect/FSM.py
@@ -0,0 +1,334 @@
+#!/usr/bin/env python
+
+'''This module implements a Finite State Machine (FSM). In addition to state
+this FSM also maintains a user defined "memory". So this FSM can be used as a
+Push-down Automata (PDA) since a PDA is a FSM + memory.
+
+The following describes how the FSM works, but you will probably also need to
+see the example function to understand how the FSM is used in practice.
+
+You define an FSM by building tables of transitions. For a given input symbol
+the process() method uses these tables to decide what action to call and what
+the next state will be. The FSM has a table of transitions that associate:
+
+        (input_symbol, current_state) --> (action, next_state)
+
+Where "action" is a function you define. The symbols and states can be any
+objects. You use the add_transition() and add_transition_list() methods to add
+to the transition table. The FSM also has a table of transitions that
+associate:
+
+        (current_state) --> (action, next_state)
+
+You use the add_transition_any() method to add to this transition table. The
+FSM also has one default transition that is not associated with any specific
+input_symbol or state. You use the set_default_transition() method to set the
+default transition.
+
+When an action function is called it is passed a reference to the FSM. The
+action function may then access attributes of the FSM such as input_symbol,
+current_state, or "memory". The "memory" attribute can be any object that you
+want to pass along to the action functions. It is not used by the FSM itself.
+For parsing you would typically pass a list to be used as a stack.
+
+The processing sequence is as follows. The process() method is given an
+input_symbol to process. The FSM will search the table of transitions that
+associate:
+
+        (input_symbol, current_state) --> (action, next_state)
+
+If the pair (input_symbol, current_state) is found then process() will call the
+associated action function and then set the current state to the next_state.
+
+If the FSM cannot find a match for (input_symbol, current_state) it will then
+search the table of transitions that associate:
+
+        (current_state) --> (action, next_state)
+
+If the current_state is found then the process() method will call the
+associated action function and then set the current state to the next_state.
+Notice that this table lacks an input_symbol. It lets you define transitions
+for a current_state and ANY input_symbol. Hence, it is called the "any" table.
+Remember, it is always checked after first searching the table for a specific
+(input_symbol, current_state).
+
+For the case where the FSM did not match either of the previous two cases the
+FSM will try to use the default transition. If the default transition is
+defined then the process() method will call the associated action function and
+then set the current state to the next_state. This lets you define a default
+transition as a catch-all case. You can think of it as an exception handler.
+There can be only one default transition.
+
+Finally, if none of the previous cases are defined for an input_symbol and
+current_state then the FSM will raise an exception. This may be desirable, but
+you can always prevent this just by defining a default transition.
+
+Noah Spurrier 20020822
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+class ExceptionFSM(Exception):
+
+    '''This is the FSM Exception class.'''
+
+    def __init__(self, value):
+        self.value = value
+
+    def __str__(self):
+        return 'ExceptionFSM: ' + str(self.value)
+
+class FSM:
+
+    '''This is a Finite State Machine (FSM).
+    '''
+
+    def __init__(self, initial_state, memory=None):
+
+        '''This creates the FSM. You set the initial state here. The "memory"
+        attribute is any object that you want to pass along to the action
+        functions. It is not used by the FSM. For parsing you would typically
+        pass a list to be used as a stack. '''
+
+        # Map (input_symbol, current_state) --> (action, next_state).
+        self.state_transitions = {}
+        # Map (current_state) --> (action, next_state).
+        self.state_transitions_any = {}
+        self.default_transition = None
+
+        self.input_symbol = None
+        self.initial_state = initial_state
+        self.current_state = self.initial_state
+        self.next_state = None
+        self.action = None
+        self.memory = memory
+
+    def reset (self):
+
+        '''This sets the current_state to the initial_state and sets
+        input_symbol to None. The initial state was set by the constructor
+        __init__(). '''
+
+        self.current_state = self.initial_state
+        self.input_symbol = None
+
+    def add_transition (self, input_symbol, state, action=None, next_state=None):
+
+        '''This adds a transition that associates:
+
+                (input_symbol, current_state) --> (action, next_state)
+
+        The action may be set to None in which case the process() method will
+        ignore the action and only set the next_state. The next_state may be
+        set to None in which case the current state will be unchanged.
+
+        You can also set transitions for a list of symbols by using
+        add_transition_list(). '''
+
+        if next_state is None:
+            next_state = state
+        self.state_transitions[(input_symbol, state)] = (action, next_state)
+
+    def add_transition_list (self, list_input_symbols, state, action=None, next_state=None):
+
+        '''This adds the same transition for a list of input symbols.
+        You can pass a list or a string. Note that it is handy to use
+        string.digits, string.whitespace, string.letters, etc. to add
+        transitions that match character classes.
+
+        The action may be set to None in which case the process() method will
+        ignore the action and only set the next_state. The next_state may be
+        set to None in which case the current state will be unchanged. '''
+
+        if next_state is None:
+            next_state = state
+        for input_symbol in list_input_symbols:
+            self.add_transition (input_symbol, state, action, next_state)
+
+    def add_transition_any (self, state, action=None, next_state=None):
+
+        '''This adds a transition that associates:
+
+                (current_state) --> (action, next_state)
+
+        That is, any input symbol will match the current state.
+        The process() method checks the "any" state associations after it first
+        checks for an exact match of (input_symbol, current_state).
+
+        The action may be set to None in which case the process() method will
+        ignore the action and only set the next_state. The next_state may be
+        set to None in which case the current state will be unchanged. '''
+
+        if next_state is None:
+            next_state = state
+        self.state_transitions_any [state] = (action, next_state)
+
+    def set_default_transition (self, action, next_state):
+
+        '''This sets the default transition. This defines an action and
+        next_state if the FSM cannot find the input symbol and the current
+        state in the transition list and if the FSM cannot find the
+        current_state in the transition_any list. This is useful as a final
+        fall-through state for catching errors and undefined states.
+
+        The default transition can be removed by setting the attribute
+        default_transition to None. '''
+
+        self.default_transition = (action, next_state)
+
+    def get_transition (self, input_symbol, state):
+
+        '''This returns (action, next state) given an input_symbol and state.
+        This does not modify the FSM state, so calling this method has no side
+        effects. Normally you do not call this method directly. It is called by
+        process().
+
+        The sequence of steps to check for a defined transition goes from the
+        most specific to the least specific.
+
+        1. Check state_transitions[] that match exactly the tuple,
+            (input_symbol, state)
+
+        2. Check state_transitions_any[] that match (state)
+            In other words, match a specific state and ANY input_symbol.
+
+        3. Check if the default_transition is defined.
+            This catches any input_symbol and any state.
+            This is a handler for errors, undefined states, or defaults.
+
+        4. No transition was defined. If we get here then raise an exception.
+        '''
+
+        if (input_symbol, state) in self.state_transitions:
+            return self.state_transitions[(input_symbol, state)]
+        elif state in self.state_transitions_any:
+            return self.state_transitions_any[state]
+        elif self.default_transition is not None:
+            return self.default_transition
+        else:
+            raise ExceptionFSM ('Transition is undefined: (%s, %s).' %
+                (str(input_symbol), str(state)) )
+
+    def process (self, input_symbol):
+
+        '''This is the main method that you call to process input. This may
+        cause the FSM to change state and call an action. This method calls
+        get_transition() to find the action and next_state associated with the
+        input_symbol and current_state. If the action is None then the action
+        is not called and only the current state is changed. This method
+        processes one complete input symbol. You can process a list of symbols
+        (or a string) by calling process_list(). '''
+
+        self.input_symbol = input_symbol
+        (self.action, self.next_state) = self.get_transition (self.input_symbol, self.current_state)
+        if self.action is not None:
+            self.action (self)
+        self.current_state = self.next_state
+        self.next_state = None
+
+    def process_list (self, input_symbols):
+
+        '''This takes a list and sends each element to process(). The list may
+        be a string or any iterable object. '''
+
+        for s in input_symbols:
+            self.process (s)
+
+##############################################################################
+# The following is an example that demonstrates the use of the FSM class to
+# process an RPN expression. Run this module from the command line. You will
+# get a prompt > for input. Enter an RPN Expression. Numbers may be integers.
+# Operators are * / + - Use the = sign to evaluate and print the expression.
+# For example:
+#
+#    167 3 2 2 * * * 1 - =
+#
+# will print:
+#
+#    2003
+##############################################################################
+
+import sys
+import string
+
+PY3 = (sys.version_info[0] >= 3)
+
+#
+# These define the actions.
+# Note that "memory" is a list being used as a stack.
+#
+
+def BeginBuildNumber (fsm):
+    fsm.memory.append (fsm.input_symbol)
+
+def BuildNumber (fsm):
+    s = fsm.memory.pop ()
+    s = s + fsm.input_symbol
+    fsm.memory.append (s)
+
+def EndBuildNumber (fsm):
+    s = fsm.memory.pop ()
+    fsm.memory.append (int(s))
+
+def DoOperator (fsm):
+    ar = fsm.memory.pop()
+    al = fsm.memory.pop()
+    if fsm.input_symbol == '+':
+        fsm.memory.append (al + ar)
+    elif fsm.input_symbol == '-':
+        fsm.memory.append (al - ar)
+    elif fsm.input_symbol == '*':
+        fsm.memory.append (al * ar)
+    elif fsm.input_symbol == '/':
+        fsm.memory.append (al / ar)
+
+def DoEqual (fsm):
+    print(str(fsm.memory.pop()))
+
+def Error (fsm):
+    print('That does not compute.')
+    print(str(fsm.input_symbol))
+
+def main():
+
+    '''This is where the example starts and the FSM state transitions are
+    defined. Note that states are strings (such as 'INIT'). This is not
+    necessary, but it makes the example easier to read. '''
+
+    f = FSM ('INIT', [])
+    f.set_default_transition (Error, 'INIT')
+    f.add_transition_any  ('INIT', None, 'INIT')
+    f.add_transition      ('=',               'INIT',            DoEqual,          'INIT')
+    f.add_transition_list (string.digits,     'INIT',            BeginBuildNumber, 'BUILDING_NUMBER')
+    f.add_transition_list (string.digits,     'BUILDING_NUMBER', BuildNumber,      'BUILDING_NUMBER')
+    f.add_transition_list (string.whitespace, 'BUILDING_NUMBER', EndBuildNumber,   'INIT')
+    f.add_transition_list ('+-*/',            'INIT',            DoOperator,       'INIT')
+
+    print()
+    print('Enter an RPN Expression.')
+    print('Numbers may be integers. Operators are * / + -')
+    print('Use the = sign to evaluate and print the expression.')
+    print('For example: ')
+    print('    167 3 2 2 * * * 1 - =')
+    inputstr = (input if PY3 else raw_input)('> ')  # analysis:ignore
+    f.process_list(inputstr)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/third_party/pexpect/pexpect/__init__.py b/third_party/pexpect/pexpect/__init__.py
new file mode 100644
index 0000000..c906e89
--- /dev/null
+++ b/third_party/pexpect/pexpect/__init__.py
@@ -0,0 +1,232 @@
+'''Pexpect is a Python module for spawning child applications and controlling
+them automatically. Pexpect can be used for automating interactive applications
+such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
+scripts for duplicating software package installations on different servers. It
+can be used for automated software testing. Pexpect is in the spirit of Don
+Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python
+require TCL and Expect or require C extensions to be compiled. Pexpect does not
+use C, Expect, or TCL extensions. It should work on any platform that supports
+the standard Python pty module. The Pexpect interface focuses on ease of use so
+that simple tasks are easy.
+
+There are two main interfaces to the Pexpect system; these are the function,
+run() and the class, spawn. The spawn class is more powerful. The run()
+function is simpler than spawn, and is good for quickly calling program. When
+you call the run() function it executes a given program and then returns the
+output. This is a handy replacement for os.system().
+
+For example::
+
+    pexpect.run('ls -la')
+
+The spawn class is the more powerful interface to the Pexpect system. You can
+use this to spawn a child program then interact with it by sending input and
+expecting responses (waiting for patterns in the child's output).
+
+For example::
+
+    child = pexpect.spawn('scp foo user at example.com:.')
+    child.expect('Password:')
+    child.sendline(mypassword)
+
+This works even for commands that ask for passwords or other input outside of
+the normal stdio streams. For example, ssh reads input directly from the TTY
+device which bypasses stdin.
+
+Credits: Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett,
+Robert Stone, Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids
+vander Molen, George Todd, Noel Taylor, Nicolas D. Cesar, Alexander Gattin,
+Jacques-Etienne Baudoux, Geoffrey Marshall, Francisco Lourenco, Glen Mabey,
+Karthik Gurusamy, Fernando Perez, Corey Minyard, Jon Cohen, Guillaume
+Chazarain, Andrew Ryan, Nick Craig-Wood, Andrew Stone, Jorgen Grahn, John
+Spiegel, Jan Grant, and Shane Kerr. Let me know if I forgot anyone.
+
+Pexpect is free, open source, and all that good stuff.
+http://pexpect.sourceforge.net/
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import sys
+import types
+
+from .exceptions import ExceptionPexpect, EOF, TIMEOUT
+from .utils import split_command_line, which, is_executable_file
+from .pty_spawn import spawn, spawnu, PY3
+from .expect import Expecter, searcher_re, searcher_string
+
+__version__ = '3.3'
+__revision__ = ''
+__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnu', 'run', 'runu',
+           'which', 'split_command_line', '__version__', '__revision__']
+
+def run(command, timeout=30, withexitstatus=False, events=None,
+        extra_args=None, logfile=None, cwd=None, env=None):
+
+    '''
+    This function runs the given command; waits for it to finish; then
+    returns all output as a string. STDERR is included in output. If the full
+    path to the command is not given then the path is searched.
+
+    Note that lines are terminated by CR/LF (\\r\\n) combination even on
+    UNIX-like systems because this is the standard for pseudottys. If you set
+    'withexitstatus' to true, then run will return a tuple of (command_output,
+    exitstatus). If 'withexitstatus' is false then this returns just
+    command_output.
+
+    The run() function can often be used instead of creating a spawn instance.
+    For example, the following code uses spawn::
+
+        from pexpect import *
+        child = spawn('scp foo user at example.com:.')
+        child.expect('(?i)password')
+        child.sendline(mypassword)
+
+    The previous code can be replace with the following::
+
+        from pexpect import *
+        run('scp foo user at example.com:.', events={'(?i)password': mypassword})
+
+    **Examples**
+
+    Start the apache daemon on the local machine::
+
+        from pexpect import *
+        run("/usr/local/apache/bin/apachectl start")
+
+    Check in a file using SVN::
+
+        from pexpect import *
+        run("svn ci -m 'automatic commit' my_file.py")
+
+    Run a command and capture exit status::
+
+        from pexpect import *
+        (command_output, exitstatus) = run('ls -l /bin', withexitstatus=1)
+
+    The following will run SSH and execute 'ls -l' on the remote machine. The
+    password 'secret' will be sent if the '(?i)password' pattern is ever seen::
+
+        run("ssh username at machine.example.com 'ls -l'",
+            events={'(?i)password':'secret\\n'})
+
+    This will start mencoder to rip a video from DVD. This will also display
+    progress ticks every 5 seconds as it runs. For example::
+
+        from pexpect import *
+        def print_ticks(d):
+            print d['event_count'],
+        run("mencoder dvd://1 -o video.avi -oac copy -ovc copy",
+            events={TIMEOUT:print_ticks}, timeout=5)
+
+    The 'events' argument should be either a dictionary or a tuple list that
+    contains patterns and responses. Whenever one of the patterns is seen
+    in the command output, run() will send the associated response string.
+    So, run() in the above example can be also written as:
+    
+        run("mencoder dvd://1 -o video.avi -oac copy -ovc copy",
+            events=[(TIMEOUT,print_ticks)], timeout=5)
+
+    Use a tuple list for events if the command output requires a delicate
+    control over what pattern should be matched, since the tuple list is passed
+    to pexpect() as its pattern list, with the order of patterns preserved.
+
+    Note that you should put newlines in your string if Enter is necessary.
+
+    Like the example above, the responses may also contain callback functions.
+    Any callback is a function that takes a dictionary as an argument.
+    The dictionary contains all the locals from the run() function, so you can
+    access the child spawn object or any other variable defined in run()
+    (event_count, child, and extra_args are the most useful). A callback may
+    return True to stop the current run process.  Otherwise run() continues
+    until the next event. A callback may also return a string which will be
+    sent to the child. 'extra_args' is not used by directly run(). It provides
+    a way to pass data to a callback function through run() through the locals
+    dictionary passed to a callback.
+    '''
+    return _run(command, timeout=timeout, withexitstatus=withexitstatus,
+                events=events, extra_args=extra_args, logfile=logfile, cwd=cwd,
+                env=env, _spawn=spawn)
+
+def runu(command, timeout=30, withexitstatus=False, events=None,
+        extra_args=None, logfile=None, cwd=None, env=None, **kwargs):
+    """This offers the same interface as :func:`run`, but using unicode.
+
+    Like :class:`spawnu`, you can pass ``encoding`` and ``errors`` parameters,
+    which will be used for both input and output.
+    """
+    return _run(command, timeout=timeout, withexitstatus=withexitstatus,
+                events=events, extra_args=extra_args, logfile=logfile, cwd=cwd,
+                env=env, _spawn=spawnu, **kwargs)
+
+def _run(command, timeout, withexitstatus, events, extra_args, logfile, cwd,
+         env, _spawn, **kwargs):
+    if timeout == -1:
+        child = _spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env,
+                        **kwargs)
+    else:
+        child = _spawn(command, timeout=timeout, maxread=2000, logfile=logfile,
+                cwd=cwd, env=env, **kwargs)
+    if isinstance(events, list):
+        patterns= [x for x,y in events]
+        responses = [y for x,y in events]
+    elif isinstance(events, dict):
+        patterns = list(events.keys())
+        responses = list(events.values())
+    else:
+        # This assumes EOF or TIMEOUT will eventually cause run to terminate.
+        patterns = None
+        responses = None
+    child_result_list = []
+    event_count = 0
+    while True:
+        try:
+            index = child.expect(patterns)
+            if isinstance(child.after, child.allowed_string_types):
+                child_result_list.append(child.before + child.after)
+            else:
+                # child.after may have been a TIMEOUT or EOF,
+                # which we don't want appended to the list.
+                child_result_list.append(child.before)
+            if isinstance(responses[index], child.allowed_string_types):
+                child.send(responses[index])
+            elif isinstance(responses[index], types.FunctionType):
+                callback_result = responses[index](locals())
+                sys.stdout.flush()
+                if isinstance(callback_result, child.allowed_string_types):
+                    child.send(callback_result)
+                elif callback_result:
+                    break
+            else:
+                raise TypeError('The callback must be a string or function.')
+            event_count = event_count + 1
+        except TIMEOUT:
+            child_result_list.append(child.before)
+            break
+        except EOF:
+            child_result_list.append(child.before)
+            break
+    child_result = child.string_type().join(child_result_list)
+    if withexitstatus:
+        child.close()
+        return (child_result, child.exitstatus)
+    else:
+        return child_result
+
+# vim: set shiftround expandtab tabstop=4 shiftwidth=4 ft=python autoindent :
diff --git a/third_party/pexpect/pexpect/async.py b/third_party/pexpect/pexpect/async.py
new file mode 100644
index 0000000..50eae3b
--- /dev/null
+++ b/third_party/pexpect/pexpect/async.py
@@ -0,0 +1,70 @@
+import asyncio
+import errno
+
+from pexpect import EOF
+
+ at asyncio.coroutine
+def expect_async(expecter, timeout=None):
+    # First process data that was previously read - if it maches, we don't need
+    # async stuff.    
+    idx = expecter.new_data(expecter.spawn.buffer)
+    expecter.spawn.buffer = expecter.spawn.string_type()
+    if idx:
+        return idx
+
+    transport, pw = yield from asyncio.get_event_loop()\
+        .connect_read_pipe(lambda: PatternWaiter(expecter), expecter.spawn)
+
+    try:
+        return (yield from asyncio.wait_for(pw.fut, timeout))
+    except asyncio.TimeoutError as e:
+        transport.pause_reading()
+        return expecter.timeout(e)
+
+class PatternWaiter(asyncio.Protocol):
+    def __init__(self, expecter):
+        self.expecter = expecter
+        self.fut = asyncio.Future()
+    
+    def found(self, result):
+        if not self.fut.done():
+            self.fut.set_result(result)
+    
+    def error(self, exc):
+        if not self.fut.done():
+            self.fut.set_exception(exc)
+    
+    def data_received(self, data):
+        spawn = self.expecter.spawn
+        s = spawn._coerce_read_string(data)
+        spawn._log(s, 'read')
+
+        if self.fut.done():
+            spawn.buffer += data
+            return
+
+        try:
+            index = self.expecter.new_data(data)
+            if index is not None:
+                # Found a match
+                self.found(index)
+        except Exception as e:
+            self.expecter.errored()
+            self.error(e)
+    
+    def eof_received(self):
+        # N.B. If this gets called, async will close the pipe (the spawn object)
+        # for us
+        try:
+            index = self.expecter.eof()
+        except EOF as e:
+            self.error(e)
+        else:
+            self.found(index)
+    
+    def connection_lost(self, exc):
+        if isinstance(exc, OSError) and exc.errno == errno.EIO:
+            # We may get here without eof_received being called, e.g on Linux
+            self.eof_received()
+        elif exc is not None:
+            self.error(exc)
\ No newline at end of file
diff --git a/third_party/pexpect/pexpect/bashrc.sh b/third_party/pexpect/pexpect/bashrc.sh
new file mode 100644
index 0000000..99a3ac2
--- /dev/null
+++ b/third_party/pexpect/pexpect/bashrc.sh
@@ -0,0 +1,5 @@
+source /etc/bash.bashrc
+source ~/.bashrc
+
+# Reset PS1 so pexpect can find it
+PS1="$"
diff --git a/third_party/pexpect/pexpect/exceptions.py b/third_party/pexpect/pexpect/exceptions.py
new file mode 100644
index 0000000..cb360f0
--- /dev/null
+++ b/third_party/pexpect/pexpect/exceptions.py
@@ -0,0 +1,35 @@
+"""Exception classes used by Pexpect"""
+
+import traceback
+import sys
+
+class ExceptionPexpect(Exception):
+    '''Base class for all exceptions raised by this module.
+    '''
+
+    def __init__(self, value):
+        super(ExceptionPexpect, self).__init__(value)
+        self.value = value
+
+    def __str__(self):
+        return str(self.value)
+
+    def get_trace(self):
+        '''This returns an abbreviated stack trace with lines that only concern
+        the caller. In other words, the stack trace inside the Pexpect module
+        is not included. '''
+
+        tblist = traceback.extract_tb(sys.exc_info()[2])
+        tblist = [item for item in tblist if ('pexpect/__init__' not in item[0])
+                                           and ('pexpect/expect' not in item[0])]
+        tblist = traceback.format_list(tblist)
+        return ''.join(tblist)
+
+
+class EOF(ExceptionPexpect):
+    '''Raised when EOF is read from a child.
+    This usually means the child has exited.'''
+
+
+class TIMEOUT(ExceptionPexpect):
+    '''Raised when a read time exceeds the timeout. '''
diff --git a/third_party/pexpect/pexpect/expect.py b/third_party/pexpect/pexpect/expect.py
new file mode 100644
index 0000000..6fde9e8
--- /dev/null
+++ b/third_party/pexpect/pexpect/expect.py
@@ -0,0 +1,297 @@
+import time
+
+from .exceptions import EOF, TIMEOUT
+
+class Expecter(object):
+    def __init__(self, spawn, searcher, searchwindowsize=-1):
+        self.spawn = spawn
+        self.searcher = searcher
+        if searchwindowsize == -1:
+            searchwindowsize = spawn.searchwindowsize
+        self.searchwindowsize = searchwindowsize
+    
+    def new_data(self, data):
+        spawn = self.spawn
+        searcher = self.searcher
+
+        incoming = spawn.buffer + data
+        freshlen = len(data)
+        index = searcher.search(incoming, freshlen, self.searchwindowsize)
+        if index >= 0:
+            spawn.buffer = incoming[searcher.end:]
+            spawn.before = incoming[: searcher.start]
+            spawn.after = incoming[searcher.start: searcher.end]
+            spawn.match = searcher.match
+            spawn.match_index = index
+            # Found a match
+            return index
+    
+        spawn.buffer = incoming
+    
+    def eof(self, err=None):
+        spawn = self.spawn
+        from . import EOF
+
+        spawn.before = spawn.buffer
+        spawn.buffer = spawn.string_type()
+        spawn.after = EOF
+        index = self.searcher.eof_index
+        if index >= 0:
+            spawn.match = EOF
+            spawn.match_index = index
+            return index
+        else:
+            spawn.match = None
+            spawn.match_index = None
+            msg = str(spawn)
+            if err is not None:
+                msg = str(err) + '\n' + msg
+            raise EOF(msg)
+    
+    def timeout(self, err=None):
+        spawn = self.spawn
+        from . import TIMEOUT
+
+        spawn.before = spawn.buffer
+        spawn.after = TIMEOUT
+        index = self.searcher.timeout_index
+        if index >= 0:
+            spawn.match = TIMEOUT
+            spawn.match_index = index
+            return index
+        else:
+            spawn.match = None
+            spawn.match_index = None
+            msg = str(spawn)
+            if err is not None:
+                msg = str(err) + '\n' + msg
+            raise TIMEOUT(msg)
+
+    def errored(self):
+        spawn = self.spawn
+        spawn.before = spawn.buffer
+        spawn.after = None
+        spawn.match = None
+        spawn.match_index = None
+    
+    def expect_loop(self, timeout=-1):
+        """Blocking expect"""
+        spawn = self.spawn
+        from . import EOF, TIMEOUT
+
+        if timeout is not None:
+            end_time = time.time() + timeout
+
+        try:
+            incoming = spawn.buffer
+            spawn.buffer = spawn.string_type()  # Treat buffer as new data
+            while True:
+                idx = self.new_data(incoming)
+                # Keep reading until exception or return.
+                if idx is not None:
+                    return idx
+                # No match at this point
+                if (timeout is not None) and (timeout < 0):
+                    return self.timeout()
+                # Still have time left, so read more data
+                incoming = spawn.read_nonblocking(spawn.maxread, timeout)
+                time.sleep(0.0001)
+                if timeout is not None:
+                    timeout = end_time - time.time()
+        except EOF as e:
+            return self.eof(e)
+        except TIMEOUT as e:
+            return self.timeout(e)
+        except:
+            self.errored()
+            raise
+
+
+class searcher_string(object):
+    '''This is a plain string search helper for the spawn.expect_any() method.
+    This helper class is for speed. For more powerful regex patterns
+    see the helper class, searcher_re.
+
+    Attributes:
+
+        eof_index     - index of EOF, or -1
+        timeout_index - index of TIMEOUT, or -1
+
+    After a successful match by the search() method the following attributes
+    are available:
+
+        start - index into the buffer, first byte of match
+        end   - index into the buffer, first byte after match
+        match - the matching string itself
+
+    '''
+
+    def __init__(self, strings):
+        '''This creates an instance of searcher_string. This argument 'strings'
+        may be a list; a sequence of strings; or the EOF or TIMEOUT types. '''
+
+        self.eof_index = -1
+        self.timeout_index = -1
+        self._strings = []
+        for n, s in enumerate(strings):
+            if s is EOF:
+                self.eof_index = n
+                continue
+            if s is TIMEOUT:
+                self.timeout_index = n
+                continue
+            self._strings.append((n, s))
+
+    def __str__(self):
+        '''This returns a human-readable string that represents the state of
+        the object.'''
+
+        ss = [(ns[0], '    %d: "%s"' % ns) for ns in self._strings]
+        ss.append((-1, 'searcher_string:'))
+        if self.eof_index >= 0:
+            ss.append((self.eof_index, '    %d: EOF' % self.eof_index))
+        if self.timeout_index >= 0:
+            ss.append((self.timeout_index,
+                '    %d: TIMEOUT' % self.timeout_index))
+        ss.sort()
+        ss = list(zip(*ss))[1]
+        return '\n'.join(ss)
+
+    def search(self, buffer, freshlen, searchwindowsize=None):
+        '''This searches 'buffer' for the first occurence of one of the search
+        strings.  'freshlen' must indicate the number of bytes at the end of
+        'buffer' which have not been searched before. It helps to avoid
+        searching the same, possibly big, buffer over and over again.
+
+        See class spawn for the 'searchwindowsize' argument.
+
+        If there is a match this returns the index of that string, and sets
+        'start', 'end' and 'match'. Otherwise, this returns -1. '''
+
+        first_match = None
+
+        # 'freshlen' helps a lot here. Further optimizations could
+        # possibly include:
+        #
+        # using something like the Boyer-Moore Fast String Searching
+        # Algorithm; pre-compiling the search through a list of
+        # strings into something that can scan the input once to
+        # search for all N strings; realize that if we search for
+        # ['bar', 'baz'] and the input is '...foo' we need not bother
+        # rescanning until we've read three more bytes.
+        #
+        # Sadly, I don't know enough about this interesting topic. /grahn
+
+        for index, s in self._strings:
+            if searchwindowsize is None:
+                # the match, if any, can only be in the fresh data,
+                # or at the very end of the old data
+                offset = -(freshlen + len(s))
+            else:
+                # better obey searchwindowsize
+                offset = -searchwindowsize
+            n = buffer.find(s, offset)
+            if n >= 0 and (first_match is None or n < first_match):
+                first_match = n
+                best_index, best_match = index, s
+        if first_match is None:
+            return -1
+        self.match = best_match
+        self.start = first_match
+        self.end = self.start + len(self.match)
+        return best_index
+
+
+class searcher_re(object):
+    '''This is regular expression string search helper for the
+    spawn.expect_any() method. This helper class is for powerful
+    pattern matching. For speed, see the helper class, searcher_string.
+
+    Attributes:
+
+        eof_index     - index of EOF, or -1
+        timeout_index - index of TIMEOUT, or -1
+
+    After a successful match by the search() method the following attributes
+    are available:
+
+        start - index into the buffer, first byte of match
+        end   - index into the buffer, first byte after match
+        match - the re.match object returned by a succesful re.search
+
+    '''
+
+    def __init__(self, patterns):
+        '''This creates an instance that searches for 'patterns' Where
+        'patterns' may be a list or other sequence of compiled regular
+        expressions, or the EOF or TIMEOUT types.'''
+
+        self.eof_index = -1
+        self.timeout_index = -1
+        self._searches = []
+        for n, s in zip(list(range(len(patterns))), patterns):
+            if s is EOF:
+                self.eof_index = n
+                continue
+            if s is TIMEOUT:
+                self.timeout_index = n
+                continue
+            self._searches.append((n, s))
+
+    def __str__(self):
+        '''This returns a human-readable string that represents the state of
+        the object.'''
+
+        #ss = [(n, '    %d: re.compile("%s")' %
+        #    (n, repr(s.pattern))) for n, s in self._searches]
+        ss = list()
+        for n, s in self._searches:
+            try:
+                ss.append((n, '    %d: re.compile("%s")' % (n, s.pattern)))
+            except UnicodeEncodeError:
+                # for test cases that display __str__ of searches, dont throw
+                # another exception just because stdout is ascii-only, using
+                # repr()
+                ss.append((n, '    %d: re.compile(%r)' % (n, s.pattern)))
+        ss.append((-1, 'searcher_re:'))
+        if self.eof_index >= 0:
+            ss.append((self.eof_index, '    %d: EOF' % self.eof_index))
+        if self.timeout_index >= 0:
+            ss.append((self.timeout_index, '    %d: TIMEOUT' %
+                self.timeout_index))
+        ss.sort()
+        ss = list(zip(*ss))[1]
+        return '\n'.join(ss)
+
+    def search(self, buffer, freshlen, searchwindowsize=None):
+        '''This searches 'buffer' for the first occurence of one of the regular
+        expressions. 'freshlen' must indicate the number of bytes at the end of
+        'buffer' which have not been searched before.
+
+        See class spawn for the 'searchwindowsize' argument.
+
+        If there is a match this returns the index of that string, and sets
+        'start', 'end' and 'match'. Otherwise, returns -1.'''
+
+        first_match = None
+        # 'freshlen' doesn't help here -- we cannot predict the
+        # length of a match, and the re module provides no help.
+        if searchwindowsize is None:
+            searchstart = 0
+        else:
+            searchstart = max(0, len(buffer) - searchwindowsize)
+        for index, s in self._searches:
+            match = s.search(buffer, searchstart)
+            if match is None:
+                continue
+            n = match.start()
+            if first_match is None or n < first_match:
+                first_match = n
+                the_match = match
+                best_index = index
+        if first_match is None:
+            return -1
+        self.start = first_match
+        self.match = the_match
+        self.end = self.match.end()
+        return best_index
\ No newline at end of file
diff --git a/third_party/pexpect/pexpect/fdpexpect.py b/third_party/pexpect/pexpect/fdpexpect.py
new file mode 100644
index 0000000..96ca2e1
--- /dev/null
+++ b/third_party/pexpect/pexpect/fdpexpect.py
@@ -0,0 +1,86 @@
+'''This is like pexpect, but it will work with any file descriptor that you
+pass it. You are reponsible for opening and close the file descriptor.
+This allows you to use Pexpect with sockets and named pipes (FIFOs).
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from .spawnbase import SpawnBase
+from .exceptions import ExceptionPexpect
+import os
+
+__all__ = ['fdspawn']
+
+class fdspawn(SpawnBase):
+    '''This is like pexpect.spawn but allows you to supply your own open file
+    descriptor. For example, you could use it to read through a file looking
+    for patterns, or to control a modem or serial device. '''
+
+    def __init__ (self, fd, args=None, timeout=30, maxread=2000, searchwindowsize=None, logfile=None):
+        '''This takes a file descriptor (an int) or an object that support the
+        fileno() method (returning an int). All Python file-like objects
+        support fileno(). '''
+
+        if type(fd) != type(0) and hasattr(fd, 'fileno'):
+            fd = fd.fileno()
+
+        if type(fd) != type(0):
+            raise ExceptionPexpect('The fd argument is not an int. If this is a command string then maybe you want to use pexpect.spawn.')
+
+        try: # make sure fd is a valid file descriptor
+            os.fstat(fd)
+        except OSError:
+            raise ExceptionPexpect('The fd argument is not a valid file descriptor.')
+
+        self.args = None
+        self.command = None
+        SpawnBase.__init__(self, timeout, maxread, searchwindowsize, logfile)
+        self.child_fd = fd
+        self.own_fd = False
+        self.closed = False
+        self.name = '<file descriptor %d>' % fd
+
+    def close (self):
+        """Close the file descriptor.
+
+        Calling this method a second time does nothing, but if the file
+        descriptor was closed elsewhere, :class:`OSError` will be raised.
+        """
+        if self.child_fd == -1:
+            return
+
+        self.flush()
+        os.close(self.child_fd)
+        self.child_fd = -1
+        self.closed = True
+
+    def isalive (self):
+        '''This checks if the file descriptor is still valid. If :func:`os.fstat`
+        does not raise an exception then we assume it is alive. '''
+
+        if self.child_fd == -1:
+            return False
+        try:
+            os.fstat(self.child_fd)
+            return True
+        except:
+            return False
+
+    def terminate (self, force=False):  # pragma: no cover
+        raise ExceptionPexpect('This method is not valid for file descriptors.')
diff --git a/third_party/pexpect/pexpect/pty_spawn.py b/third_party/pexpect/pexpect/pty_spawn.py
new file mode 100644
index 0000000..0663926
--- /dev/null
+++ b/third_party/pexpect/pexpect/pty_spawn.py
@@ -0,0 +1,819 @@
+import os
+import sys
+import time
+import select
+import re
+import pty
+import tty
+import termios
+import errno
+import signal
+from contextlib import contextmanager
+
+import ptyprocess
+from ptyprocess.ptyprocess import use_native_pty_fork
+
+from .exceptions import ExceptionPexpect, EOF, TIMEOUT
+from .spawnbase import SpawnBase, SpawnBaseUnicode
+from .utils import which, split_command_line
+
+ at contextmanager
+def _wrap_ptyprocess_err():
+    """Turn ptyprocess errors into our own ExceptionPexpect errors"""
+    try:
+        yield
+    except ptyprocess.PtyProcessError as e:
+        raise ExceptionPexpect(*e.args)
+
+PY3 = (sys.version_info[0] >= 3)
+
+class spawn(SpawnBase):
+    '''This is the main class interface for Pexpect. Use this class to start
+    and control child applications. '''
+    ptyprocess_class = ptyprocess.PtyProcess
+
+    # This is purely informational now - changing it has no effect
+    use_native_pty_fork = use_native_pty_fork
+
+    def __init__(self, command, args=[], timeout=30, maxread=2000,
+                 searchwindowsize=None, logfile=None, cwd=None, env=None,
+                 ignore_sighup=True, echo=True, preexec_fn=None):
+        '''This is the constructor. The command parameter may be a string that
+        includes a command and any arguments to the command. For example::
+
+            child = pexpect.spawn('/usr/bin/ftp')
+            child = pexpect.spawn('/usr/bin/ssh user at example.com')
+            child = pexpect.spawn('ls -latr /tmp')
+
+        You may also construct it with a list of arguments like so::
+
+            child = pexpect.spawn('/usr/bin/ftp', [])
+            child = pexpect.spawn('/usr/bin/ssh', ['user at example.com'])
+            child = pexpect.spawn('ls', ['-latr', '/tmp'])
+
+        After this the child application will be created and will be ready to
+        talk to. For normal use, see expect() and send() and sendline().
+
+        Remember that Pexpect does NOT interpret shell meta characters such as
+        redirect, pipe, or wild cards (``>``, ``|``, or ``*``). This is a
+        common mistake.  If you want to run a command and pipe it through
+        another command then you must also start a shell. For example::
+
+            child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > logs.txt"')
+            child.expect(pexpect.EOF)
+
+        The second form of spawn (where you pass a list of arguments) is useful
+        in situations where you wish to spawn a command and pass it its own
+        argument list. This can make syntax more clear. For example, the
+        following is equivalent to the previous example::
+
+            shell_cmd = 'ls -l | grep LOG > logs.txt'
+            child = pexpect.spawn('/bin/bash', ['-c', shell_cmd])
+            child.expect(pexpect.EOF)
+
+        The maxread attribute sets the read buffer size. This is maximum number
+        of bytes that Pexpect will try to read from a TTY at one time. Setting
+        the maxread size to 1 will turn off buffering. Setting the maxread
+        value higher may help performance in cases where large amounts of
+        output are read back from the child. This feature is useful in
+        conjunction with searchwindowsize.
+
+        The searchwindowsize attribute sets the how far back in the incoming
+        seach buffer Pexpect will search for pattern matches. Every time
+        Pexpect reads some data from the child it will append the data to the
+        incoming buffer. The default is to search from the beginning of the
+        incoming buffer each time new data is read from the child. But this is
+        very inefficient if you are running a command that generates a large
+        amount of data where you want to match. The searchwindowsize does not
+        affect the size of the incoming data buffer. You will still have
+        access to the full buffer after expect() returns.
+
+        The logfile member turns on or off logging. All input and output will
+        be copied to the given file object. Set logfile to None to stop
+        logging. This is the default. Set logfile to sys.stdout to echo
+        everything to standard output. The logfile is flushed after each write.
+
+        Example log input and output to a file::
+
+            child = pexpect.spawn('some_command')
+            fout = open('mylog.txt','wb')
+            child.logfile = fout
+
+        Example log to stdout::
+
+            # In Python 2:
+            child = pexpect.spawn('some_command')
+            child.logfile = sys.stdout
+
+            # In Python 3, spawnu should be used to give str to stdout:
+            child = pexpect.spawnu('some_command')
+            child.logfile = sys.stdout
+
+        The logfile_read and logfile_send members can be used to separately log
+        the input from the child and output sent to the child. Sometimes you
+        don't want to see everything you write to the child. You only want to
+        log what the child sends back. For example::
+
+            child = pexpect.spawn('some_command')
+            child.logfile_read = sys.stdout
+
+        Remember to use spawnu instead of spawn for the above code if you are
+        using Python 3.
+
+        To separately log output sent to the child use logfile_send::
+
+            child.logfile_send = fout
+
+        If ``ignore_sighup`` is True, the child process will ignore SIGHUP
+        signals. For now, the default is True, to preserve the behaviour of
+        earlier versions of Pexpect, but you should pass this explicitly if you
+        want to rely on it.
+
+        The delaybeforesend helps overcome a weird behavior that many users
+        were experiencing. The typical problem was that a user would expect() a
+        "Password:" prompt and then immediately call sendline() to send the
+        password. The user would then see that their password was echoed back
+        to them. Passwords don't normally echo. The problem is caused by the
+        fact that most applications print out the "Password" prompt and then
+        turn off stdin echo, but if you send your password before the
+        application turned off echo, then you get your password echoed.
+        Normally this wouldn't be a problem when interacting with a human at a
+        real keyboard. If you introduce a slight delay just before writing then
+        this seems to clear up the problem. This was such a common problem for
+        many users that I decided that the default pexpect behavior should be
+        to sleep just before writing to the child application. 1/20th of a
+        second (50 ms) seems to be enough to clear up the problem. You can set
+        delaybeforesend to 0 to return to the old behavior. Most Linux machines
+        don't like this to be below 0.03. I don't know why.
+
+        Note that spawn is clever about finding commands on your path.
+        It uses the same logic that "which" uses to find executables.
+
+        If you wish to get the exit status of the child you must call the
+        close() method. The exit or signal status of the child will be stored
+        in self.exitstatus or self.signalstatus. If the child exited normally
+        then exitstatus will store the exit return code and signalstatus will
+        be None. If the child was terminated abnormally with a signal then
+        signalstatus will store the signal value and exitstatus will be None.
+        If you need more detail you can also read the self.status member which
+        stores the status returned by os.waitpid. You can interpret this using
+        os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG.
+
+        The echo attribute may be set to False to disable echoing of input.
+        As a pseudo-terminal, all input echoed by the "keyboard" (send()
+        or sendline()) will be repeated to output.  For many cases, it is
+        not desirable to have echo enabled, and it may be later disabled
+        using setecho(False) followed by waitnoecho().  However, for some
+        platforms such as Solaris, this is not possible, and should be
+        disabled immediately on spawn.
+        
+        If preexec_fn is given, it will be called in the child process before
+        launching the given command. This is useful to e.g. reset inherited
+        signal handlers.
+        '''
+        super(spawn, self).__init__(timeout=timeout, maxread=maxread, searchwindowsize=searchwindowsize,
+                                    logfile=logfile)
+        self.STDIN_FILENO = pty.STDIN_FILENO
+        self.STDOUT_FILENO = pty.STDOUT_FILENO
+        self.STDERR_FILENO = pty.STDERR_FILENO
+        self.cwd = cwd
+        self.env = env
+        self.echo = echo
+        self.ignore_sighup = ignore_sighup
+        self.__irix_hack = sys.platform.lower().startswith('irix')
+        if command is None:
+            self.command = None
+            self.args = None
+            self.name = '<pexpect factory incomplete>'
+        else:
+            self._spawn(command, args, preexec_fn)
+
+    def __str__(self):
+        '''This returns a human-readable string that represents the state of
+        the object. '''
+
+        s = []
+        s.append(repr(self))
+        s.append('command: ' + str(self.command))
+        s.append('args: %r' % (self.args,))
+        s.append('searcher: %r' % (self.searcher,))
+        s.append('buffer (last 100 chars): %r' % (
+                self.buffer[-100:] if self.buffer else self.buffer,))
+        s.append('before (last 100 chars): %r' % (
+                self.before[-100:] if self.before else self.before,))
+        s.append('after: %r' % (self.after,))
+        s.append('match: %r' % (self.match,))
+        s.append('match_index: ' + str(self.match_index))
+        s.append('exitstatus: ' + str(self.exitstatus))
+        s.append('flag_eof: ' + str(self.flag_eof))
+        s.append('pid: ' + str(self.pid))
+        s.append('child_fd: ' + str(self.child_fd))
+        s.append('closed: ' + str(self.closed))
+        s.append('timeout: ' + str(self.timeout))
+        s.append('delimiter: ' + str(self.delimiter))
+        s.append('logfile: ' + str(self.logfile))
+        s.append('logfile_read: ' + str(self.logfile_read))
+        s.append('logfile_send: ' + str(self.logfile_send))
+        s.append('maxread: ' + str(self.maxread))
+        s.append('ignorecase: ' + str(self.ignorecase))
+        s.append('searchwindowsize: ' + str(self.searchwindowsize))
+        s.append('delaybeforesend: ' + str(self.delaybeforesend))
+        s.append('delayafterclose: ' + str(self.delayafterclose))
+        s.append('delayafterterminate: ' + str(self.delayafterterminate))
+        return '\n'.join(s)
+
+    def _spawn(self, command, args=[], preexec_fn=None):
+        '''This starts the given command in a child process. This does all the
+        fork/exec type of stuff for a pty. This is called by __init__. If args
+        is empty then command will be parsed (split on spaces) and args will be
+        set to parsed arguments. '''
+
+        # The pid and child_fd of this object get set by this method.
+        # Note that it is difficult for this method to fail.
+        # You cannot detect if the child process cannot start.
+        # So the only way you can tell if the child process started
+        # or not is to try to read from the file descriptor. If you get
+        # EOF immediately then it means that the child is already dead.
+        # That may not necessarily be bad because you may have spawned a child
+        # that performs some task; creates no stdout output; and then dies.
+
+        # If command is an int type then it may represent a file descriptor.
+        if isinstance(command, type(0)):
+            raise ExceptionPexpect('Command is an int type. ' +
+                    'If this is a file descriptor then maybe you want to ' +
+                    'use fdpexpect.fdspawn which takes an existing ' +
+                    'file descriptor instead of a command string.')
+
+        if not isinstance(args, type([])):
+            raise TypeError('The argument, args, must be a list.')
+
+        if args == []:
+            self.args = split_command_line(command)
+            self.command = self.args[0]
+        else:
+            # Make a shallow copy of the args list.
+            self.args = args[:]
+            self.args.insert(0, command)
+            self.command = command
+
+        command_with_path = which(self.command)
+        if command_with_path is None:
+            raise ExceptionPexpect('The command was not found or was not ' +
+                    'executable: %s.' % self.command)
+        self.command = command_with_path
+        self.args[0] = self.command
+
+        self.name = '<' + ' '.join(self.args) + '>'
+
+        assert self.pid is None, 'The pid member must be None.'
+        assert self.command is not None, 'The command member must not be None.'
+
+        kwargs = {'echo': self.echo, 'preexec_fn': preexec_fn}
+        if self.ignore_sighup:
+            def preexec_wrapper():
+                "Set SIGHUP to be ignored, then call the real preexec_fn"
+                signal.signal(signal.SIGHUP, signal.SIG_IGN)
+                if preexec_fn is not None:
+                    preexec_fn()
+            kwargs['preexec_fn'] = preexec_wrapper
+
+        self.ptyproc = self.ptyprocess_class.spawn(self.args, env=self.env,
+                                                   cwd=self.cwd, **kwargs)
+
+        self.pid = self.ptyproc.pid
+        self.child_fd = self.ptyproc.fd
+
+
+        self.terminated = False
+        self.closed = False
+
+    def close(self, force=True):
+        '''This closes the connection with the child application. Note that
+        calling close() more than once is valid. This emulates standard Python
+        behavior with files. Set force to True if you want to make sure that
+        the child is terminated (SIGKILL is sent if the child ignores SIGHUP
+        and SIGINT). '''
+
+        self.flush()
+        self.ptyproc.close()
+        self.isalive()  # Update exit status from ptyproc
+        self.child_fd = -1
+
+    def isatty(self):
+        '''This returns True if the file descriptor is open and connected to a
+        tty(-like) device, else False.
+
+        On SVR4-style platforms implementing streams, such as SunOS and HP-UX,
+        the child pty may not appear as a terminal device.  This means
+        methods such as setecho(), setwinsize(), getwinsize() may raise an
+        IOError. '''
+
+        return os.isatty(self.child_fd)
+
+    def waitnoecho(self, timeout=-1):
+        '''This waits until the terminal ECHO flag is set False. This returns
+        True if the echo mode is off. This returns False if the ECHO flag was
+        not set False before the timeout. This can be used to detect when the
+        child is waiting for a password. Usually a child application will turn
+        off echo mode when it is waiting for the user to enter a password. For
+        example, instead of expecting the "password:" prompt you can wait for
+        the child to set ECHO off::
+
+            p = pexpect.spawn('ssh user at example.com')
+            p.waitnoecho()
+            p.sendline(mypassword)
+
+        If timeout==-1 then this method will use the value in self.timeout.
+        If timeout==None then this method to block until ECHO flag is False.
+        '''
+
+        if timeout == -1:
+            timeout = self.timeout
+        if timeout is not None:
+            end_time = time.time() + timeout
+        while True:
+            if not self.getecho():
+                return True
+            if timeout < 0 and timeout is not None:
+                return False
+            if timeout is not None:
+                timeout = end_time - time.time()
+            time.sleep(0.1)
+
+    def getecho(self):
+        '''This returns the terminal echo mode. This returns True if echo is
+        on or False if echo is off. Child applications that are expecting you
+        to enter a password often set ECHO False. See waitnoecho().
+
+        Not supported on platforms where ``isatty()`` returns False.  '''
+        return self.ptyproc.getecho()
+
+    def setecho(self, state):
+        '''This sets the terminal echo mode on or off. Note that anything the
+        child sent before the echo will be lost, so you should be sure that
+        your input buffer is empty before you call setecho(). For example, the
+        following will work as expected::
+
+            p = pexpect.spawn('cat') # Echo is on by default.
+            p.sendline('1234') # We expect see this twice from the child...
+            p.expect(['1234']) # ... once from the tty echo...
+            p.expect(['1234']) # ... and again from cat itself.
+            p.setecho(False) # Turn off tty echo
+            p.sendline('abcd') # We will set this only once (echoed by cat).
+            p.sendline('wxyz') # We will set this only once (echoed by cat)
+            p.expect(['abcd'])
+            p.expect(['wxyz'])
+
+        The following WILL NOT WORK because the lines sent before the setecho
+        will be lost::
+
+            p = pexpect.spawn('cat')
+            p.sendline('1234')
+            p.setecho(False) # Turn off tty echo
+            p.sendline('abcd') # We will set this only once (echoed by cat).
+            p.sendline('wxyz') # We will set this only once (echoed by cat)
+            p.expect(['1234'])
+            p.expect(['1234'])
+            p.expect(['abcd'])
+            p.expect(['wxyz'])
+
+
+        Not supported on platforms where ``isatty()`` returns False.
+        '''
+        return self.ptyproc.setecho(state)
+
+        self.echo = state
+
+    def read_nonblocking(self, size=1, timeout=-1):
+        '''This reads at most size characters from the child application. It
+        includes a timeout. If the read does not complete within the timeout
+        period then a TIMEOUT exception is raised. If the end of file is read
+        then an EOF exception will be raised. If a log file was set using
+        setlog() then all data will also be written to the log file.
+
+        If timeout is None then the read may block indefinitely.
+        If timeout is -1 then the self.timeout value is used. If timeout is 0
+        then the child is polled and if there is no data immediately ready
+        then this will raise a TIMEOUT exception.
+
+        The timeout refers only to the amount of time to read at least one
+        character. This is not effected by the 'size' parameter, so if you call
+        read_nonblocking(size=100, timeout=30) and only one character is
+        available right away then one character will be returned immediately.
+        It will not wait for 30 seconds for another 99 characters to come in.
+
+        This is a wrapper around os.read(). It uses select.select() to
+        implement the timeout. '''
+
+        if self.closed:
+            raise ValueError('I/O operation on closed file.')
+
+        if timeout == -1:
+            timeout = self.timeout
+
+        # Note that some systems such as Solaris do not give an EOF when
+        # the child dies. In fact, you can still try to read
+        # from the child_fd -- it will block forever or until TIMEOUT.
+        # For this case, I test isalive() before doing any reading.
+        # If isalive() is false, then I pretend that this is the same as EOF.
+        if not self.isalive():
+            # timeout of 0 means "poll"
+            r, w, e = self.__select([self.child_fd], [], [], 0)
+            if not r:
+                self.flag_eof = True
+                raise EOF('End Of File (EOF). Braindead platform.')
+        elif self.__irix_hack:
+            # Irix takes a long time before it realizes a child was terminated.
+            # FIXME So does this mean Irix systems are forced to always have
+            # FIXME a 2 second delay when calling read_nonblocking? That sucks.
+            r, w, e = self.__select([self.child_fd], [], [], 2)
+            if not r and not self.isalive():
+                self.flag_eof = True
+                raise EOF('End Of File (EOF). Slow platform.')
+
+        r, w, e = self.__select([self.child_fd], [], [], timeout)
+
+        if not r:
+            if not self.isalive():
+                # Some platforms, such as Irix, will claim that their
+                # processes are alive; timeout on the select; and
+                # then finally admit that they are not alive.
+                self.flag_eof = True
+                raise EOF('End of File (EOF). Very slow platform.')
+            else:
+                raise TIMEOUT('Timeout exceeded.')
+
+        if self.child_fd in r:
+            return super(spawn, self).read_nonblocking(size)
+
+        raise ExceptionPexpect('Reached an unexpected state.')  # pragma: no cover
+
+    def write(self, s):
+        '''This is similar to send() except that there is no return value.
+        '''
+
+        self.send(s)
+
+    def writelines(self, sequence):
+        '''This calls write() for each element in the sequence. The sequence
+        can be any iterable object producing strings, typically a list of
+        strings. This does not add line separators. There is no return value.
+        '''
+
+        for s in sequence:
+            self.write(s)
+
+    def send(self, s):
+        '''Sends string ``s`` to the child process, returning the number of
+        bytes written. If a logfile is specified, a copy is written to that
+        log.
+
+        The default terminal input mode is canonical processing unless set
+        otherwise by the child process. This allows backspace and other line
+        processing to be performed prior to transmitting to the receiving
+        program. As this is buffered, there is a limited size of such buffer.
+
+        On Linux systems, this is 4096 (defined by N_TTY_BUF_SIZE). All
+        other systems honor the POSIX.1 definition PC_MAX_CANON -- 1024
+        on OSX, 256 on OpenSolaris, 255 on FreeBSD.
+
+        This value may be discovered using fpathconf(3)::
+
+        >>> from os import fpathconf
+        >>> print(fpathconf(0, 'PC_MAX_CANON'))
+        256
+
+        On such a system, only 256 bytes may be received per line. Any
+        subsequent bytes received will be discarded. BEL (``'\a'``) is then
+        sent to output if IMAXBEL (termios.h) is set by the tty driver.
+        This is usually enabled by default.  Linux does not honor this as
+        an option -- it behaves as though it is always set on.
+
+        Canonical input processing may be disabled altogether by executing
+        a shell, then stty(1), before executing the final program::
+
+        >>> bash = pexpect.spawn('/bin/bash', echo=False)
+        >>> bash.sendline('stty -icanon')
+        >>> bash.sendline('base64')
+        >>> bash.sendline('x' * 5000)
+        '''
+
+        time.sleep(self.delaybeforesend)
+
+        s = self._coerce_send_string(s)
+        self._log(s, 'send')
+
+        return self._send(s)
+
+    def _send(self, s):
+        return os.write(self.child_fd, s)
+
+    def sendline(self, s=''):
+        '''Wraps send(), sending string ``s`` to child process, with
+        ``os.linesep`` automatically appended. Returns number of bytes
+        written.  Only a limited number of bytes may be sent for each
+        line in the default terminal mode, see docstring of :meth:`send`.
+        '''
+
+        n = self.send(s)
+        n = n + self.send(self.linesep)
+        return n
+
+    def _log_control(self, byte):
+        """Write control characters to the appropriate log files"""
+        self._log(byte, 'send')
+
+    def sendcontrol(self, char):
+        '''Helper method that wraps send() with mnemonic access for sending control
+        character to the child (such as Ctrl-C or Ctrl-D).  For example, to send
+        Ctrl-G (ASCII 7, bell, '\a')::
+
+            child.sendcontrol('g')
+
+        See also, sendintr() and sendeof().
+        '''
+        n, byte = self.ptyproc.sendcontrol(char)
+        self._log_control(byte)
+        return n
+
+    def sendeof(self):
+        '''This sends an EOF to the child. This sends a character which causes
+        the pending parent output buffer to be sent to the waiting child
+        program without waiting for end-of-line. If it is the first character
+        of the line, the read() in the user program returns 0, which signifies
+        end-of-file. This means to work as expected a sendeof() has to be
+        called at the beginning of a line. This method does not send a newline.
+        It is the responsibility of the caller to ensure the eof is sent at the
+        beginning of a line. '''
+
+        n, byte = self.ptyproc.sendeof()
+        self._log_control(byte)
+
+    def sendintr(self):
+        '''This sends a SIGINT to the child. It does not require
+        the SIGINT to be the first character on a line. '''
+
+        n, byte = self.ptyproc.sendintr()
+        self._log_control(byte)
+
+    @property
+    def flag_eof(self):
+        return self.ptyproc.flag_eof
+
+    @flag_eof.setter
+    def flag_eof(self, value):
+        self.ptyproc.flag_eof = value
+
+    def eof(self):
+        '''This returns True if the EOF exception was ever raised.
+        '''
+        return self.flag_eof
+
+    def terminate(self, force=False):
+        '''This forces a child process to terminate. It starts nicely with
+        SIGHUP and SIGINT. If "force" is True then moves onto SIGKILL. This
+        returns True if the child was terminated. This returns False if the
+        child could not be terminated. '''
+
+        if not self.isalive():
+            return True
+        try:
+            self.kill(signal.SIGHUP)
+            time.sleep(self.delayafterterminate)
+            if not self.isalive():
+                return True
+            self.kill(signal.SIGCONT)
+            time.sleep(self.delayafterterminate)
+            if not self.isalive():
+                return True
+            self.kill(signal.SIGINT)
+            time.sleep(self.delayafterterminate)
+            if not self.isalive():
+                return True
+            if force:
+                self.kill(signal.SIGKILL)
+                time.sleep(self.delayafterterminate)
+                if not self.isalive():
+                    return True
+                else:
+                    return False
+            return False
+        except OSError:
+            # I think there are kernel timing issues that sometimes cause
+            # this to happen. I think isalive() reports True, but the
+            # process is dead to the kernel.
+            # Make one last attempt to see if the kernel is up to date.
+            time.sleep(self.delayafterterminate)
+            if not self.isalive():
+                return True
+            else:
+                return False
+
+    def wait(self):
+        '''This waits until the child exits. This is a blocking call. This will
+        not read any data from the child, so this will block forever if the
+        child has unread output and has terminated. In other words, the child
+        may have printed output then called exit(), but, the child is
+        technically still alive until its output is read by the parent. '''
+
+        ptyproc = self.ptyproc
+        with _wrap_ptyprocess_err():
+            exitstatus = ptyproc.wait()
+        self.status = ptyproc.status
+        self.exitstatus = ptyproc.exitstatus
+        self.signalstatus = ptyproc.signalstatus
+        self.terminated = True
+
+        return exitstatus
+
+    def isalive(self):
+        '''This tests if the child process is running or not. This is
+        non-blocking. If the child was terminated then this will read the
+        exitstatus or signalstatus of the child. This returns True if the child
+        process appears to be running or False if not. It can take literally
+        SECONDS for Solaris to return the right status. '''
+
+        ptyproc = self.ptyproc
+        with _wrap_ptyprocess_err():
+            alive = ptyproc.isalive()
+
+        if not alive:
+            self.status = ptyproc.status
+            self.exitstatus = ptyproc.exitstatus
+            self.signalstatus = ptyproc.signalstatus
+            self.terminated = True
+
+        return alive
+
+    def kill(self, sig):
+
+        '''This sends the given signal to the child application. In keeping
+        with UNIX tradition it has a misleading name. It does not necessarily
+        kill the child unless you send the right signal. '''
+
+        # Same as os.kill, but the pid is given for you.
+        if self.isalive():
+            os.kill(self.pid, sig)
+
+    def getwinsize(self):
+        '''This returns the terminal window size of the child tty. The return
+        value is a tuple of (rows, cols). '''
+        return self.ptyproc.getwinsize()
+
+    def setwinsize(self, rows, cols):
+        '''This sets the terminal window size of the child tty. This will cause
+        a SIGWINCH signal to be sent to the child. This does not change the
+        physical window size. It changes the size reported to TTY-aware
+        applications like vi or curses -- applications that respond to the
+        SIGWINCH signal. '''
+        return self.ptyproc.setwinsize(rows, cols)
+
+
+    def interact(self, escape_character=chr(29),
+            input_filter=None, output_filter=None):
+
+        '''This gives control of the child process to the interactive user (the
+        human at the keyboard). Keystrokes are sent to the child process, and
+        the stdout and stderr output of the child process is printed. This
+        simply echos the child stdout and child stderr to the real stdout and
+        it echos the real stdin to the child stdin. When the user types the
+        escape_character this method will stop. The default for
+        escape_character is ^]. This should not be confused with ASCII 27 --
+        the ESC character. ASCII 29 was chosen for historical merit because
+        this is the character used by 'telnet' as the escape character. The
+        escape_character will not be sent to the child process.
+
+        You may pass in optional input and output filter functions. These
+        functions should take a string and return a string. The output_filter
+        will be passed all the output from the child process. The input_filter
+        will be passed all the keyboard input from the user. The input_filter
+        is run BEFORE the check for the escape_character.
+
+        Note that if you change the window size of the parent the SIGWINCH
+        signal will not be passed through to the child. If you want the child
+        window size to change when the parent's window size changes then do
+        something like the following example::
+
+            import pexpect, struct, fcntl, termios, signal, sys
+            def sigwinch_passthrough (sig, data):
+                s = struct.pack("HHHH", 0, 0, 0, 0)
+                a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(),
+                    termios.TIOCGWINSZ , s))
+                global p
+                p.setwinsize(a[0],a[1])
+            # Note this 'p' global and used in sigwinch_passthrough.
+            p = pexpect.spawn('/bin/bash')
+            signal.signal(signal.SIGWINCH, sigwinch_passthrough)
+            p.interact()
+        '''
+
+        # Flush the buffer.
+        self.write_to_stdout(self.buffer)
+        self.stdout.flush()
+        self.buffer = self.string_type()
+        mode = tty.tcgetattr(self.STDIN_FILENO)
+        tty.setraw(self.STDIN_FILENO)
+        if PY3:
+            escape_character = escape_character.encode('latin-1')
+        try:
+            self.__interact_copy(escape_character, input_filter, output_filter)
+        finally:
+            tty.tcsetattr(self.STDIN_FILENO, tty.TCSAFLUSH, mode)
+
+    def __interact_writen(self, fd, data):
+        '''This is used by the interact() method.
+        '''
+
+        while data != b'' and self.isalive():
+            n = os.write(fd, data)
+            data = data[n:]
+
+    def __interact_read(self, fd):
+        '''This is used by the interact() method.
+        '''
+
+        return os.read(fd, 1000)
+
+    def __interact_copy(self, escape_character=None,
+            input_filter=None, output_filter=None):
+
+        '''This is used by the interact() method.
+        '''
+
+        while self.isalive():
+            r, w, e = self.__select([self.child_fd, self.STDIN_FILENO], [], [])
+            if self.child_fd in r:
+                try:
+                    data = self.__interact_read(self.child_fd)
+                except OSError as err:
+                    if err.args[0] == errno.EIO:
+                        # Linux-style EOF
+                        break
+                    raise
+                if data == b'':
+                    # BSD-style EOF
+                    break
+                if output_filter:
+                    data = output_filter(data)
+                if self.logfile is not None:
+                    self.logfile.write(data)
+                    self.logfile.flush()
+                os.write(self.STDOUT_FILENO, data)
+            if self.STDIN_FILENO in r:
+                data = self.__interact_read(self.STDIN_FILENO)
+                if input_filter:
+                    data = input_filter(data)
+                i = data.rfind(escape_character)
+                if i != -1:
+                    data = data[:i]
+                    self.__interact_writen(self.child_fd, data)
+                    break
+                self.__interact_writen(self.child_fd, data)
+
+    def __select(self, iwtd, owtd, ewtd, timeout=None):
+
+        '''This is a wrapper around select.select() that ignores signals. If
+        select.select raises a select.error exception and errno is an EINTR
+        error then it is ignored. Mainly this is used to ignore sigwinch
+        (terminal resize). '''
+
+        # if select() is interrupted by a signal (errno==EINTR) then
+        # we loop back and enter the select() again.
+        if timeout is not None:
+            end_time = time.time() + timeout
+        while True:
+            try:
+                return select.select(iwtd, owtd, ewtd, timeout)
+            except select.error:
+                err = sys.exc_info()[1]
+                if err.args[0] == errno.EINTR:
+                    # if we loop back we have to subtract the
+                    # amount of time we already waited.
+                    if timeout is not None:
+                        timeout = end_time - time.time()
+                        if timeout < 0:
+                            return([], [], [])
+                else:
+                    # something else caused the select.error, so
+                    # this actually is an exception.
+                    raise
+
+
+class spawnu(SpawnBaseUnicode, spawn):
+    """Works like spawn, but accepts and returns unicode strings.
+
+    Extra parameters:
+
+    :param encoding: The encoding to use for communications (default: 'utf-8')
+    :param errors: How to handle encoding/decoding errors; one of 'strict'
+                   (the default), 'ignore', or 'replace', as described
+                   for :meth:`~bytes.decode` and :meth:`~str.encode`.
+    """
+    ptyprocess_class = ptyprocess.PtyProcessUnicode
+
+    def _send(self, s):
+        return os.write(self.child_fd, s.encode(self.encoding, self.errors))
+
+    def _log_control(self, byte):
+        s = byte.decode(self.encoding, 'replace')
+        self._log(s, 'send')
diff --git a/third_party/pexpect/pexpect/pxssh.py b/third_party/pexpect/pexpect/pxssh.py
new file mode 100644
index 0000000..71f56a0
--- /dev/null
+++ b/third_party/pexpect/pexpect/pxssh.py
@@ -0,0 +1,403 @@
+'''This class extends pexpect.spawn to specialize setting up SSH connections.
+This adds methods for login, logout, and expecting the shell prompt.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from pexpect import ExceptionPexpect, TIMEOUT, EOF, spawn
+import time
+import os
+
+__all__ = ['ExceptionPxssh', 'pxssh']
+
+# Exception classes used by this module.
+class ExceptionPxssh(ExceptionPexpect):
+    '''Raised for pxssh exceptions.
+    '''
+
+class pxssh (spawn):
+    '''This class extends pexpect.spawn to specialize setting up SSH
+    connections. This adds methods for login, logout, and expecting the shell
+    prompt. It does various tricky things to handle many situations in the SSH
+    login process. For example, if the session is your first login, then pxssh
+    automatically accepts the remote certificate; or if you have public key
+    authentication setup then pxssh won't wait for the password prompt.
+
+    pxssh uses the shell prompt to synchronize output from the remote host. In
+    order to make this more robust it sets the shell prompt to something more
+    unique than just $ or #. This should work on most Borne/Bash or Csh style
+    shells.
+
+    Example that runs a few commands on a remote server and prints the result::
+
+        import pxssh
+        import getpass
+        try:
+            s = pxssh.pxssh()
+            hostname = raw_input('hostname: ')
+            username = raw_input('username: ')
+            password = getpass.getpass('password: ')
+            s.login(hostname, username, password)
+            s.sendline('uptime')   # run a command
+            s.prompt()             # match the prompt
+            print(s.before)        # print everything before the prompt.
+            s.sendline('ls -l')
+            s.prompt()
+            print(s.before)
+            s.sendline('df')
+            s.prompt()
+            print(s.before)
+            s.logout()
+        except pxssh.ExceptionPxssh as e:
+            print("pxssh failed on login.")
+            print(e)
+
+    Example showing how to specify SSH options::
+
+        import pxssh
+        s = pxssh.pxssh(options={
+                            "StrictHostKeyChecking": "no",
+                            "UserKnownHostsFile": "/dev/null"})
+        ...
+
+    Note that if you have ssh-agent running while doing development with pxssh
+    then this can lead to a lot of confusion. Many X display managers (xdm,
+    gdm, kdm, etc.) will automatically start a GUI agent. You may see a GUI
+    dialog box popup asking for a password during development. You should turn
+    off any key agents during testing. The 'force_password' attribute will turn
+    off public key authentication. This will only work if the remote SSH server
+    is configured to allow password logins. Example of using 'force_password'
+    attribute::
+
+            s = pxssh.pxssh()
+            s.force_password = True
+            hostname = raw_input('hostname: ')
+            username = raw_input('username: ')
+            password = getpass.getpass('password: ')
+            s.login (hostname, username, password)
+    '''
+
+    def __init__ (self, timeout=30, maxread=2000, searchwindowsize=None,
+                    logfile=None, cwd=None, env=None, ignore_sighup=True, echo=True,
+                    options={}):
+
+        spawn.__init__(self, None, timeout=timeout, maxread=maxread, searchwindowsize=searchwindowsize, logfile=logfile, cwd=cwd, env=env, ignore_sighup=ignore_sighup, echo=echo)
+
+        self.name = '<pxssh>'
+
+        #SUBTLE HACK ALERT! Note that the command that SETS the prompt uses a
+        #slightly different string than the regular expression to match it. This
+        #is because when you set the prompt the command will echo back, but we
+        #don't want to match the echoed command. So if we make the set command
+        #slightly different than the regex we eliminate the problem. To make the
+        #set command different we add a backslash in front of $. The $ doesn't
+        #need to be escaped, but it doesn't hurt and serves to make the set
+        #prompt command different than the regex.
+
+        # used to match the command-line prompt
+        self.UNIQUE_PROMPT = "\[PEXPECT\][\$\#] "
+        self.PROMPT = self.UNIQUE_PROMPT
+
+        # used to set shell command-line prompt to UNIQUE_PROMPT.
+        self.PROMPT_SET_SH = "PS1='[PEXPECT]\$ '"
+        self.PROMPT_SET_CSH = "set prompt='[PEXPECT]\$ '"
+        self.SSH_OPTS = ("-o'RSAAuthentication=no'"
+                + " -o 'PubkeyAuthentication=no'")
+# Disabling host key checking, makes you vulnerable to MITM attacks.
+#                + " -o 'StrictHostKeyChecking=no'"
+#                + " -o 'UserKnownHostsFile /dev/null' ")
+        # Disabling X11 forwarding gets rid of the annoying SSH_ASKPASS from
+        # displaying a GUI password dialog. I have not figured out how to
+        # disable only SSH_ASKPASS without also disabling X11 forwarding.
+        # Unsetting SSH_ASKPASS on the remote side doesn't disable it! Annoying!
+        #self.SSH_OPTS = "-x -o'RSAAuthentication=no' -o 'PubkeyAuthentication=no'"
+        self.force_password = False
+
+        # User defined SSH options, eg,
+        # ssh.otions = dict(StrictHostKeyChecking="no",UserKnownHostsFile="/dev/null")
+        self.options = options
+
+    def levenshtein_distance(self, a, b):
+        '''This calculates the Levenshtein distance between a and b.
+        '''
+
+        n, m = len(a), len(b)
+        if n > m:
+            a,b = b,a
+            n,m = m,n
+        current = range(n+1)
+        for i in range(1,m+1):
+            previous, current = current, [i]+[0]*n
+            for j in range(1,n+1):
+                add, delete = previous[j]+1, current[j-1]+1
+                change = previous[j-1]
+                if a[j-1] != b[i-1]:
+                    change = change + 1
+                current[j] = min(add, delete, change)
+        return current[n]
+
+    def try_read_prompt(self, timeout_multiplier):
+        '''This facilitates using communication timeouts to perform
+        synchronization as quickly as possible, while supporting high latency
+        connections with a tunable worst case performance. Fast connections
+        should be read almost immediately. Worst case performance for this
+        method is timeout_multiplier * 3 seconds.
+        '''
+
+        # maximum time allowed to read the first response
+        first_char_timeout = timeout_multiplier * 0.5
+
+        # maximum time allowed between subsequent characters
+        inter_char_timeout = timeout_multiplier * 0.1
+
+        # maximum time for reading the entire prompt
+        total_timeout = timeout_multiplier * 3.0
+
+        prompt = b''
+        begin = time.time()
+        expired = 0.0
+        timeout = first_char_timeout
+
+        while expired < total_timeout:
+            try:
+                prompt += self.read_nonblocking(size=1, timeout=timeout)
+                expired = time.time() - begin # updated total time expired
+                timeout = inter_char_timeout
+            except TIMEOUT:
+                break
+
+        return prompt
+
+    def sync_original_prompt (self, sync_multiplier=1.0):
+        '''This attempts to find the prompt. Basically, press enter and record
+        the response; press enter again and record the response; if the two
+        responses are similar then assume we are at the original prompt.
+        This can be a slow function. Worst case with the default sync_multiplier
+        can take 12 seconds. Low latency connections are more likely to fail
+        with a low sync_multiplier. Best case sync time gets worse with a
+        high sync multiplier (500 ms with default). '''
+
+        # All of these timing pace values are magic.
+        # I came up with these based on what seemed reliable for
+        # connecting to a heavily loaded machine I have.
+        self.sendline()
+        time.sleep(0.1)
+
+        try:
+            # Clear the buffer before getting the prompt.
+            self.try_read_prompt(sync_multiplier)
+        except TIMEOUT:
+            pass
+
+        self.sendline()
+        x = self.try_read_prompt(sync_multiplier)
+
+        self.sendline()
+        a = self.try_read_prompt(sync_multiplier)
+
+        self.sendline()
+        b = self.try_read_prompt(sync_multiplier)
+
+        ld = self.levenshtein_distance(a,b)
+        len_a = len(a)
+        if len_a == 0:
+            return False
+        if float(ld)/len_a < 0.4:
+            return True
+        return False
+
+    ### TODO: This is getting messy and I'm pretty sure this isn't perfect.
+    ### TODO: I need to draw a flow chart for this.
+    def login (self, server, username, password='', terminal_type='ansi',
+                original_prompt=r"[#$]", login_timeout=10, port=None,
+                auto_prompt_reset=True, ssh_key=None, quiet=True,
+                sync_multiplier=1, check_local_ip=True):
+        '''This logs the user into the given server.
+
+        It uses
+        'original_prompt' to try to find the prompt right after login. When it
+        finds the prompt it immediately tries to reset the prompt to something
+        more easily matched. The default 'original_prompt' is very optimistic
+        and is easily fooled. It's more reliable to try to match the original
+        prompt as exactly as possible to prevent false matches by server
+        strings such as the "Message Of The Day". On many systems you can
+        disable the MOTD on the remote server by creating a zero-length file
+        called :file:`~/.hushlogin` on the remote server. If a prompt cannot be found
+        then this will not necessarily cause the login to fail. In the case of
+        a timeout when looking for the prompt we assume that the original
+        prompt was so weird that we could not match it, so we use a few tricks
+        to guess when we have reached the prompt. Then we hope for the best and
+        blindly try to reset the prompt to something more unique. If that fails
+        then login() raises an :class:`ExceptionPxssh` exception.
+
+        In some situations it is not possible or desirable to reset the
+        original prompt. In this case, pass ``auto_prompt_reset=False`` to
+        inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh
+        uses a unique prompt in the :meth:`prompt` method. If the original prompt is
+        not reset then this will disable the :meth:`prompt` method unless you
+        manually set the :attr:`PROMPT` attribute.
+        '''
+
+        ssh_options = ''.join([" -o '%s=%s'" % (o, v) for (o, v) in self.options.items()])
+        if quiet:
+            ssh_options = ssh_options + ' -q'
+        if not check_local_ip:
+            ssh_options = ssh_options + " -o'NoHostAuthenticationForLocalhost=yes'"
+        if self.force_password:
+            ssh_options = ssh_options + ' ' + self.SSH_OPTS
+        if port is not None:
+            ssh_options = ssh_options + ' -p %s'%(str(port))
+        if ssh_key is not None:
+            try:
+                os.path.isfile(ssh_key)
+            except:
+                raise ExceptionPxssh('private ssh key does not exist')
+            ssh_options = ssh_options + ' -i %s' % (ssh_key)
+        cmd = "ssh %s -l %s %s" % (ssh_options, username, server)
+
+        # This does not distinguish between a remote server 'password' prompt
+        # and a local ssh 'passphrase' prompt (for unlocking a private key).
+        spawn._spawn(self, cmd)
+        i = self.expect(["(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT, "(?i)connection closed by remote host"], timeout=login_timeout)
+
+        # First phase
+        if i==0:
+            # New certificate -- always accept it.
+            # This is what you get if SSH does not have the remote host's
+            # public key stored in the 'known_hosts' cache.
+            self.sendline("yes")
+            i = self.expect(["(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT])
+        if i==2: # password or passphrase
+            self.sendline(password)
+            i = self.expect(["(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT])
+        if i==4:
+            self.sendline(terminal_type)
+            i = self.expect(["(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT])
+
+        # Second phase
+        if i==0:
+            # This is weird. This should not happen twice in a row.
+            self.close()
+            raise ExceptionPxssh('Weird error. Got "are you sure" prompt twice.')
+        elif i==1: # can occur if you have a public key pair set to authenticate.
+            ### TODO: May NOT be OK if expect() got tricked and matched a false prompt.
+            pass
+        elif i==2: # password prompt again
+            # For incorrect passwords, some ssh servers will
+            # ask for the password again, others return 'denied' right away.
+            # If we get the password prompt again then this means
+            # we didn't get the password right the first time.
+            self.close()
+            raise ExceptionPxssh('password refused')
+        elif i==3: # permission denied -- password was bad.
+            self.close()
+            raise ExceptionPxssh('permission denied')
+        elif i==4: # terminal type again? WTF?
+            self.close()
+            raise ExceptionPxssh('Weird error. Got "terminal type" prompt twice.')
+        elif i==5: # Timeout
+            #This is tricky... I presume that we are at the command-line prompt.
+            #It may be that the shell prompt was so weird that we couldn't match
+            #it. Or it may be that we couldn't log in for some other reason. I
+            #can't be sure, but it's safe to guess that we did login because if
+            #I presume wrong and we are not logged in then this should be caught
+            #later when I try to set the shell prompt.
+            pass
+        elif i==6: # Connection closed by remote host
+            self.close()
+            raise ExceptionPxssh('connection closed')
+        else: # Unexpected
+            self.close()
+            raise ExceptionPxssh('unexpected login response')
+        if not self.sync_original_prompt(sync_multiplier):
+            self.close()
+            raise ExceptionPxssh('could not synchronize with original prompt')
+        # We appear to be in.
+        # set shell prompt to something unique.
+        if auto_prompt_reset:
+            if not self.set_unique_prompt():
+                self.close()
+                raise ExceptionPxssh('could not set shell prompt '
+                                     '(recieved: %r, expected: %r).' % (
+                                         self.before, self.PROMPT,))
+        return True
+
+    def logout (self):
+        '''Sends exit to the remote shell.
+
+        If there are stopped jobs then this automatically sends exit twice.
+        '''
+        self.sendline("exit")
+        index = self.expect([EOF, "(?i)there are stopped jobs"])
+        if index==1:
+            self.sendline("exit")
+            self.expect(EOF)
+        self.close()
+
+    def prompt(self, timeout=-1):
+        '''Match the next shell prompt.
+
+        This is little more than a short-cut to the :meth:`~pexpect.spawn.expect`
+        method. Note that if you called :meth:`login` with
+        ``auto_prompt_reset=False``, then before calling :meth:`prompt` you must
+        set the :attr:`PROMPT` attribute to a regex that it will use for
+        matching the prompt.
+
+        Calling :meth:`prompt` will erase the contents of the :attr:`before`
+        attribute even if no prompt is ever matched. If timeout is not given or
+        it is set to -1 then self.timeout is used.
+
+        :return: True if the shell prompt was matched, False if the timeout was
+                 reached.
+        '''
+
+        if timeout == -1:
+            timeout = self.timeout
+        i = self.expect([self.PROMPT, TIMEOUT], timeout=timeout)
+        if i==1:
+            return False
+        return True
+
+    def set_unique_prompt(self):
+        '''This sets the remote prompt to something more unique than ``#`` or ``$``.
+        This makes it easier for the :meth:`prompt` method to match the shell prompt
+        unambiguously. This method is called automatically by the :meth:`login`
+        method, but you may want to call it manually if you somehow reset the
+        shell prompt. For example, if you 'su' to a different user then you
+        will need to manually reset the prompt. This sends shell commands to
+        the remote host to set the prompt, so this assumes the remote host is
+        ready to receive commands.
+
+        Alternatively, you may use your own prompt pattern. In this case you
+        should call :meth:`login` with ``auto_prompt_reset=False``; then set the
+        :attr:`PROMPT` attribute to a regular expression. After that, the
+        :meth:`prompt` method will try to match your prompt pattern.
+        '''
+
+        self.sendline("unset PROMPT_COMMAND")
+        self.sendline(self.PROMPT_SET_SH) # sh-style
+        i = self.expect ([TIMEOUT, self.PROMPT], timeout=10)
+        if i == 0: # csh-style
+            self.sendline(self.PROMPT_SET_CSH)
+            i = self.expect([TIMEOUT, self.PROMPT], timeout=10)
+            if i == 0:
+                return False
+        return True
+
+# vi:ts=4:sw=4:expandtab:ft=python:
diff --git a/third_party/pexpect/pexpect/replwrap.py b/third_party/pexpect/pexpect/replwrap.py
new file mode 100644
index 0000000..7b0e823
--- /dev/null
+++ b/third_party/pexpect/pexpect/replwrap.py
@@ -0,0 +1,113 @@
+"""Generic wrapper for read-eval-print-loops, a.k.a. interactive shells
+"""
+import os.path
+import signal
+import sys
+import re
+
+import pexpect
+
+PY3 = (sys.version_info[0] >= 3)
+
+if PY3:
+    def u(s): return s
+else:
+    def u(s): return s.decode('utf-8')
+
+PEXPECT_PROMPT = u('[PEXPECT_PROMPT>')
+PEXPECT_CONTINUATION_PROMPT = u('[PEXPECT_PROMPT+')
+
+class REPLWrapper(object):
+    """Wrapper for a REPL.
+
+    :param cmd_or_spawn: This can either be an instance of :class:`pexpect.spawn`
+      in which a REPL has already been started, or a str command to start a new
+      REPL process.
+    :param str orig_prompt: The prompt to expect at first.
+    :param str prompt_change: A command to change the prompt to something more
+      unique. If this is ``None``, the prompt will not be changed. This will
+      be formatted with the new and continuation prompts as positional
+      parameters, so you can use ``{}`` style formatting to insert them into
+      the command.
+    :param str new_prompt: The more unique prompt to expect after the change.
+    :param str extra_init_cmd: Commands to do extra initialisation, such as
+      disabling pagers.
+    """
+    def __init__(self, cmd_or_spawn, orig_prompt, prompt_change,
+                 new_prompt=PEXPECT_PROMPT,
+                 continuation_prompt=PEXPECT_CONTINUATION_PROMPT,
+                 extra_init_cmd=None):
+        if isinstance(cmd_or_spawn, str):
+            self.child = pexpect.spawnu(cmd_or_spawn, echo=False)
+        else:
+            self.child = cmd_or_spawn
+        if self.child.echo:
+            # Existing spawn instance has echo enabled, disable it
+            # to prevent our input from being repeated to output.
+            self.child.setecho(False)
+            self.child.waitnoecho()
+
+        if prompt_change is None:
+            self.prompt = orig_prompt
+        else:
+            self.set_prompt(orig_prompt,
+                        prompt_change.format(new_prompt, continuation_prompt))
+            self.prompt = new_prompt
+        self.continuation_prompt = continuation_prompt
+
+        self._expect_prompt()
+
+        if extra_init_cmd is not None:
+            self.run_command(extra_init_cmd)
+
+    def set_prompt(self, orig_prompt, prompt_change):
+        self.child.expect(orig_prompt)
+        self.child.sendline(prompt_change)
+
+    def _expect_prompt(self, timeout=-1):
+        return self.child.expect_exact([self.prompt, self.continuation_prompt],
+                                       timeout=timeout)
+
+    def run_command(self, command, timeout=-1):
+        """Send a command to the REPL, wait for and return output.
+
+        :param str command: The command to send. Trailing newlines are not needed.
+          This should be a complete block of input that will trigger execution;
+          if a continuation prompt is found after sending input, :exc:`ValueError`
+          will be raised.
+        :param int timeout: How long to wait for the next prompt. -1 means the
+          default from the :class:`pexpect.spawn` object (default 30 seconds).
+          None means to wait indefinitely.
+        """
+        # Split up multiline commands and feed them in bit-by-bit
+        cmdlines = command.splitlines()
+        # splitlines ignores trailing newlines - add it back in manually
+        if command.endswith('\n'):
+            cmdlines.append('')
+        if not cmdlines:
+            raise ValueError("No command was given")
+
+        self.child.sendline(cmdlines[0])
+        for line in cmdlines[1:]:
+            self._expect_prompt(timeout=1)
+            self.child.sendline(line)
+
+        # Command was fully submitted, now wait for the next prompt
+        if self._expect_prompt(timeout=timeout) == 1:
+            # We got the continuation prompt - command was incomplete
+            self.child.kill(signal.SIGINT)
+            self._expect_prompt(timeout=1)
+            raise ValueError("Continuation prompt found - input was incomplete:\n"
+                             + command)
+        return self.child.before
+
+def python(command="python"):
+    """Start a Python shell and return a :class:`REPLWrapper` object."""
+    return REPLWrapper(command, u(">>> "), u("import sys; sys.ps1={0!r}; sys.ps2={1!r}"))
+
+def bash(command="bash"):
+    """Start a bash shell and return a :class:`REPLWrapper` object."""
+    bashrc = os.path.join(os.path.dirname(__file__), 'bashrc.sh')
+    child = pexpect.spawnu(command, ['--rcfile', bashrc], echo=False)
+    return REPLWrapper(child, u'\$', u("PS1='{0}' PS2='{1}' PROMPT_COMMAND=''"),
+                       extra_init_cmd="export PAGER=cat")
diff --git a/third_party/pexpect/pexpect/screen.py b/third_party/pexpect/pexpect/screen.py
new file mode 100644
index 0000000..efe9ee5
--- /dev/null
+++ b/third_party/pexpect/pexpect/screen.py
@@ -0,0 +1,424 @@
+'''This implements a virtual screen. This is used to support ANSI terminal
+emulation. The screen representation and state is implemented in this class.
+Most of the methods are inspired by ANSI screen control codes. The
+:class:`~pexpect.ANSI.ANSI` class extends this class to add parsing of ANSI
+escape codes.
+
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import codecs
+import copy
+import sys
+
+NUL = 0    # Fill character; ignored on input.
+ENQ = 5    # Transmit answerback message.
+BEL = 7    # Ring the bell.
+BS  = 8    # Move cursor left.
+HT  = 9    # Move cursor to next tab stop.
+LF = 10    # Line feed.
+VT = 11    # Same as LF.
+FF = 12    # Same as LF.
+CR = 13    # Move cursor to left margin or newline.
+SO = 14    # Invoke G1 character set.
+SI = 15    # Invoke G0 character set.
+XON = 17   # Resume transmission.
+XOFF = 19  # Halt transmission.
+CAN = 24   # Cancel escape sequence.
+SUB = 26   # Same as CAN.
+ESC = 27   # Introduce a control sequence.
+DEL = 127  # Fill character; ignored on input.
+SPACE = u' ' # Space or blank character.
+
+PY3 = (sys.version_info[0] >= 3)
+if PY3:
+    unicode = str
+
+def constrain (n, min, max):
+
+    '''This returns a number, n constrained to the min and max bounds. '''
+
+    if n < min:
+        return min
+    if n > max:
+        return max
+    return n
+
+class screen:
+    '''This object maintains the state of a virtual text screen as a
+    rectangluar array. This maintains a virtual cursor position and handles
+    scrolling as characters are added. This supports most of the methods needed
+    by an ANSI text screen. Row and column indexes are 1-based (not zero-based,
+    like arrays).
+
+    Characters are represented internally using unicode. Methods that accept
+    input characters, when passed 'bytes' (which in Python 2 is equivalent to
+    'str'), convert them from the encoding specified in the 'encoding'
+    parameter to the constructor. Methods that return screen contents return
+    unicode strings, with the exception of __str__() under Python 2. Passing
+    ``encoding=None`` limits the API to only accept unicode input, so passing
+    bytes in will raise :exc:`TypeError`.
+    '''
+    def __init__(self, r=24, c=80, encoding='latin-1', encoding_errors='replace'):
+        '''This initializes a blank screen of the given dimensions.'''
+
+        self.rows = r
+        self.cols = c
+        self.encoding = encoding
+        self.encoding_errors = encoding_errors
+        if encoding is not None:
+            self.decoder = codecs.getincrementaldecoder(encoding)(encoding_errors)            
+        else:
+            self.decoder = None
+        self.cur_r = 1
+        self.cur_c = 1
+        self.cur_saved_r = 1
+        self.cur_saved_c = 1
+        self.scroll_row_start = 1
+        self.scroll_row_end = self.rows
+        self.w = [ [SPACE] * self.cols for _ in range(self.rows)]
+
+    def _decode(self, s):
+        '''This converts from the external coding system (as passed to
+        the constructor) to the internal one (unicode). '''
+        if self.decoder is not None:
+            return self.decoder.decode(s)
+        else:
+            raise TypeError("This screen was constructed with encoding=None, "
+                            "so it does not handle bytes.")
+
+    def _unicode(self):
+        '''This returns a printable representation of the screen as a unicode
+        string (which, under Python 3.x, is the same as 'str'). The end of each
+        screen line is terminated by a newline.'''
+
+        return u'\n'.join ([ u''.join(c) for c in self.w ])
+
+    if PY3:
+        __str__ = _unicode
+    else:
+        __unicode__ = _unicode
+
+        def __str__(self):
+            '''This returns a printable representation of the screen. The end of
+            each screen line is terminated by a newline. '''
+            encoding = self.encoding or 'ascii'
+            return self._unicode().encode(encoding, 'replace')
+
+    def dump (self):
+        '''This returns a copy of the screen as a unicode string. This is similar to
+        __str__/__unicode__ except that lines are not terminated with line
+        feeds.'''
+
+        return u''.join ([ u''.join(c) for c in self.w ])
+
+    def pretty (self):
+        '''This returns a copy of the screen as a unicode string with an ASCII
+        text box around the screen border. This is similar to
+        __str__/__unicode__ except that it adds a box.'''
+
+        top_bot = u'+' + u'-'*self.cols + u'+\n'
+        return top_bot + u'\n'.join([u'|'+line+u'|' for line in unicode(self).split(u'\n')]) + u'\n' + top_bot
+
+    def fill (self, ch=SPACE):
+
+        if isinstance(ch, bytes):
+            ch = self._decode(ch)
+
+        self.fill_region (1,1,self.rows,self.cols, ch)
+
+    def fill_region (self, rs,cs, re,ce, ch=SPACE):
+
+        if isinstance(ch, bytes):
+            ch = self._decode(ch)
+
+        rs = constrain (rs, 1, self.rows)
+        re = constrain (re, 1, self.rows)
+        cs = constrain (cs, 1, self.cols)
+        ce = constrain (ce, 1, self.cols)
+        if rs > re:
+            rs, re = re, rs
+        if cs > ce:
+            cs, ce = ce, cs
+        for r in range (rs, re+1):
+            for c in range (cs, ce + 1):
+                self.put_abs (r,c,ch)
+
+    def cr (self):
+        '''This moves the cursor to the beginning (col 1) of the current row.
+        '''
+
+        self.cursor_home (self.cur_r, 1)
+
+    def lf (self):
+        '''This moves the cursor down with scrolling.
+        '''
+
+        old_r = self.cur_r
+        self.cursor_down()
+        if old_r == self.cur_r:
+            self.scroll_up ()
+            self.erase_line()
+
+    def crlf (self):
+        '''This advances the cursor with CRLF properties.
+        The cursor will line wrap and the screen may scroll.
+        '''
+
+        self.cr ()
+        self.lf ()
+
+    def newline (self):
+        '''This is an alias for crlf().
+        '''
+
+        self.crlf()
+
+    def put_abs (self, r, c, ch):
+        '''Screen array starts at 1 index.'''
+
+        r = constrain (r, 1, self.rows)
+        c = constrain (c, 1, self.cols)
+        if isinstance(ch, bytes):
+            ch = self._decode(ch)[0]
+        else:
+            ch = ch[0]
+        self.w[r-1][c-1] = ch
+
+    def put (self, ch):
+        '''This puts a characters at the current cursor position.
+        '''
+
+        if isinstance(ch, bytes):
+            ch = self._decode(ch)
+
+        self.put_abs (self.cur_r, self.cur_c, ch)
+
+    def insert_abs (self, r, c, ch):
+        '''This inserts a character at (r,c). Everything under
+        and to the right is shifted right one character.
+        The last character of the line is lost.
+        '''
+
+        if isinstance(ch, bytes):
+            ch = self._decode(ch)
+
+        r = constrain (r, 1, self.rows)
+        c = constrain (c, 1, self.cols)
+        for ci in range (self.cols, c, -1):
+            self.put_abs (r,ci, self.get_abs(r,ci-1))
+        self.put_abs (r,c,ch)
+
+    def insert (self, ch):
+
+        if isinstance(ch, bytes):
+            ch = self._decode(ch)
+
+        self.insert_abs (self.cur_r, self.cur_c, ch)
+
+    def get_abs (self, r, c):
+
+        r = constrain (r, 1, self.rows)
+        c = constrain (c, 1, self.cols)
+        return self.w[r-1][c-1]
+
+    def get (self):
+
+        self.get_abs (self.cur_r, self.cur_c)
+
+    def get_region (self, rs,cs, re,ce):
+        '''This returns a list of lines representing the region.
+        '''
+
+        rs = constrain (rs, 1, self.rows)
+        re = constrain (re, 1, self.rows)
+        cs = constrain (cs, 1, self.cols)
+        ce = constrain (ce, 1, self.cols)
+        if rs > re:
+            rs, re = re, rs
+        if cs > ce:
+            cs, ce = ce, cs
+        sc = []
+        for r in range (rs, re+1):
+            line = u''
+            for c in range (cs, ce + 1):
+                ch = self.get_abs (r,c)
+                line = line + ch
+            sc.append (line)
+        return sc
+
+    def cursor_constrain (self):
+        '''This keeps the cursor within the screen area.
+        '''
+
+        self.cur_r = constrain (self.cur_r, 1, self.rows)
+        self.cur_c = constrain (self.cur_c, 1, self.cols)
+
+    def cursor_home (self, r=1, c=1): # <ESC>[{ROW};{COLUMN}H
+
+        self.cur_r = r
+        self.cur_c = c
+        self.cursor_constrain ()
+
+    def cursor_back (self,count=1): # <ESC>[{COUNT}D (not confused with down)
+
+        self.cur_c = self.cur_c - count
+        self.cursor_constrain ()
+
+    def cursor_down (self,count=1): # <ESC>[{COUNT}B (not confused with back)
+
+        self.cur_r = self.cur_r + count
+        self.cursor_constrain ()
+
+    def cursor_forward (self,count=1): # <ESC>[{COUNT}C
+
+        self.cur_c = self.cur_c + count
+        self.cursor_constrain ()
+
+    def cursor_up (self,count=1): # <ESC>[{COUNT}A
+
+        self.cur_r = self.cur_r - count
+        self.cursor_constrain ()
+
+    def cursor_up_reverse (self): # <ESC> M   (called RI -- Reverse Index)
+
+        old_r = self.cur_r
+        self.cursor_up()
+        if old_r == self.cur_r:
+            self.scroll_up()
+
+    def cursor_force_position (self, r, c): # <ESC>[{ROW};{COLUMN}f
+        '''Identical to Cursor Home.'''
+
+        self.cursor_home (r, c)
+
+    def cursor_save (self): # <ESC>[s
+        '''Save current cursor position.'''
+
+        self.cursor_save_attrs()
+
+    def cursor_unsave (self): # <ESC>[u
+        '''Restores cursor position after a Save Cursor.'''
+
+        self.cursor_restore_attrs()
+
+    def cursor_save_attrs (self): # <ESC>7
+        '''Save current cursor position.'''
+
+        self.cur_saved_r = self.cur_r
+        self.cur_saved_c = self.cur_c
+
+    def cursor_restore_attrs (self): # <ESC>8
+        '''Restores cursor position after a Save Cursor.'''
+
+        self.cursor_home (self.cur_saved_r, self.cur_saved_c)
+
+    def scroll_constrain (self):
+        '''This keeps the scroll region within the screen region.'''
+
+        if self.scroll_row_start <= 0:
+            self.scroll_row_start = 1
+        if self.scroll_row_end > self.rows:
+            self.scroll_row_end = self.rows
+
+    def scroll_screen (self): # <ESC>[r
+        '''Enable scrolling for entire display.'''
+
+        self.scroll_row_start = 1
+        self.scroll_row_end = self.rows
+
+    def scroll_screen_rows (self, rs, re): # <ESC>[{start};{end}r
+        '''Enable scrolling from row {start} to row {end}.'''
+
+        self.scroll_row_start = rs
+        self.scroll_row_end = re
+        self.scroll_constrain()
+
+    def scroll_down (self): # <ESC>D
+        '''Scroll display down one line.'''
+
+        # Screen is indexed from 1, but arrays are indexed from 0.
+        s = self.scroll_row_start - 1
+        e = self.scroll_row_end - 1
+        self.w[s+1:e+1] = copy.deepcopy(self.w[s:e])
+
+    def scroll_up (self): # <ESC>M
+        '''Scroll display up one line.'''
+
+        # Screen is indexed from 1, but arrays are indexed from 0.
+        s = self.scroll_row_start - 1
+        e = self.scroll_row_end - 1
+        self.w[s:e] = copy.deepcopy(self.w[s+1:e+1])
+
+    def erase_end_of_line (self): # <ESC>[0K -or- <ESC>[K
+        '''Erases from the current cursor position to the end of the current
+        line.'''
+
+        self.fill_region (self.cur_r, self.cur_c, self.cur_r, self.cols)
+
+    def erase_start_of_line (self): # <ESC>[1K
+        '''Erases from the current cursor position to the start of the current
+        line.'''
+
+        self.fill_region (self.cur_r, 1, self.cur_r, self.cur_c)
+
+    def erase_line (self): # <ESC>[2K
+        '''Erases the entire current line.'''
+
+        self.fill_region (self.cur_r, 1, self.cur_r, self.cols)
+
+    def erase_down (self): # <ESC>[0J -or- <ESC>[J
+        '''Erases the screen from the current line down to the bottom of the
+        screen.'''
+
+        self.erase_end_of_line ()
+        self.fill_region (self.cur_r + 1, 1, self.rows, self.cols)
+
+    def erase_up (self): # <ESC>[1J
+        '''Erases the screen from the current line up to the top of the
+        screen.'''
+
+        self.erase_start_of_line ()
+        self.fill_region (self.cur_r-1, 1, 1, self.cols)
+
+    def erase_screen (self): # <ESC>[2J
+        '''Erases the screen with the background color.'''
+
+        self.fill ()
+
+    def set_tab (self): # <ESC>H
+        '''Sets a tab at the current position.'''
+
+        pass
+
+    def clear_tab (self): # <ESC>[g
+        '''Clears tab at the current position.'''
+
+        pass
+
+    def clear_all_tabs (self): # <ESC>[3g
+        '''Clears all tabs.'''
+
+        pass
+
+#        Insert line             Esc [ Pn L
+#        Delete line             Esc [ Pn M
+#        Delete character        Esc [ Pn P
+#        Scrolling region        Esc [ Pn(top);Pn(bot) r
+
diff --git a/third_party/pexpect/pexpect/spawnbase.py b/third_party/pexpect/pexpect/spawnbase.py
new file mode 100644
index 0000000..d79c5c0
--- /dev/null
+++ b/third_party/pexpect/pexpect/spawnbase.py
@@ -0,0 +1,484 @@
+import codecs
+import os
+import sys
+import re
+import errno
+from .exceptions import ExceptionPexpect, EOF, TIMEOUT
+from .expect import Expecter, searcher_string, searcher_re
+
+PY3 = (sys.version_info[0] >= 3)
+
+class SpawnBase(object):
+    """A base class providing the backwards-compatible spawn API for Pexpect.
+
+    This should not be instantiated directly: use :class:`pexpect.spawn` or :class:`pexpect.fdpexpect.fdspawn`."""
+    string_type = bytes
+    if PY3:
+        allowed_string_types = (bytes, str)
+        linesep = os.linesep.encode('ascii')
+        crlf = '\r\n'.encode('ascii')
+
+        @staticmethod
+        def write_to_stdout(b):
+            try:
+                return sys.stdout.buffer.write(b)
+            except AttributeError:
+                # If stdout has been replaced, it may not have .buffer
+                return sys.stdout.write(b.decode('ascii', 'replace'))
+    else:
+        allowed_string_types = (basestring,)  # analysis:ignore
+        linesep = os.linesep
+        crlf = '\r\n'
+        write_to_stdout = sys.stdout.write
+
+    encoding = None
+    pid = None
+    flag_eof = False
+
+    def __init__(self, timeout=30, maxread=2000, searchwindowsize=None, logfile=None):
+        self.stdin = sys.stdin
+        self.stdout = sys.stdout
+        self.stderr = sys.stderr
+
+        self.searcher = None
+        self.ignorecase = False
+        self.before = None
+        self.after = None
+        self.match = None
+        self.match_index = None
+        self.terminated = True
+        self.exitstatus = None
+        self.signalstatus = None
+        # status returned by os.waitpid
+        self.status = None
+        # the child file descriptor is initially closed
+        self.child_fd = -1
+        self.timeout = timeout
+        self.delimiter = EOF
+        self.logfile = logfile
+        # input from child (read_nonblocking)
+        self.logfile_read = None
+        # output to send (send, sendline)
+        self.logfile_send = None
+        # max bytes to read at one time into buffer
+        self.maxread = maxread
+        # This is the read buffer. See maxread.
+        self.buffer = self.string_type()
+        # Data before searchwindowsize point is preserved, but not searched.
+        self.searchwindowsize = searchwindowsize
+        # Delay used before sending data to child. Time in seconds.
+        # Most Linux machines don't like this to be below 0.03 (30 ms).
+        self.delaybeforesend = 0.05
+        # Used by close() to give kernel time to update process status.
+        # Time in seconds.
+        self.delayafterclose = 0.1
+        # Used by terminate() to give kernel time to update process status.
+        # Time in seconds.
+        self.delayafterterminate = 0.1
+        self.softspace = False
+        self.name = '<' + repr(self) + '>'
+        self.closed = True
+
+    def _log(self, s, direction):
+        if self.logfile is not None:
+            self.logfile.write(s)
+            self.logfile.flush()
+        second_log = self.logfile_send if (direction=='send') else self.logfile_read
+        if second_log is not None:
+            second_log.write(s)
+            second_log.flush()
+
+    @staticmethod
+    def _coerce_expect_string(s):
+        if not isinstance(s, bytes):
+            return s.encode('ascii')
+        return s
+
+    @staticmethod
+    def _coerce_send_string(s):
+        if not isinstance(s, bytes):
+            return s.encode('utf-8')
+        return s
+
+    @staticmethod
+    def _coerce_read_string(s):
+        return s
+
+    def read_nonblocking(self, size=1, timeout=None):
+        """This reads data from the file descriptor.
+
+        This is a simple implementation suitable for a regular file. Subclasses using ptys or pipes should override it.
+
+        The timeout parameter is ignored.
+        """
+
+        try:
+            s = os.read(self.child_fd, size)
+        except OSError as err:
+            if err.args[0] == errno.EIO:
+                # Linux-style EOF
+                self.flag_eof = True
+                raise EOF('End Of File (EOF). Exception style platform.')
+            raise
+        if s == b'':
+            # BSD-style EOF
+            self.flag_eof = True
+            raise EOF('End Of File (EOF). Empty string style platform.')
+
+        s = self._coerce_read_string(s)
+        self._log(s, 'read')
+        return s
+
+    def _pattern_type_err(self, pattern):
+        raise TypeError('got {badtype} ({badobj!r}) as pattern, must be one'
+                        ' of: {goodtypes}, pexpect.EOF, pexpect.TIMEOUT'\
+                        .format(badtype=type(pattern),
+                                badobj=pattern,
+                                goodtypes=', '.join([str(ast)\
+                                    for ast in self.allowed_string_types])
+                                )
+                        )
+
+    def compile_pattern_list(self, patterns):
+        '''This compiles a pattern-string or a list of pattern-strings.
+        Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or a list of
+        those. Patterns may also be None which results in an empty list (you
+        might do this if waiting for an EOF or TIMEOUT condition without
+        expecting any pattern).
+
+        This is used by expect() when calling expect_list(). Thus expect() is
+        nothing more than::
+
+             cpl = self.compile_pattern_list(pl)
+             return self.expect_list(cpl, timeout)
+
+        If you are using expect() within a loop it may be more
+        efficient to compile the patterns first and then call expect_list().
+        This avoid calls in a loop to compile_pattern_list()::
+
+             cpl = self.compile_pattern_list(my_pattern)
+             while some_condition:
+                ...
+                i = self.expect_list(cpl, timeout)
+                ...
+        '''
+
+        if patterns is None:
+            return []
+        if not isinstance(patterns, list):
+            patterns = [patterns]
+
+        # Allow dot to match \n
+        compile_flags = re.DOTALL
+        if self.ignorecase:
+            compile_flags = compile_flags | re.IGNORECASE
+        compiled_pattern_list = []
+        for idx, p in enumerate(patterns):
+            if isinstance(p, self.allowed_string_types):
+                p = self._coerce_expect_string(p)
+                compiled_pattern_list.append(re.compile(p, compile_flags))
+            elif p is EOF:
+                compiled_pattern_list.append(EOF)
+            elif p is TIMEOUT:
+                compiled_pattern_list.append(TIMEOUT)
+            elif isinstance(p, type(re.compile(''))):
+                compiled_pattern_list.append(p)
+            else:
+                self._pattern_type_err(p)
+        return compiled_pattern_list
+
+    def expect(self, pattern, timeout=-1, searchwindowsize=-1, async=False):
+        '''This seeks through the stream until a pattern is matched. The
+        pattern is overloaded and may take several types. The pattern can be a
+        StringType, EOF, a compiled re, or a list of any of those types.
+        Strings will be compiled to re types. This returns the index into the
+        pattern list. If the pattern was not a list this returns index 0 on a
+        successful match. This may raise exceptions for EOF or TIMEOUT. To
+        avoid the EOF or TIMEOUT exceptions add EOF or TIMEOUT to the pattern
+        list. That will cause expect to match an EOF or TIMEOUT condition
+        instead of raising an exception.
+
+        If you pass a list of patterns and more than one matches, the first
+        match in the stream is chosen. If more than one pattern matches at that
+        point, the leftmost in the pattern list is chosen. For example::
+
+            # the input is 'foobar'
+            index = p.expect(['bar', 'foo', 'foobar'])
+            # returns 1('foo') even though 'foobar' is a "better" match
+
+        Please note, however, that buffering can affect this behavior, since
+        input arrives in unpredictable chunks. For example::
+
+            # the input is 'foobar'
+            index = p.expect(['foobar', 'foo'])
+            # returns 0('foobar') if all input is available at once,
+            # but returs 1('foo') if parts of the final 'bar' arrive late
+
+        After a match is found the instance attributes 'before', 'after' and
+        'match' will be set. You can see all the data read before the match in
+        'before'. You can see the data that was matched in 'after'. The
+        re.MatchObject used in the re match will be in 'match'. If an error
+        occurred then 'before' will be set to all the data read so far and
+        'after' and 'match' will be None.
+
+        If timeout is -1 then timeout will be set to the self.timeout value.
+
+        A list entry may be EOF or TIMEOUT instead of a string. This will
+        catch these exceptions and return the index of the list entry instead
+        of raising the exception. The attribute 'after' will be set to the
+        exception type. The attribute 'match' will be None. This allows you to
+        write code like this::
+
+                index = p.expect(['good', 'bad', pexpect.EOF, pexpect.TIMEOUT])
+                if index == 0:
+                    do_something()
+                elif index == 1:
+                    do_something_else()
+                elif index == 2:
+                    do_some_other_thing()
+                elif index == 3:
+                    do_something_completely_different()
+
+        instead of code like this::
+
+                try:
+                    index = p.expect(['good', 'bad'])
+                    if index == 0:
+                        do_something()
+                    elif index == 1:
+                        do_something_else()
+                except EOF:
+                    do_some_other_thing()
+                except TIMEOUT:
+                    do_something_completely_different()
+
+        These two forms are equivalent. It all depends on what you want. You
+        can also just expect the EOF if you are waiting for all output of a
+        child to finish. For example::
+
+                p = pexpect.spawn('/bin/ls')
+                p.expect(pexpect.EOF)
+                print p.before
+
+        If you are trying to optimize for speed then see expect_list().
+
+        On Python 3.4, or Python 3.3 with asyncio installed, passing
+        ``async=True``  will make this return an :mod:`asyncio` coroutine,
+        which you can yield from to get the same result that this method would
+        normally give directly. So, inside a coroutine, you can replace this code::
+
+            index = p.expect(patterns)
+
+        With this non-blocking form::
+
+            index = yield from p.expect(patterns, async=True)
+        '''
+
+        compiled_pattern_list = self.compile_pattern_list(pattern)
+        return self.expect_list(compiled_pattern_list,
+                timeout, searchwindowsize, async)
+
+    def expect_list(self, pattern_list, timeout=-1, searchwindowsize=-1,
+                    async=False):
+        '''This takes a list of compiled regular expressions and returns the
+        index into the pattern_list that matched the child output. The list may
+        also contain EOF or TIMEOUT(which are not compiled regular
+        expressions). This method is similar to the expect() method except that
+        expect_list() does not recompile the pattern list on every call. This
+        may help if you are trying to optimize for speed, otherwise just use
+        the expect() method.  This is called by expect(). If timeout==-1 then
+        the self.timeout value is used. If searchwindowsize==-1 then the
+        self.searchwindowsize value is used.
+
+        Like :meth:`expect`, passing ``async=True`` will make this return an
+        asyncio coroutine.
+        '''
+        if timeout == -1:
+            timeout = self.timeout
+
+        exp = Expecter(self, searcher_re(pattern_list), searchwindowsize)
+        if async:
+            from .async import expect_async
+            return expect_async(exp, timeout)
+        else:
+            return exp.expect_loop(timeout)
+
+    def expect_exact(self, pattern_list, timeout=-1, searchwindowsize=-1,
+                     async=False):
+
+        '''This is similar to expect(), but uses plain string matching instead
+        of compiled regular expressions in 'pattern_list'. The 'pattern_list'
+        may be a string; a list or other sequence of strings; or TIMEOUT and
+        EOF.
+
+        This call might be faster than expect() for two reasons: string
+        searching is faster than RE matching and it is possible to limit the
+        search to just the end of the input buffer.
+
+        This method is also useful when you don't want to have to worry about
+        escaping regular expression characters that you want to match.
+
+        Like :meth:`expect`, passing ``async=True`` will make this return an
+        asyncio coroutine.
+        '''
+        if timeout == -1:
+            timeout = self.timeout
+
+        if (isinstance(pattern_list, self.allowed_string_types) or
+                pattern_list in (TIMEOUT, EOF)):
+            pattern_list = [pattern_list]
+
+        def prepare_pattern(pattern):
+            if pattern in (TIMEOUT, EOF):
+                return pattern
+            if isinstance(pattern, self.allowed_string_types):
+                return self._coerce_expect_string(pattern)
+            self._pattern_type_err(pattern)
+
+        try:
+            pattern_list = iter(pattern_list)
+        except TypeError:
+            self._pattern_type_err(pattern_list)
+        pattern_list = [prepare_pattern(p) for p in pattern_list]
+
+        exp = Expecter(self, searcher_string(pattern_list), searchwindowsize)
+        if async:
+            from .async import expect_async
+            return expect_async(exp, timeout)
+        else:
+            return exp.expect_loop(timeout)
+
+    def expect_loop(self, searcher, timeout=-1, searchwindowsize=-1):
+        '''This is the common loop used inside expect. The 'searcher' should be
+        an instance of searcher_re or searcher_string, which describes how and
+        what to search for in the input.
+
+        See expect() for other arguments, return value and exceptions. '''
+
+        exp = Expecter(self, searcher, searchwindowsize)
+        return exp.expect_loop(timeout)
+
+    def read(self, size=-1):
+        '''This reads at most "size" bytes from the file (less if the read hits
+        EOF before obtaining size bytes). If the size argument is negative or
+        omitted, read all data until EOF is reached. The bytes are returned as
+        a string object. An empty string is returned when EOF is encountered
+        immediately. '''
+
+        if size == 0:
+            return self.string_type()
+        if size < 0:
+            # delimiter default is EOF
+            self.expect(self.delimiter)
+            return self.before
+
+        # I could have done this more directly by not using expect(), but
+        # I deliberately decided to couple read() to expect() so that
+        # I would catch any bugs early and ensure consistant behavior.
+        # It's a little less efficient, but there is less for me to
+        # worry about if I have to later modify read() or expect().
+        # Note, it's OK if size==-1 in the regex. That just means it
+        # will never match anything in which case we stop only on EOF.
+        cre = re.compile(self._coerce_expect_string('.{%d}' % size), re.DOTALL)
+        # delimiter default is EOF
+        index = self.expect([cre, self.delimiter])
+        if index == 0:
+            ### FIXME self.before should be ''. Should I assert this?
+            return self.after
+        return self.before
+
+    def readline(self, size=-1):
+        '''This reads and returns one entire line. The newline at the end of
+        line is returned as part of the string, unless the file ends without a
+        newline. An empty string is returned if EOF is encountered immediately.
+        This looks for a newline as a CR/LF pair (\\r\\n) even on UNIX because
+        this is what the pseudotty device returns. So contrary to what you may
+        expect you will receive newlines as \\r\\n.
+
+        If the size argument is 0 then an empty string is returned. In all
+        other cases the size argument is ignored, which is not standard
+        behavior for a file-like object. '''
+
+        if size == 0:
+            return self.string_type()
+        # delimiter default is EOF
+        index = self.expect([self.crlf, self.delimiter])
+        if index == 0:
+            return self.before + self.crlf
+        else:
+            return self.before
+
+    def __iter__(self):
+        '''This is to support iterators over a file-like object.
+        '''
+        return iter(self.readline, self.string_type())
+
+    def readlines(self, sizehint=-1):
+        '''This reads until EOF using readline() and returns a list containing
+        the lines thus read. The optional 'sizehint' argument is ignored.
+        Remember, because this reads until EOF that means the child
+        process should have closed its stdout. If you run this method on
+        a child that is still running with its stdout open then this
+        method will block until it timesout.'''
+
+        lines = []
+        while True:
+            line = self.readline()
+            if not line:
+                break
+            lines.append(line)
+        return lines
+
+    def fileno(self):
+        '''Expose file descriptor for a file-like interface
+        '''
+        return self.child_fd
+
+    def flush(self):
+        '''This does nothing. It is here to support the interface for a
+        File-like object. '''
+        pass
+
+    def isatty(self):
+        """Overridden in subclass using tty"""
+        return False
+
+    # For 'with spawn(...) as child:'
+    def __enter__(self):
+        return self
+    
+    def __exit__(self, etype, evalue, tb):
+        # We rely on subclasses to implement close(). If they don't, it's not
+        # clear what a context manager should do.
+        self.close()
+
+class SpawnBaseUnicode(SpawnBase):
+    if PY3:
+        string_type = str
+        allowed_string_types = (str, )
+        linesep = os.linesep
+        crlf = '\r\n'
+    else:
+        string_type = unicode
+        allowed_string_types = (unicode, )
+        linesep = os.linesep.decode('ascii')
+        crlf = '\r\n'.decode('ascii')
+    # This can handle unicode in both Python 2 and 3
+    write_to_stdout = sys.stdout.write
+
+    def __init__(self, *args, **kwargs):
+        self.encoding = kwargs.pop('encoding', 'utf-8')
+        self.errors = kwargs.pop('errors', 'strict')
+        self._decoder = codecs.getincrementaldecoder(self.encoding)(errors=self.errors)
+        super(SpawnBaseUnicode, self).__init__(*args, **kwargs)
+
+    @staticmethod
+    def _coerce_expect_string(s):
+        return s
+
+    @staticmethod
+    def _coerce_send_string(s):
+        return s
+
+    def _coerce_read_string(self, s):
+        return self._decoder.decode(s, final=False)
\ No newline at end of file
diff --git a/third_party/pexpect/pexpect/utils.py b/third_party/pexpect/pexpect/utils.py
new file mode 100644
index 0000000..737f0ed
--- /dev/null
+++ b/third_party/pexpect/pexpect/utils.py
@@ -0,0 +1,112 @@
+import os
+import sys
+import stat
+
+
+def is_executable_file(path):
+    """Checks that path is an executable regular file, or a symlink towards one.
+
+    This is roughly ``os.path isfile(path) and os.access(path, os.X_OK)``.
+    """
+    # follow symlinks,
+    fpath = os.path.realpath(path)
+
+    if not os.path.isfile(fpath):
+        # non-files (directories, fifo, etc.)
+        return False
+
+    mode = os.stat(fpath).st_mode
+
+    if (sys.platform.startswith('sunos')
+            and os.getuid() == 0):
+        # When root on Solaris, os.X_OK is True for *all* files, irregardless
+        # of their executability -- instead, any permission bit of any user,
+        # group, or other is fine enough.
+        #
+        # (This may be true for other "Unix98" OS's such as HP-UX and AIX)
+        return bool(mode & (stat.S_IXUSR |
+                            stat.S_IXGRP |
+                            stat.S_IXOTH))
+
+    return os.access(fpath, os.X_OK)
+
+
+def which(filename):
+    '''This takes a given filename; tries to find it in the environment path;
+    then checks if it is executable. This returns the full path to the filename
+    if found and executable. Otherwise this returns None.'''
+
+    # Special case where filename contains an explicit path.
+    if os.path.dirname(filename) != '' and is_executable_file(filename):
+        return filename
+    if 'PATH' not in os.environ or os.environ['PATH'] == '':
+        p = os.defpath
+    else:
+        p = os.environ['PATH']
+    pathlist = p.split(os.pathsep)
+    for path in pathlist:
+        ff = os.path.join(path, filename)
+        if is_executable_file(ff):
+            return ff
+    return None
+
+
+def split_command_line(command_line):
+
+    '''This splits a command line into a list of arguments. It splits arguments
+    on spaces, but handles embedded quotes, doublequotes, and escaped
+    characters. It's impossible to do this with a regular expression, so I
+    wrote a little state machine to parse the command line. '''
+
+    arg_list = []
+    arg = ''
+
+    # Constants to name the states we can be in.
+    state_basic = 0
+    state_esc = 1
+    state_singlequote = 2
+    state_doublequote = 3
+    # The state when consuming whitespace between commands.
+    state_whitespace = 4
+    state = state_basic
+
+    for c in command_line:
+        if state == state_basic or state == state_whitespace:
+            if c == '\\':
+                # Escape the next character
+                state = state_esc
+            elif c == r"'":
+                # Handle single quote
+                state = state_singlequote
+            elif c == r'"':
+                # Handle double quote
+                state = state_doublequote
+            elif c.isspace():
+                # Add arg to arg_list if we aren't in the middle of whitespace.
+                if state == state_whitespace:
+                    # Do nothing.
+                    None
+                else:
+                    arg_list.append(arg)
+                    arg = ''
+                    state = state_whitespace
+            else:
+                arg = arg + c
+                state = state_basic
+        elif state == state_esc:
+            arg = arg + c
+            state = state_basic
+        elif state == state_singlequote:
+            if c == r"'":
+                state = state_basic
+            else:
+                arg = arg + c
+        elif state == state_doublequote:
+            if c == r'"':
+                state = state_basic
+            else:
+                arg = arg + c
+
+    if arg != '':
+        arg_list.append(arg)
+    return arg_list
diff --git a/third_party/pexpect/pxssh.py b/third_party/pexpect/pxssh.py
new file mode 100644
index 0000000..1849769
--- /dev/null
+++ b/third_party/pexpect/pxssh.py
@@ -0,0 +1,7 @@
+import warnings
+
+warnings.warn("This module has been moved to pexpect.pxssh, please update imports.",
+                ImportWarning)
+del warnings
+
+from pexpect.pxssh import *  # analysis:ignore
\ No newline at end of file
diff --git a/third_party/pexpect/screen.py b/third_party/pexpect/screen.py
new file mode 100644
index 0000000..0358c41
--- /dev/null
+++ b/third_party/pexpect/screen.py
@@ -0,0 +1,7 @@
+import warnings
+
+warnings.warn("This module has been moved to pexpect.screen, please update imports.",
+                ImportWarning)
+del warnings
+
+from pexpect.screen import *  # analysis:ignore
\ No newline at end of file
diff --git a/third_party/pexpect/setup.cfg b/third_party/pexpect/setup.cfg
new file mode 100644
index 0000000..ae62686
--- /dev/null
+++ b/third_party/pexpect/setup.cfg
@@ -0,0 +1,2 @@
+[pytest]
+norecursedirs = .git
diff --git a/third_party/pexpect/setup.py b/third_party/pexpect/setup.py
new file mode 100644
index 0000000..126749a
--- /dev/null
+++ b/third_party/pexpect/setup.py
@@ -0,0 +1,65 @@
+from distutils.core import setup
+import os
+import re
+
+with open(os.path.join(os.path.dirname(__file__), 'pexpect', '__init__.py'), 'r') as f:
+    for line in f:
+        version_match = re.search(r"__version__ = ['\"]([^'\"]*)['\"]", line)
+        if version_match:
+            version = version_match.group(1)
+            break
+    else:
+        raise Exception("couldn't find version number")
+
+long_description = """
+Pexpect is a pure Python module for spawning child applications; controlling
+them; and responding to expected patterns in their output. Pexpect works like
+Don Libes' Expect. Pexpect allows your script to spawn a child application and
+control it as if a human were typing commands.
+
+Pexpect can be used for automating interactive applications such as ssh, ftp,
+passwd, telnet, etc. It can be used to a automate setup scripts for duplicating
+software package installations on different servers. It can be used for
+automated software testing. Pexpect is in the spirit of Don Libes' Expect, but
+Pexpect is pure Python. Unlike other Expect-like modules for Python, Pexpect
+does not require TCL or Expect nor does it require C extensions to be compiled.
+It should work on any platform that supports the standard Python pty module.
+The Pexpect interface was designed to be easy to use.
+"""
+
+setup (name='pexpect',
+    version=version,
+    py_modules=['pxssh', 'fdpexpect', 'FSM', 'screen', 'ANSI'],
+    packages=['pexpect'],
+    description='Pexpect allows easy control of interactive console applications.',
+    long_description=long_description,
+    author='Noah Spurrier; Thomas Kluyver; Jeff Quast',
+    author_email='noah at noah.org; thomas at kluyver.me.uk; contact at jeffquast.com',
+    url='http://pexpect.readthedocs.org/',
+    license='ISC license',
+    platforms='UNIX',
+    classifiers = [
+        'Development Status :: 5 - Production/Stable',
+        'Environment :: Console',
+        'Intended Audience :: Developers',
+        'Intended Audience :: System Administrators',
+        'License :: OSI Approved :: ISC License (ISCL)',
+        'Operating System :: POSIX',
+        'Operating System :: MacOS :: MacOS X',
+        'Programming Language :: Python',
+        'Programming Language :: Python :: 2.6',
+        'Programming Language :: Python :: 2.7',
+        'Programming Language :: Python :: 3',
+        'Topic :: Software Development',
+        'Topic :: Software Development :: Libraries :: Python Modules',
+        'Topic :: Software Development :: Quality Assurance',
+        'Topic :: Software Development :: Testing',
+        'Topic :: System',
+        'Topic :: System :: Archiving :: Packaging',
+        'Topic :: System :: Installation/Setup',
+        'Topic :: System :: Shells',
+        'Topic :: System :: Software Distribution',
+        'Topic :: Terminals',
+    ],
+    install_requires=['ptyprocess'],
+)
diff --git a/third_party/pexpect/tests/PexpectTestCase.py b/third_party/pexpect/tests/PexpectTestCase.py
new file mode 100644
index 0000000..307437e
--- /dev/null
+++ b/third_party/pexpect/tests/PexpectTestCase.py
@@ -0,0 +1,108 @@
+
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from __future__ import print_function
+
+import contextlib
+import unittest
+import signal
+import sys
+import os
+
+
+class PexpectTestCase(unittest.TestCase):
+    def setUp(self):
+        self.PYTHONBIN = sys.executable
+        self.original_path = os.getcwd()
+        tests_dir = os.path.dirname(__file__)
+        self.project_dir = project_dir = os.path.dirname(tests_dir)
+
+        # all tests are executed in this folder; there are many auxiliary
+        # programs in this folder executed by spawn().
+        os.chdir(tests_dir)
+
+        # If the pexpect raises an exception after fork(), but before
+        # exec(), our test runner *also* forks.  We prevent this by
+        # storing our pid and asserting equality on tearDown.
+        self.pid = os.getpid()
+
+        coverage_rc = os.path.join(project_dir, '.coveragerc')
+        os.environ['COVERAGE_PROCESS_START'] = coverage_rc
+        os.environ['COVERAGE_FILE'] = os.path.join(project_dir, '.coverage')
+        print('\n', self.id(), end=' ')
+        sys.stdout.flush()
+
+        # some build agents will ignore SIGHUP and SIGINT, which python
+        # inherits.  This causes some of the tests related to terminate()
+        # to fail.  We set them to the default handlers that they should
+        # be, and restore them back to their SIG_IGN value on tearDown.
+        #
+        # I'm not entirely convinced they need to be restored, only our
+        # test runner is affected.
+        self.restore_ignored_signals = [
+            value for value in (signal.SIGHUP, signal.SIGINT,)
+            if signal.getsignal(value) == signal.SIG_IGN]
+        if signal.SIGHUP in self.restore_ignored_signals:
+            # sighup should be set to default handler
+            signal.signal(signal.SIGHUP, signal.SIG_DFL)
+        if signal.SIGINT in self.restore_ignored_signals:
+            # SIGINT should be set to signal.default_int_handler
+            signal.signal(signal.SIGINT, signal.default_int_handler)
+        unittest.TestCase.setUp(self)
+
+    def tearDown(self):
+        # restore original working folder
+        os.chdir(self.original_path)
+
+        if self.pid != os.getpid():
+            # The build server pattern-matches phrase 'Test runner has forked!'
+            print("Test runner has forked! This means a child process raised "
+                  "an exception before exec() in a test case, the error is "
+                  "more than likely found above this line in stderr.",
+                  file=sys.stderr)
+            exit(1)
+
+        # restore signal handlers
+        for signal_value in self.restore_ignored_signals:
+            signal.signal(signal_value, signal.SIG_IGN)
+
+    if sys.version_info < (2, 7):
+        # We want to use these methods, which are new/improved in 2.7, but
+        # we are still supporting 2.6 for the moment. This section can be
+        # removed when we drop Python 2.6 support.
+        @contextlib.contextmanager
+        def assertRaises(self, excClass):
+            try:
+                yield
+            except Exception as e:
+                assert isinstance(e, excClass)
+            else:
+                raise AssertionError("%s was not raised" % excClass)
+
+        @contextlib.contextmanager
+        def assertRaisesRegexp(self, excClass, pattern):
+            import re
+            try:
+                yield
+            except Exception as e:
+                assert isinstance(e, excClass)
+                assert re.match(pattern, str(e))
+            else:
+                raise AssertionError("%s was not raised" % excClass)
diff --git a/third_party/pexpect/tests/README b/third_party/pexpect/tests/README
new file mode 100644
index 0000000..ef5b613
--- /dev/null
+++ b/third_party/pexpect/tests/README
@@ -0,0 +1,8 @@
+
+The best way to run these tests is from the directory above this one. Run:
+
+    py.test
+
+To run a specific test file:
+
+    py.test tests/test_constructor.py
diff --git a/third_party/pexpect/tests/TESTDATA.txt b/third_party/pexpect/tests/TESTDATA.txt
new file mode 100644
index 0000000..adb9c01
--- /dev/null
+++ b/third_party/pexpect/tests/TESTDATA.txt
@@ -0,0 +1,8 @@
+This is test data.
+    One
+    2
+    THREE
+    IV
+    .....
+    110
+This is the end of test data: END
diff --git a/third_party/pexpect/tests/__init__.py b/third_party/pexpect/tests/__init__.py
new file mode 100755
index 0000000..f717d82
--- /dev/null
+++ b/third_party/pexpect/tests/__init__.py
@@ -0,0 +1,25 @@
+
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+# __init__.py
+# The mere presence of this file makes the dir a package.
+pass
+
diff --git a/third_party/pexpect/tests/adhoc.py b/third_party/pexpect/tests/adhoc.py
new file mode 100755
index 0000000..0813d34
--- /dev/null
+++ b/third_party/pexpect/tests/adhoc.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from  __future__ import print_function
+
+import pexpect
+import time
+
+p = pexpect.spawn ('./a.out')
+print(p.exitstatus)
+p.expect (pexpect.EOF)
+print(p.before)
+time.sleep(1)
+print('exitstatus:', p.exitstatus)
+print('isalive',p.isalive())
+print('exitstatus',p.exitstatus)
+print('isalive',p.isalive())
+print('exitstatus',p.exitstatus)
+
diff --git a/third_party/pexpect/tests/alarm_die.py b/third_party/pexpect/tests/alarm_die.py
new file mode 100644
index 0000000..a1519ab
--- /dev/null
+++ b/third_party/pexpect/tests/alarm_die.py
@@ -0,0 +1,5 @@
+import signal, time
+
+signal.alarm(1) # Schedule SIGALRM in 1s
+
+time.sleep(6)
\ No newline at end of file
diff --git a/third_party/pexpect/tests/bambi.vt b/third_party/pexpect/tests/bambi.vt
new file mode 100644
index 0000000..853f099
--- /dev/null
+++ b/third_party/pexpect/tests/bambi.vt
@@ -0,0 +1,417 @@
+[?25l
+
+
+                         The
+                         The Adventures
+                         The Adventures of
+                         The Adventures of BAMBI
+                                                            
+                     Number
+                     Number One :
+                     Number One : BAMBI
+                     Number One : BAMBI versus
+                     Number One : BAMBI versus GODZILLA
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+                                                            
+
+ ,| *./\|(/|/
+   /| |/`|',/| \|/
+ \/_,| /| /, /<|\\/\|/|\
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /   .:::. .  /
+  \___________/
+    |\      |\
+    | >     | \
+   / /      |  \
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /   .:::. .  /
+  \___________/
+    \|      |\
+     \      | \
+    / \    /  |
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /   .:::. .  /
+  \___________/
+    \\      \|
+     \\      \ 
+     | \     |\
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /   .:::. .  /
+  \___________/
+    \\      \|
+     >\      \
+    / |     /|
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    |\      |\
+    | >     | \
+   / /      |  \
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    \|      |\
+     \      | \
+    / \    /  |
+          
+         
+--,_^_   
+.    .\  
+__--___o
+--_    
+.  \    
+__  \/|  
+|\(  .|
+| \\ /
+  | "
+--_    
+.  \    
+__  \/|  
+|\(  .|
+| \\ /
+  | "
+--_    
+.  \    
+__  \/|  
+|\(  .|
+| \\ /
+  | "
+--_    
+.  \    
+__  \/|  
+|\(  .|
+| \\ /
+  | "
+--,_^_  
+.    .\  
+__--___o
+|\        
+| \      
+  |      
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /     
+  \___________/     
+    \\      \|
+     \\      \ 
+     | \     |\
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    \\      \|
+     >\      \
+    / |     /|
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    |\      |\
+    | >     | \
+   / /      |  \
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    \|      |\
+     \      | \
+    / \    /  |
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    \\      \|
+     \\      \ 
+     | \     |\
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    \\      \|
+     >\      \
+    / |     /|
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    |\      |\
+    | >     | \
+   / /      |  \
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    \|      |\
+     \      | \
+    / \    /  |
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    \\      \|
+     \\      \ 
+     | \     |\
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    \\      \|
+     >\      \
+    / |     /|
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    |\      |\
+    | >     | \
+   / /      |  \
+        
+         
+--,_^_   
+.    .\  
+__--___o
+--_     
+.  \     
+__  \/|  
+|\(  .| 
+| \\ /
+|  \"
+--_      
+.  \     
+__  \/|   
+|\(  .|
+| \\ /
+|  \"
+--,_^_
+.    .\ 
+__--___o
+|\       
+| \      
+|  \     
+--,_^_
+.    .\ 
+__--___o
+|\       
+| \      
+|  \     
+--_      
+.  \     
+__  \/|   
+|\(  .|
+| \\ /
+|  \"
+--_      
+.  \     
+__  \/|   
+|\(  .|
+| \\ /
+|  \"
+--_      
+.  \     
+__  \/|   
+|\(  .|
+| \\ /
+|  \"
+--,_^_
+.    .\ 
+__--___o
+|\      
+| \     
+|  \    
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /    
+  \___________/     
+    \|      |\
+     \      | \
+    / \    /  |
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    \\      \|
+     \\      \ 
+     | \     |\
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    \\      \|
+     >\      \
+    / |     /|
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    |\      |\
+    | >     | \
+   / /      |  \
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    \|      |\
+     \      | \
+    / \    /  |
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    \\      \|
+     \\      \ 
+     | \     |\
+              _^_
+ o           /  .\
+  \,--------;   __o
+  /  .:::.. .  /
+  \___________/
+    \\      \|
+     >\      \
+    / |     /|
+                     
+ o                  
+  \,----------,_^_   
+  /  .:::.. .    .\  
+  \___________--___o
+    \\      \|
+     >\      \
+    / |     /|
+                     
+ o          
+  \,----------_    
+  /  .:::.. .  \    
+  \___________  \/|  
+    \\      \|(  .|
+     >\      \ \ /
+    / |     /|  "
+
+`'     `.__________________________________/M
+( /   (/M
+(-.___)M
+/     \/)M
+_______.--'\M
+,____________/\M
+(           /   )M
+(            )  /M
+\           \    )M
+(                 )M
+(    (            /M
+\    (             )M
+(     \             )M
+(    (              /M
+
+\    (        )      )M
+
+(     (        /      )M
+
+(     \         )     /M
+
+\    (          )      )M
+
+(                )      )M
+
+(                )      /M
+
+\                /       )M
+
+(                  )      )
+  /  >      | \
+                             
+                             
+          T          T          T
+          T H          T H          T H
+          T H E          T H E          T H E           T H E 
+          T H E   E          T H E   E          T H E   E
+          T H E   E N          T H E   E N          T H E   E N
+          T H E   E N D          T H E   E N D
+         ===============
+ 
+[?25h
diff --git a/third_party/pexpect/tests/depricated_test_filedescriptor.py b/third_party/pexpect/tests/depricated_test_filedescriptor.py
new file mode 100755
index 0000000..6b0ef3e
--- /dev/null
+++ b/third_party/pexpect/tests/depricated_test_filedescriptor.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import PexpectTestCase
+import os
+
+class ExpectTestCase(PexpectTestCase.PexpectTestCase):
+    def setUp(self):
+        print(self.id())
+        PexpectTestCase.PexpectTestCase.setUp(self)
+
+    def test_fd (self):
+        fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+        s = pexpect.spawn (fd)
+        s.expect ('This is the end of test data:')
+        s.expect (pexpect.EOF)
+        assert s.before == ' END\n'
+
+    def test_maxread (self):
+        fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+        s = pexpect.spawn (fd)
+        s.maxread = 100
+        s.expect('2')
+        s.expect ('This is the end of test data:')
+        s.expect (pexpect.EOF)
+        assert s.before == ' END\n'
+
+    def test_fd_isalive (self):
+        fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+        s = pexpect.spawn (fd)
+        assert s.isalive()
+        os.close (fd)
+        assert not s.isalive()
+
+    def test_fd_isatty (self):
+        fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+        s = pexpect.spawn (fd)
+        assert not s.isatty()
+        os.close(fd)
+
+###    def test_close_does_not_close_fd (self):
+###        '''Calling close() on a pexpect.spawn object should not
+###                close the underlying file descriptor.
+###        '''
+###        fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+###        s = pexpect.spawn (fd)
+###        try:
+###            s.close()
+###            self.fail('Expected an Exception.')
+###        except pexpect.ExceptionPexpect, e:
+###            pass
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase, 'test')
+
+#fout = open('delete_me_1','wb')
+#fout.write(the_old_way)
+#fout.close
+#fout = open('delete_me_2', 'wb')
+#fout.write(the_new_way)
+#fout.close
diff --git a/third_party/pexpect/tests/echo_w_prompt.py b/third_party/pexpect/tests/echo_w_prompt.py
new file mode 100644
index 0000000..3c80553
--- /dev/null
+++ b/third_party/pexpect/tests/echo_w_prompt.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+from __future__ import print_function
+
+try:
+    raw_input
+except NameError:
+    raw_input = input
+
+while True:
+    try:
+        a = raw_input('<in >')
+    except EOFError:
+        print('<eof>')
+        break
+    print('<out>', a, sep='')
diff --git a/third_party/pexpect/tests/echo_wait.py b/third_party/pexpect/tests/echo_wait.py
new file mode 100755
index 0000000..e152059
--- /dev/null
+++ b/third_party/pexpect/tests/echo_wait.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import time
+import termios
+import sys
+
+# a dumb PAM will print the password prompt first then set ECHO
+# False. What it should do it set ECHO False first then print the
+# prompt. Otherwise, if we see the password prompt and type out
+# password real fast before it turns off ECHO then some or all of
+# our password might be visibly echod back to us. Sounds unlikely?
+# It happens.
+
+print("fake password:")
+sys.stdout.flush()
+time.sleep(3)
+attr = termios.tcgetattr(sys.stdout)
+attr[3] = attr[3] & ~termios.ECHO
+termios.tcsetattr(sys.stdout, termios.TCSANOW, attr)
+time.sleep(12)
+attr[3] = attr[3] | termios.ECHO
+termios.tcsetattr(sys.stdout, termios.TCSANOW, attr)
+time.sleep(2)
diff --git a/third_party/pexpect/tests/exit1.py b/third_party/pexpect/tests/exit1.py
new file mode 100755
index 0000000..587b8ad
--- /dev/null
+++ b/third_party/pexpect/tests/exit1.py
@@ -0,0 +1,24 @@
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import os, sys
+
+print("Hello")
+sys.stdout.flush()
+os._exit(1)
diff --git a/third_party/pexpect/tests/exit667.c b/third_party/pexpect/tests/exit667.c
new file mode 100644
index 0000000..962b9fd
--- /dev/null
+++ b/third_party/pexpect/tests/exit667.c
@@ -0,0 +1,26 @@
+/*
+    PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+#include <stdio.h>
+int main ()
+{
+    printf ("Hello world!\n");
+    exit(7);
+}
diff --git a/third_party/pexpect/tests/fakessh/ssh b/third_party/pexpect/tests/fakessh/ssh
new file mode 100755
index 0000000..28eedc4
--- /dev/null
+++ b/third_party/pexpect/tests/fakessh/ssh
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+from __future__ import print_function
+
+import getpass
+import sys
+PY3 = (sys.version_info[0] >= 3)
+if not PY3:
+    input = raw_input
+
+print("Mock SSH client for tests. Do not enter real security info.")
+
+pw = getpass.getpass('password:')
+if pw != 's3cret':
+    print('Permission denied!')
+    sys.exit(1)
+
+prompt = "$"
+while True:
+    cmd = input(prompt)
+    if cmd.startswith('PS1='):
+        prompt = eval(cmd[4:]).replace('\$', '$')
+    elif cmd == 'ping':
+        print('pong')
+    elif cmd.startswith('ls'):
+        print('file1.py', 'file2.html', sep='\t')
+    elif cmd == 'echo $?':
+        print(0)
+    elif cmd in ('exit', 'logout'):
+        break
\ No newline at end of file
diff --git a/third_party/pexpect/tests/getch.py b/third_party/pexpect/tests/getch.py
new file mode 100755
index 0000000..41e3224
--- /dev/null
+++ b/third_party/pexpect/tests/getch.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import sys, tty, termios
+
+if hasattr(sys.stdin, 'buffer'):
+    # Python 3: we want to read raw bytes
+    stdin = sys.stdin.buffer
+else:
+    stdin = sys.stdin
+
+def main():
+    print('READY')
+    while True:
+        try:
+            val = ord(stdin.read(1))
+        except KeyboardInterrupt:
+            val = 3
+        sys.stdout.write('%d<STOP>\r\n' % (val,))
+        if val == 0:
+            # StopIteration equivalent is ctrl+' ' (\x00, NUL)
+            break
+
+if __name__ == '__main__':
+    fd = sys.stdin.fileno()
+    old_settings = termios.tcgetattr(fd)
+    try:
+        tty.setraw(sys.stdin.fileno())
+        main()
+    finally:
+        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
diff --git a/third_party/pexpect/tests/globe.vt b/third_party/pexpect/tests/globe.vt
new file mode 100644
index 0000000..85dc78d
--- /dev/null
+++ b/third_party/pexpect/tests/globe.vt
@@ -0,0 +1,690 @@
+              _-o#&&*''''?d:>b\_
+          _o/"`''  '',, dMF9MMMMMHo_
+       .o&#'        `"MbHMMMMMMMMMMMHo.
+     .o"" '         vodM*$&&HMMMMMMMMMM?.
+    ,'              $M&ood,~'`(&##MMMMMMH\
+   /               ,MMMMMMM#b?#bobMMMMHMMML
+  &              ?MMMMMMMMMMMMMMMMM7MMM$R*Hk
+ ?$.            :MMMMMMMMMMMMMMMMMMM/HMMM|`*L
+|               |MMMMMMMMMMMMMMMMMMMMbMH'   T,
+$H#:            `*MMMMMMMMMMMMMMMMMMMMb#}'  `?
+]MMH#             ""*""""*#MMMMMMMMMMMMM'    -
+MMMMMb_                   |MMMMMMMMMMMP'     :
+HMMMMMMMHo                 `MMMMMMMMMT       .
+?MMMMMMMMP                  9MMMMMMMM}       -
+-?MMMMMMM                  |MMMMMMMMM?,d-    '
+ :|MMMMMM-                 `MMMMMMMT .M|.   :
+  .9MMM[                    &MMMMM*' `'    .
+   :9MMk                    `MMM#"        -
+     &M}                     `          .-
+      `&.                             .
+        `~,   .                     ./
+            . _                  .-
+              '`--._,dd###pp=""'
+              _v->#H#P? "':o<>\_
+          .,dP` `''  "'-o.+H6&MMMHo_
+        oHMH9'         `?&bHMHMMMMMMHo.
+      oMP"' '           ooMP*#&HMMMMMMM?.
+    ,M*          -     `*MSdob//`^&##MMMH\
+   d*'                .,MMMMMMH#o>#ooMMMMMb
+  HM-                :HMMMMMMMMMMMMMMM&HM[R\
+ d"Z\.               9MMMMMMMMMMMMMMMMM[HMM|:
+-H    -              MMMMMMMMMMMMMMMMMMMbMP' :
+:??Mb#               `9MMMMMMMMMMMMMMMMMMH#! .
+: MMMMH#,              "*""""`#HMMMMMMMMMMH  -
+||MMMMMM6\.                    {MMMMMMMMMH'  :
+:|MMMMMMMMMMHo                 `9MMMMMMMM'   .
+. HMMMMMMMMMMP'                 !MMMMMMMM    `
+- `#MMMMMMMMM                   HMMMMMMM*,/  :
+ :  ?MMMMMMMF                   HMMMMMM',P' :
+  .  HMMMMR'                    {MMMMP' ^' -
+   : `HMMMT                     iMMH'     .'
+    -.`HMH                               .
+      -:*H                            . '
+        -`\,,    .                  .-
+          ' .  _                 .-`
+              '`~\.__,obb#q==~'''
+              .ovr:HMM#?:`' >b\_
+          .,:&Hi' `'   "' \\|&bSMHo_
+        oHMMM#*}          `?&dMMMMMMHo.
+     .dMMMH"''''           ,oHH*&&9MMMM?.
+    ,MMM*'                 `*M\bd<|"*&#MH\
+   dHH?'                   :MMMMMM#bd#odMML
+  H' |\                  `dMMMMMMMMMMMMMM9Mk
+ JL/"7+,.                `MMMMMMMMMMMMMMMH9ML
+-`Hp     '               |MMMMMMMMMMMMMMMMHH|:
+:  \\#M#d?                `HMMMMMMMMMMMMMMMMH.
+.   JMMMMM##,              ``*""'"*#MMMMMMMMH
+-. ,MMMMMMMM6o_                    |MMMMMMMM':
+:  |MMMMMMMMMMMMMb\                 TMMMMMMT :
+.   ?MMMMMMMMMMMMM'                 :MMMMMM|.`
+-    ?HMMMMMMMMMM:                  HMMMMMM\|:
+ :     9MMMMMMMMH'                 `MMMMMP.P.
+  .    `MMMMMMT''                   HMMM*''-
+   -    TMMMMM'                     MM*'  -
+    '.   HMM#                            -
+      -. `9M:                          .'
+        -. `b,,    .                . '
+          '-\   .,               .-`
+              '-:b~\\_,oddq==--"
+              _oo##'9MMHb':'-,o_
+          .oH":HH$' ""'  "' -\7*R&o_
+       .oHMMMHMH#9:          "\bMMMMHo.
+      dMMMMMM*""'`'           .oHM"H9MM?.
+    ,MMMMMM'                   "HLbd<|?&H\
+   JMMH#H'                     |MMMMM#b>bHb
+  :MH  ."\                   `|MMMMMMMMMMMM&
+ .:M:d-"|:b..                 9MMMMMMMMMMMMM+
+:  "*H|      -                &MMMMMMMMMMMMMH:
+.    `LvdHH#d?                `?MMMMMMMMMMMMMb
+:      iMMMMMMH#b               `"*"'"#HMMMMMM
+.   . ,MMMMMMMMMMb\.                   {MMMMMH
+-     |MMMMMMMMMMMMMMHb,               `MMMMM|
+:      |MMMMMMMMMMMMMMH'                &MMMM,
+-       `#MMMMMMMMMMMM                 |MMMM6-
+ :        `MMMMMMMMMM+                 ]MMMT/
+  .       `MMMMMMMP"                   HMM*`
+   -       |MMMMMH'                   ,M#'-
+    '.     :MMMH|                       .-
+      .     |MM                        -
+       ` .   `#?..    .             ..'
+           -.     _.             .-
+              '-|.#qo__,,ob=~~-''
+              _ooppH[`MMMD::--\_
+          _oHMR":&M&. ""'  "'  /&\\_
+        oHMMMMMHMMH#9,         `"<MMHo.
+      oHMMMMMMMM*""'``           .dMP#M?.
+    .dMMMMMMMM*                   `H\do?&\
+   -iMMMHH#H'                      &MMMHb#?
+  : ZMM'   7-.                   `{MMMMMMMMH
+ .  .M6_d|"`$|v..                 9MMMMMMMMML
+-    `'*H#       :                |MMMMMMMMMM:
+:        *\\dHM#dd.                ?MMMMMMMMMb
+-          |MMMMMMM##\              `"*""?HMMM
+:      .  |MMMMMMMMMMMo\.                 {MMM
+.         {MMMMMMMMMMMMMMMHo.             `MMM
+-          ?MMMMMMMMMMMMMMM*'             -MMP
+:           `#MMMMMMMMMMMMT               dMM'
+ -            |MMMMMMMMMMH'              -MMT
+  :           `MMMMMMMM"'                JMP
+   -           MMMMMMH'                 ,H?
+    '.         HMMM#'                    :
+      .        ?MM-                   . '
+        -.      *M:..               .-
+           - .      _.           .-
+              '-.~-dHb__\ov+~~-`
+              .oo>#&H6?*MMH:-.._
+          .oHMMMR:"&MZ\ `"'  "  |$-_
+       ..dMMMMMMMMdMMM#9\        `'HHo.
+     . ,dMMMMMMMMMMM"`' `           ?MP?.
+    . |MMMMMMMMMMM'                 `"$b&\
+   -  |MMMMHH##M'                     HMMH?
+  -   TTMM|    >..                   \MMMMMH
+ :     |MM\,#-""$~b\.                `MMMMMM+
+.       ``"H&#        -               &MMMMMM|
+:            *\v,#MHddc.              `9MMMMMb
+.               MMMMMMMM##\             `"":HM
+-          .  .HMMMMMMMMMMRo_.              |M
+:             |MMMMMMMMMMMMMMMM#\           :M
+-              `HMMMMMMMMMMMMMMM'           |T
+:               `*HMMMMMMMMMMMM'            H'
+ :                 MMMMMMMMMMM|            |T
+  .                MMMMMMMM?'             ./
+  `.               MMMMMMH'              ./
+    -.            |MMMH#'                .
+      .           `MM*                . '
+        -.         #M: .    .       .-
+          ` .         .,         .-
+              '-.-~ooHH__,,v~--`
+              _ood>H&H&Z?#M#b-\.
+          .\HMMMMMR?`\M6b."`' ''``v.
+       .. .MMMMMMMMMMHMMM#&.      ``~o.
+     .   ,HMMMMMMMMMMMM*"'-`          &b.
+    .   .MMMMMMMMMMMMH'               `"&\
+   -     RMMMMM#H##R'                   4Mb
+  -      |7MMM'    ?::                 `|MMb
+ /         HMM__#|`"\>?v..              `MMML
+.           `"'#Hd|       `              9MMM:
+-                |\,\?HH#bbL             `9MMb
+:                   !MMMMMMMH#b,          `""T
+.              .   ,MMMMMMMMMMMbo.           |
+:                  4MMMMMMMMMMMMMMMHo        |
+:                   ?MMMMMMMMMMMMMMM?        :
+-.                   `#MMMMMMMMMMMM:        .-
+ :                     |MMMMMMMMMM?         .
+  -                    JMMMMMMMT'          :
+  `.                   MMMMMMH'           -
+    -.                |MMM#*`            -
+      .               HMH'            . '
+        -.            #H:.          .-
+          ` .           .\       .-
+              '-..-+oodHL_,--/-`
+              _,\?dZkMHF&$*q#b..
+          .//9MMMMMMM?:'HM\\"`-''`..
+       ..`  :MMMMMMMMMMHMMMMH?_    `-\
+     .     .dMMMMMMMMMMMMMM'"'"       `\.
+    .      |MMMMMMMMMMMMMR              \\
+   -        T9MMMMMHH##M"                `?
+  :          (9MMM'    !':.               &k
+ .:            HMM\_?p "":-b\.            `ML
+-                "'"H&#,       :           |M|
+:                     ?\,\dMH#b#.           9b
+:                        |MMMMMMM##,        `*
+:                   .   +MMMMMMMMMMMo_       -
+:                       HMMMMMMMMMMMMMM#,    :
+:                        9MMMMMMMMMMMMMH'    .
+: .                       *HMMMMMMMMMMP     .'
+ :                          MMMMMMMMMH'     .
+  -                        :MMMMMMM'`      .
+  `.                       9MMMMM*'       -
+    -.                    {MMM#'         :
+      -                  |MM"          .'
+       `.                &M'..  .   ..'
+          ' .             ._     .-
+              '-. -voboo#&:,-.-`
+              _oo:\bk99M[<$$+b\.
+           .$*"MMMMMMMM[:"\Mb\?^" .
+       . '`    HMMMMMMMMMMHMMMM+?.  `.
+     .        .HMMMMMMMMMMMMMMP"''     .
+    .         `MMMMMMMMMMMMMM|         -`.
+   -           `&MMMMMMHH##H:             :
+  :             `(*MMM}    `|\             |
+ : `-              ?MMb__#|""`|+v..         \
+.                    `''*H#b       -        :|
+:                         `*\v,#M#b#,        \
+.                             9MMMMMMHb.     :
+:                        .   #MMMMMMMMMb\    -
+-                           .HMMMMMMMMMMMMb  :
+:                            `MMMMMMMMMMMMH  .
+-:  .                         `#MMMMMMMMMP   '
+ :                              ]MMMMMMMH'  :
+  -                            ,MMMMMM?'   .
+  `:                           HMMMMH"    -
+    -.                       .HMM#*     .-
+     `.                     .HH*'     .
+       `-.                  &R".    .-
+           -.               ._   .-
+              '-. .voodoodc?..-`
+              _\oo\?ddk9MRbS>v\_
+          ..:>*""MMMMMMMMM:?|H?$?-.
+       ..- -     "HMMMMMMMMMMHMMMH\_-.
+     .            dMMMMMMMMMMMMMMT"    .
+    .             TMMMMMMMMMMMMMM       `.
+   -               `&HMMMMMM#H#H:         .
+  -                 `\7HMMH     |\.        .
+ :    `                 HMM\_?c`""+?\..     :
+-                         "``#&#|      .     -
+:                              `?,\#MHdb.    .
+:                                 |MMMMMH#.  :
+:                            .   ,HMMMMMMMb, -
+: '                              4MMMMMMMMMMH`
+:   .                             9MMMMMMMMMT-
+:.`                               `#MMMMMMMH '
+ :      '                           HMMMMMH':
+  -                                |MMMMH" -
+  `:                              |MMMH*' .'
+    '?                           dMM#'   .
+      \.                       .dH"    .'
+        -.                    ,M'-  ..'
+          ` .                .. ..-`
+              '-. .\ooooboo<^.-`
+              _o,:o?\?dM&MHcc~,.
+          ..^':&#""HMMMMMMMM$:?&&?.
+        .`  -`      'HMMMMMMMMMHMMMp\.
+     . '             |MMMMMMMMMMMMMM"' .
+    .                `9MMMMMMMMMMMMM    -.
+   -                   `*9MMMMMHH##[      .
+  -                     `\Z9MMM    `~\     .
+ :       '|                 ?MMb_?p""-?v..  :
+-                             `"'*&#,    -   .
+:                                  `?,oHH#?  .
+--                                    |MMMMH,:
+:                                 .  |MMMMMM6,
+:   -                                |MMMMMMMM
+?                                     HMMMMMMP
+-- . '                                |HMMMMM'
+ :.`     .  '                          JMMMM+
+  \                                   ,MMMP:
+   :                                 |MMH?:
+    -:\.                            dM#" .
+       \                          ,H*' .'
+        -.                       d':..'
+          ` .                  .,.-
+              '-.. .\oooodov~^-`
+              _o\:,??\??MR9#cb\_
+          .v/''':&#""#HMMMMMMM$?*d\.
+       ..~' - -`      `"#MMMMMMMMMMMHv.
+     .-'                 HMMMMMMMMMMMR!.
+    :                    `9MMMMMMMMMMM| -.
+   .                       `*9MMMMMH##|   .
+  -                          `(#MMH   `:,  .
+ :           '|                 `HMb_>/"|\,.:
+.'                                `"'#&b   - .
+:                                      ?\oHH?.
+:                                        !MMM&
+:  .                                  .  HMMMM
+/.      -                               -MMMMM
+\`.                                      9MMMP
+:. .  . -                                |MMM'
+ \... '                                  .MMT
+  &.                                    .dMP
+   \,                                  .HM*
+    \. `\.                            ,H&'
+     `- `| -                        ,&':
+       `.                         ,/\ '
+          '-..                  _.-
+              "---.._\o,oov+--'"
+              _,d?,:?o?:?HM>#b\_
+          ..H*"''`'H#*"**MMMMMM6$$v_
+        v//"   - ``      `'#MMMMMMMMHo.
+      /"`                   |MMMMMMMMMM:.
+    ,>                       `HMMMMMMMMH:.
+   :                           `#HMMMMHH\ -
+  '                              `Z#MM,  `,:
+ :               '\                 ?HH_>:`\,
+:                                     "'*&| `:
+.                                         <\Hb
+:                                           MM
+:                                        . iMM
+Mb\.                                       {MM
+::.`-       -                              !MP
+`&.   .  .  -                              :M'
+ 9H,  \  '                                 |T
+  HM?                                     ,P
+   *ML                                   ??
+    :&.   `o                           .d'
+      ':  |T                          /"
+        -.                         .<''
+          `...                  ..-
+              "`-=.,_,,,oov-~.-`
+              _,oc>?_:b?o?HH#b\_
+          .v/99*""" '*H#""*HMMMMMZ,_
+        oH* /"   -   '      "`#MMMMM#o.
+     ./*>-                     `MMMMMMMb
+    ,b/'                        `#MMMMMMM\
+   :'                             ``HMMMMb:
+  /-                                `|&MH `\
+ /                   `-.               |Hb??\
+,-  '                                    "`&,.
+1                                           \}
+!.                                           T
+$,.                                        . 1
+?`M??.                                       M
+?.::| '\        -                            ?
+ M?&.    .   .  -                           ,'
+ 9MMH\   ..  '           `                  .
+  HMMM#.                                   :'
+   9#MMb                                 ..
+    -:"#     `b.                        .-
+      . `    {!                        /
+        -                           ,-'
+          ' .                    .-
+             ```^==\_.,,,ov--\-`
+              _\o##??,:io??$#b\_
+          .oH#"H9*""" "`#H*"*#MMMHo_
+        oHMM- -'    -  ''     ``*HMMHo.
+      dM#S>-`                     ?MMMM?.
+    ,&&,/'                         "#MMMH\
+   d?-"                              `*HMMb
+  H?                                   "ZHb:
+ /:                        \              H?L
+|:|   .                                    `*:
+:?:                                          \
+>"                                           :
+M|\,_                                        |
+!|":HH?-'.                                   :
+:^'_:?"\ `--         -                       .
+- |ML?b      .   ..  -                       -
+ :HMMMMH\    \               `              :
+  >MMMMMM#.                                .
+   ^M*HMMM|                               -
+    `. `"#+     `?v                     .`
+      .   `-    +?'                    -
+       ` .                          ..'
+           - .                   .-
+              "`\b=p?.._\\vv---`
+              _,o#bH\??::?o?cbo_
+          .o#MH#**SH""' "`*H#"*#MHo_
+        oHMMMH^  ^"    -  `      '*HHo.
+     .dMMM#">>-                     `HM?.
+    ,MH:R_o/                         `*MH\
+   dMM' '                               "ML
+  HMR! '                                 `#k
+ d&'.                          -.          `L
+:M ::     `                                 `-
+/| !|                                        -
+k.$-"                                        :
+}9R:!,,_.                                    .
+\::\':`*M#\-'.                               -
+: "''..:"!`\  '-          -                  `
+-   ,HMb.H|      .    _   -                 .'
+ : ,MMMMMMMb.    ..                         .
+  .`HMMMMMMMM?                             .
+  `.`9M#*HMMMM                            :
+    -.'   "##*      `b,                  .
+      .      `     ,/'                 .'
+       ` .                          ..'
+           - .                  ..-
+              "`*#d##c.._\v----`
+              _,o#&oHb?\o::d?>\_
+          .oHHMMM#**$M""` "`*HH"#&o_
+        oHMMMMMMD' .''    -  '    ``bo.
+     .dMMMMMH*'/|-                   `\b.
+    ,MMMM?T|_o/                        `\\
+   dMMMMP  ''                            `|
+  HMMMH& -                                `\
+ /MH7' :                          --        :
+-:MM  {.      .                              .
+:i?' .!&                                     .
+:{, o| '                                     :
+-T?9M\:-'o,_                                 .
+: \?::``"`?9MHo./..                          -
+.  '"`'^ _.`"!"^.  `-         -              `
+-      ,bMM?.M\       .    .  -      .      .'
+ :   .oMMMMMMMMb.    ..   `                 .
+  .  `HMMMMMMMMMMb                         -
+   -   9MH*#HMMMMH                        .'
+    '.  '   `"*##'      `b.              :
+      .         `     .d''             .'
+        -.                          . '
+           -.                    .-`
+              "`*##H###:._\--.-`
+              _oo#H&d#b?\b:_>>\_
+          .oHMMMMMMH*"*9R"'-``*#P\-_
+        oHMMMMMMMMM$  ."       '   `^-
+     .dMMMMMMMMH*",?-                 '\.
+    ,MMMMMMM:?}.,d'                     `.
+   dMMMMMMMH  /''                         :
+  HMMMMMMM&' -                             -
+ dPTMMP>' :                           -.    :
+|? -MM}  .\                                  .
+J' ::*'  -$L                                 .
+:  ?b .,H- '                                 :
+-  |6.&MP:: !.,_.                            -
+:   `\:: "' "`:"MM#,-^,            -         :
+-     ````:' _.:"?``\   `-                   .
+:         .?bMML.]#        -   _  `      .  .'
+ -      .o#MMMMMMMMH\     \.          .     .
+  -     `HMMMMMMMMMMMH                     :
+  `.     `HMM#*#MMMMMH'                   -
+    -.     '    ``##*'      i+           :
+      -            `'     v/'          .'
+       `-                           ..'
+          ' .                    .-
+              "`*##HMH##:__,-.-`
+              _oo##Mbb&bo??o_>\_
+          .oHMMMMMMMMM**#?M*' "?*&..
+        oHMMMMMMMMMMMM4  `"      -  `.
+     .dMMMMMMMMMMMM#"\?.-              .
+    ,MMMMMMMMMM}"9:_,d'                 -.
+   dMMMMMMMMMMM|  ^''                     .
+  &MMMMMMMMMMH\  -                         .
+ :{M*"MMMPT"' :                         `-. :
+.'M'  'MMM.  -T,       .                     .
+- k   i:?''  -|&                             .
+: `  -o&  .,H- "                             :
+-     `M:`HMP|:'!.o._.                       .
+:      "<:::'<^ '"``9MH#,-^ .                -
+-         '''``''._.`"?`^|   ^        -      :
+:              ?#dMM_.M?       .   .  -    ..'
+ :          ,ddMMMMMMMMMb.    ..   '        .
+  .         TMMMMMMMMMMMMM,                :
+   -         ?MMH**#MMMMMH'               :
+    '.        '     "`##*'      &.       :
+      -.               `'    ,~"       .'
+        -.                          ..'
+          ` .                    .-
+             ```*##HMMMH#<:,..-`
+              _,dd#HMb&dHo?\?:\_
+          .oHMMMMMMMMMMMH***9P'`"\v.
+        oHMMMMMMMMMMMMMMM>  `'      -.
+     .dMMMMMMMMMMMMMMMH*'|~-'          .
+    ,MMMMMMMMMMMMM6>`H._,&              -.
+   dMMMMMMMMMMMMMMM|  `"                  .
+  H*MMMMMMMMMMMMMH&. -                     .
+ d' HMM""&MMMPT'' :.                      `.-
+,'  MP   `TMMM,   |:        .                -
+|   #:    ? *"   : &L                        :
+!   `'   /?H   ,#r `'                        :
+.         ?M: HMM^<~->,o._                   :
+:          `9:::'`*-``':`9MHb,|-,         '  :
+.             `"''':' :_ ""!"^.  `|          :
+`.                 _dbHM6_|H.      .   . '  .'
+ \              _odHMMMMMMMMH,    ..  `     :
+ `-             |MMMMMMMMMMMMM|            :
+  `.             9MMH**#MMMMMH'           :
+    -.            '     "?##"      d     :
+      .                    '    ,/"    .'
+       `..                          ..'
+          `  .                   .-
+              '`"#HHMMMMM#<>..-`
+              _oo##bHMb&d#bd,>\_
+          .oHMMMMMMMMMMMMMM***9R"-..
+        oHMMMMMMMMMMMMMMMMMH\  ?   `-.
+     .dMMMMMMMMMMMMMMMMMMM#".}-'       .
+    ,MMMMMMMMMMMMMMMMM6/`H _o}          -.
+   dMMMMMMMMMMMMMMMMMMML  `''             .
+  HbP*HMMMMMMMMMMMMMMM*: -                 ,
+ dMH' `MMMP'"HMMMR'T"  :                    :
+|H'   -MR'   `?MMMb    P,       .            .
+1&     *|     |.`*"  .-`&|                   .
+M'      "    |\&|  .,#~ "'                   :
+T             :HL.|HMH\c~`|v,\_              :
+|              `"|:::':`-`` '"MM#\-'.       -:
+%                 ``'``'`' :_ '?'`| ``.      :
+||,                     ,#dMM?.M?      .  .` -
+ ?\                 .,odMMMMMMMMM?    \  `  :
+  /                 |MMMMMMMMMMMMM:        .'
+  `.                 TMMH#*9MMMMM*        :
+    -.               `      "*#*'    ,:  .
+      .                       `   .v'' .'
+       `.                           ..'
+          '- .                   .-
+              "`\+HHMMMMMMHr~.-`
+              _,,>#b&HMHd&&bb>\_
+          _oHMMMMMMMMMMMMMMMMH**H:.
+        oHMMMMMMMMMMMMMMMMMMMM#v`?  `.
+     .dMMMMMMMMMMMMMMMMMMMMMMH*`+|     .
+    ,MMMMMMMMMMMMMMMMMMMMMb|?+.,H       -.
+   ddHMMMMMMMMMMMMMMMMMMMMMb  `'          .
+  HMMkZ**HMMMMMMMMMMMMMMMMH\  -   .        :
+ dTMMM*  `9MMMP'"*MMMMPT"` ..               :
+|M6H''    4MP'   `"HMMM|   !|.      .        .
+1MHp'      #L      $ *"'  .-:&.              .
+MMM'        "     q:H.  .o#-``'              :
+MM'                ?H?.|MMH::::-o,_.         -
+M[                  `*?:::'|` `"`:9MH\~-.    `
+&M.                     ""'`'^'.:.`?'`. '|  -:
+`M|d,                       .dbHM[.1?     .. :
+ 9||| .                  _obMMMMMMMMH,   .  :
+  H.^                    MMMMMMMMMMMM}     -
+   \                     |MMH#*HMMMMH'    .'
+    .                    `      `#*'   ,:-
+     `                           '' .-'.
+       `.                           .-
+          '- .                   .-`
+              '`\bqHMMMMMMHHb--`
+              .,:,#&6dHHHb&##o\_
+          .oHHMMMMMMMMMMMMMMMMMH*\,.
+        oHMMMMMMMMMMMMMMMMMMMMMMHb:'-.
+     .dMMMMMMMMMMMMMMMMMMMMMMMMMH|\/'  .
+    ,&HMMMMMMMMMMMMMMMMMMMMMMM/"&.,d.   -.
+   dboMMHMMMMMMMMMMMMMMMMMMMMMML `'       .
+  HMHMMM$Z***MMMMMMMMMMMMMMMMMM|.-         .
+ dMM}MMMM#'  `9MMMH?"`MMMMR'T'  _           :
+|MMMbM#''     |MM"    ``MMMH.   <_           .
+dMMMM#&        *&.     .?`*"   .'&:          .
+MMMMMH-         `'    -v/H   .dD "'  '       :
+MMMM*                  `*M: 4MM*::-!v,_      :
+MMMM                     `*?::" "'``"?9Mb::. :
+&MMM,                       `"'"'|"._ "?`| - :
+`MMM}.H                          ,#dM[_H   ..:
+ 9MMi`M: .                   .ooHMMMMMMM,  ..
+  9Mb `-                     1MMMMMMMMMM|  :
+   ?M                        |MM#*#MMMM*  .
+    -.                       `     |#"' ,'
+      .                            -" v`
+        -.                          .-
+           - .                   . `
+              '-*#d#HHMMMMHH#"-'
+              _,<_:&S6dHHHb&bb\_
+          .odHMMMMMMMMMMMMMMMMMMM}-_
+       .oHMMMMMMMMMMMMMMMMMMMMMMMM#d:.
+      ?9MMMMMMMMMMMMMMMMMMMMMMMMMMMH-$ .
+    ,::dHMMMMMMMMMMMMMMMMMMMMMMMMH:\.?? -.
+   dMdboHMMHMMMMMMMMMMMMMMMMMMMMMMH, '    .
+  HMMMM7MMMb$R***MMMMMMMMMMMMMMMMMH\ -     .
+ dMMMMM/MMMMM*   `$MMMM*'"*MMMM?&'  .       :
+|MMMMMMb1H*'       HMP'    '9MMM|   &.    .  .
+dMMMMMMM##~`       `#\      |.`*"  .-9.      :
+9MMMMMMMM*           `     |v7?  .,H `' `    :
+SMMMMMMH'                   '9M_-MMH::-\v_   :
+:HMMMMM                       `\_:"'|'`':9Mv\.
+-|MMMMM,                         ""`'`':.`?\ \
+`:MMMMM}.d}                         .?bM6,|  |
+ :?MMM6  M|  .                   .,oHMMMMM| /
+  .?MMM- `'                      &MMMMMMMM|.
+   -`HM-                         HMH#*MMM?:
+    '.                           '   `#*:`
+      -                              -'/
+       ` .                          . '
+          ` .                    . `
+              '--##HH#HMMMHH#""`
+              _o,d_?dZdoHHHb#b\_
+          .vdMMMMMMMMMMMMMMMMMMMMH\.
+       .,HHMMMMMMMMMMMMMMMMMMMMMMMMH&,.
+      /?RMMMMMMMMMMMMMMMMMMMMMMMMMMMMH|..
+    ,\?>`T#RMMMMMMMMMMMMMMMMMMMMMMMM6`\|/
+   dMMbd#ooHMMMHMMMMMMMMMMMMMMMMMMMMMH,`' '
+  HMMMMMMMTMMMMb$ZP**HMMMMMMMMMMMMMMMM|.   :
+ dMMMMMMMM}$MMMMMH'   `HMMMH?"`MMMM?T' .    :
+|MMMMMMMMMMoMH*''      `MM?    ``MMM|  +\    .
+1MMMMMMMMMMMb#/         ?#?      |`#"  -T:   :
+*'HMMMMMMMMMM*'           "     ~?&  .?} ' ' .
+- 4MMMMMMMMP"                    `M? HMTc:\\.:
+: `MMMMMMM[                       "#:::`>`"?M{
+.  |MMMMMMH.                        ``'``'_`:-
+-  |MMMMMMM|.dD                         ,#Mb\'
+ :  *MMMMM: iM|  .                   _oHMMMM:
+  .  ?MMMM'  "'                     ,MMMMMMP
+   :  `HMH                          JM#*MMT
+    -.  '                           `   #'
+      .                                /
+        -.            -              .'
+           -.                    . `
+              '--=&&MH##HMHH#"""
+              .-:?,Z?:&$dHH##b\_
+           ,:bqRMMMMMMMMMMMMMMMMMHo.
+        .?HHHMMMMMMMMMMMMMMMMMMMMMMMHo.
+      -o/*M9MMMMMMMMMMMMMMMMMMMMMMMMMMMv
+    .:H\b\'|?#HHMMMMMMMMMMMMMMMMMMMMMM6?Z\
+   .?MMMHbdbbodMMMMHMMMMMMMMMMMMMMMMMMMM\':
+  :MMMMMMMMMMM7MMMMb?6P**#MMMMMMMMMMMMMMM_ :
+ \MMMMMMMMMMMMb^MMMMMM?   `*MMMM*"`MMMR<' . -
+.1MMMMMMMMMMMMMb]M#""       9MR'   `?MMb  \. :
+-MMMMMMMMMMMMMMMH##|`        *&.     |`*' .\ .
+-?""*MMMMMMMMMMMMM'            '    |?b  ,}" :
+:    MMMMMMMMMMH'                    `M_|M}r\?
+.    `MMMMMMMMM'                      `$_:`'"H
+-     TMMMMMMMM,                        '"``::
+:     {MMMMMMMM| oH|                      .#M-
+ :    `9MMMMMM' .MP   .                 ,oMMT
+  .     HMMMMP'  `'                    ,MMMP
+   -     `MMH'                         HH9*
+    '.    `                           ` .'
+      -                               . '
+       ` .               -          .-
+          ` .                    .-
+              ' -==pHMMH##HH#"""
+              _..-:b&::&?&&##bo_
+          ...?-#&9MMMMMMMMMMMMMMMHo_
+       .. .1&#MMHMMMMMMMMMMMMMMMMMMMHo.
+     .  .o/##R9MMMMMMMMMMMMMMMMMMMMMMMM?.
+    .- |MSd?|'`$?#HMMMMMMMMMMMMMMMMMMMMMH\
+   -  dMMMMHbd##oodMMMM#MMMMMMMMMMMMMMMMMH:
+  - JMMMMMMMMMMMMM7HMMMH$SR***MMMMMMMMMMMMb>
+ : {MMMMMMMMMMMMMMM`9MMMMMH'  ``HMMM?"*MM[| :
+- |MMMMMMMMMMMMMMMMM<MH*''      `MM'   'HM? |.
+: `MMMMMMMMMMMMMMMMMM##H-'       `#,  ` |`? /|
+.  ?"""?HMMMMMMMMMMMMMH'           "    v& .}?
+-       |MMMMMMMMMMMP'                  `H:&H&
+i       `9MMMMMMMMMT                     `|?"?
+:         MMMMMMMMMH                       "`\
+:         MMMMMMMMMH-.dH                    ,|
+ :        ?MMMMMMM?  {M' .                .dT
+  .        ?MMMMMR'  `'                  ,MP
+   -        `HMM#'                      .&*
+    '.        '                         `.
+      -                               . '
+       `..                          .-
+           -.                    .-
+              '-.==p##HMMHp&#"""
+              _v---:?&?:?&?&#b\_
+          ..' i: #M$MMMMMMMMMMMMMHo_
+       ..   -]M#HMHMMMMMMMMMMMMMMMMMHo.
+     .     ooP*&6&MMMMMMMMMMMMMMMMMMMMM?.
+    . -   &Rbbd-/`?:##HMMMMMMMMMMMMMMMMMH?
+   -    ,HMMMMM#od#boodMMMMHMMMMMMMMMMMMMMb
+  -   iMMMMMMMMMMMMMMM[*MMMH&$R***MMMMMMMMMb
+ :   |MMMMMMMMMMMMMMMMML"MMMMMM'  ``MMMP"HMM:
+.    HMMMMMMMMMMMMMMMMMMb/MH""      `MR   *M,|
+:    TMMMMMMMMMMMMMMMMMMMMd#&`       `D.   ?|\
+.     `*"'"*HMMMMMMMMMMMMMMP'          '  -d,J
+:           |MMMMMMMMMMMMP'                ||M
+M,           ?MMMMMMMMMM|                  `\?
+&|            HMMMMMMMMM}                   ``
+`L           .MMMMMMMMMMP ,d|                :
+ *.           ?MMMMMMMF' .MP                /
+  |            TMMMMMM'  `"'               /
+  `.            `MMMP'                   ./
+    -.           `                       .
+      .                               . '
+        - .                         .-
+           -\                   ..-
+              '-..=p####HMH&="""
+              _vo~^'':&b::d,#b\_
+          ..`" `:v +9P]MMMMMMMMMMHo_
+        ,-     ?Mb#MMMMMMMMMMMMMMMMMHo.
+     . "     ,ooM*&&&HMMMMMMMMMMMMMMMMHb.
+    .   -    99Soo?|'`*?##HMMMMMMMMMMMMMH\
+   -       .HMMMMMM#od#boodMMMMHMMMMMMMMMMb
+  -      :MMMMMMMMMMMMMMMM67HMMH&$R**HMMMMMb
+ :      .MMMMMMMMMMMMMMMMMMM/HMMMMM|  `9MM'HL
+:       {MMMMMMMMMMMMMMMMMMMM\MM*''    `H[ `9|
+|       `HMMMMMMMMMMMMMMMMMMMMb##|      `F. :?
+H        `"*"'"`#MMMMMMMMMMMMMMM?         '  k
+M.               MMMMMMMMMMMMM"'             H
+MMH.             `HMMMMMMMMMM:               |
+&MM|              `MMMMMMMMMM,               -
+`MM|              dMMMMMMMMMM|.oH            :
+ 9ML              `HMMMMMMM?  dH'           -
+  Hi               |MMMMMMP   "'           .'
+   T.               `MMM#'                -
+    `.               `                  .`
+     `                                 -
+       `.. .                        ..'
+           ...                   .-
+              '-. //######M#b~""
+              _ooq=""''$b$_&?b\_
+          .-`^"  "'o |&M:MMMMMMMMHo_
+        o/'      -$Mb#MMMMMMMMMMMMMMHo.
+      /'        .ooHP*&R&MMMMMMMMMMMMMM?.
+    .'          `MRbod?|'`+?##9MMMMMMMMMH\
+  .`          .,MMMMMMH#od##obdMMMMHMMMMMMb
+  -          ?MMMMMMMMMMMMMMMMM$HMMH$ZP*HMMb
+ ?          |MMMMMMMMMMMMMMMMMMM|9MMMMP  "M6\
+.-          dMMMMMMMMMMMMMMMMMMMMb]M*'    |R |
+1|          `HMMMMMMMMMMMMMMMMMMMMMd#|     ?,:
+MH,          ``*""'"*#MMMMMMMMMMMMMM*       '`
+MM6_                 |MMMMMMMMMMMMH"         :
+MMMMMb.               "MMMMMMMMMMT           -
+&MMMMM'                |MMMMMMMMMH           `
+!MMMMb                .HMMMMMMMMM+.?&        :
+ TMMMM                 *MMMMMMMP  dH' .     :
+  9MM'                 `MMMMMMP'  "'       .
+   9ML                  `MMM#'            -
+    `H                   `               :
+     `\.                               .'
+       `-\  .                       .-
+          ' ._                   .-`
+              '-\. ,b#####p&**^`
diff --git a/third_party/pexpect/tests/interact.py b/third_party/pexpect/tests/interact.py
new file mode 100755
index 0000000..9f8e672
--- /dev/null
+++ b/third_party/pexpect/tests/interact.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+try:
+    # This allows coverage to measure code run in this process
+    import coverage
+    coverage.process_startup()
+except ImportError:
+    pass
+
+from utils import no_coverage_env
+import pexpect
+import sys
+
+
+def main():
+    p = pexpect.spawn(sys.executable + ' echo_w_prompt.py',
+                      env=no_coverage_env())
+    p.interact()
+    print("Escaped interact")
+
+if __name__ == '__main__':
+    main()
diff --git a/third_party/pexpect/tests/interact_unicode.py b/third_party/pexpect/tests/interact_unicode.py
new file mode 100644
index 0000000..f4c1f55
--- /dev/null
+++ b/third_party/pexpect/tests/interact_unicode.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+'''
+Just like interact.py, but using spawnu instead of spawn
+'''
+try:
+    # This allows coverage to measure code run in this process
+    import coverage
+    coverage.process_startup()
+except ImportError:
+    pass
+
+from utils import no_coverage_env
+import pexpect
+import sys
+
+
+def main():
+    p = pexpect.spawnu(sys.executable + ' echo_w_prompt.py',
+                       env=no_coverage_env())
+    p.interact()
+    print("Escaped interact")
+
+if __name__ == '__main__':
+    main()
diff --git a/third_party/pexpect/tests/list100.py b/third_party/pexpect/tests/list100.py
new file mode 100644
index 0000000..3b2b6ec
--- /dev/null
+++ b/third_party/pexpect/tests/list100.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+print(list(range(100)))
diff --git a/third_party/pexpect/tests/needs_kill.py b/third_party/pexpect/tests/needs_kill.py
new file mode 100755
index 0000000..810236bd
--- /dev/null
+++ b/third_party/pexpect/tests/needs_kill.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+"""This script can only be killed by SIGKILL."""
+import signal, time
+
+# Ignore interrupt, hangup and continue signals - only SIGKILL will work
+signal.signal(signal.SIGINT, signal.SIG_IGN)
+signal.signal(signal.SIGHUP, signal.SIG_IGN)
+signal.signal(signal.SIGCONT, signal.SIG_IGN)
+
+print('READY')
+while True:
+    time.sleep(10)
+    
\ No newline at end of file
diff --git a/third_party/pexpect/tests/pexpectTest.py b/third_party/pexpect/tests/pexpectTest.py
new file mode 100755
index 0000000..6839a2f
--- /dev/null
+++ b/third_party/pexpect/tests/pexpectTest.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import time
+import pexpect
+import sys
+
+def getProcessResults(cmd, timeLimit=20):
+  '''
+  executes 'cmd' as a child process and returns the child's output,
+  the duration of execution, and the process exit status. Aborts if
+  child process does not generate output for 'timeLimit' seconds.
+  '''
+  output = ""
+  startTime = time.time()
+  child = pexpect.spawn(cmd, timeout=10)
+  child.logfile = sys.stdout
+
+  while 1:
+    try:
+      # read_nonblocking will add to 'outout' one byte at a time
+      # newlines can show up as '\r\n' so we kill any '\r's which
+      # will mess up the formatting for the viewer
+      output += child.read_nonblocking(timeout=timeLimit).replace("\r","")
+    except pexpect.EOF as e:
+      print(str(e))
+      # process terminated normally
+      break
+    except pexpect.TIMEOUT as e:
+      print(str(e))
+      output += "\nProcess aborted by FlashTest after %s seconds.\n" % timeLimit
+      print(child.isalive())
+      child.kill(9)
+      break
+
+  endTime = time.time()
+  child.close(force=True)
+
+  duration = endTime - startTime
+  exitStatus = child.exitstatus
+
+  return (output, duration, exitStatus)
+
+cmd = "./ticker.py"
+
+result, duration, exitStatus = getProcessResults(cmd)
+
+print("result: %s" % result)
+print("duration: %s" % duration)
+print("exit-status: %s" % exitStatus)
+
diff --git a/third_party/pexpect/tests/platform_checks/CSIGNALTEST/test.c b/third_party/pexpect/tests/platform_checks/CSIGNALTEST/test.c
new file mode 100644
index 0000000..86bcc17
--- /dev/null
+++ b/third_party/pexpect/tests/platform_checks/CSIGNALTEST/test.c
@@ -0,0 +1,90 @@
+/* I built this with "gcc -lutil test.c -otest" */
+#include <sys/types.h>  /* include this before any other sys headers */
+#include <sys/wait.h>   /* header for waitpid() and various macros */
+#include <signal.h>     /* header for signal functions */
+#include <stdio.h>      /* header for fprintf() */
+#include <unistd.h>     /* header for fork() */
+#ifdef LINUX
+#include <pty.h>
+#else
+#include <util.h>	/* header for forkpty, compile with -lutil */
+#endif
+
+void sig_chld(int);  /* prototype for our SIGCHLD handler */
+
+int main() 
+{
+    struct sigaction act;
+    int pid;
+    int fdm;
+    char slave_name [20];
+
+
+    /* Assign sig_chld as our SIGCHLD handler.
+       We don't want to block any other signals in this example 
+       We're only interested in children that have terminated, not ones
+       which have been stopped (eg user pressing control-Z at terminal).
+       Finally, make these values effective. If we were writing a real 
+       application, we would save the old value instead of passing NULL.
+     */
+    act.sa_handler = sig_chld;
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = SA_NOCLDSTOP;
+    if (sigaction(SIGCHLD, &act, NULL) < 0) 
+    {
+        fprintf(stderr, "sigaction failed\n");
+        return 1;
+    }
+
+    /* Do the Fork thing. 
+    */
+    pid = forkpty (&fdm, slave_name, NULL, NULL);
+    /* pid = fork(); */
+
+    switch (pid)
+    {
+	    case -1:
+		fprintf(stderr, "fork failed\n");
+		return 1;
+	    break;
+
+	    case 0: /* Child process. */     
+		printf ("This child output will cause trouble.\n");
+		_exit(7);
+	    break;
+
+	    default: /* Parent process. */
+		sleep(1);
+		printf ("Child pid: %d\n", pid); 
+		sleep(10);  /* let child finish -- crappy way to avoid race. */
+	    break;
+    }
+
+    return 0;
+}
+ 
+void sig_chld(int signo) 
+{
+    int status, wpid, child_val;
+
+    printf ("In sig_chld signal handler.\n");
+
+    /* Wait for any child without blocking */
+    wpid = waitpid (-1, & status, WNOHANG);
+    printf ("\tWaitpid found status for pid: %d\n", wpid);
+    if (wpid < 0)
+    {
+        fprintf(stderr, "\twaitpid failed\n");
+        return;
+    }
+    printf("\tWaitpid status: %d\n", status);
+
+    if (WIFEXITED(status)) /* did child exit normally? */
+    {
+        child_val = WEXITSTATUS(status); 
+        printf("\tchild exited normally with status %d\n", child_val);
+    }
+    printf ("End of sig_chld.\n");
+}
+
+
diff --git a/third_party/pexpect/tests/platform_checks/README b/third_party/pexpect/tests/platform_checks/README
new file mode 100644
index 0000000..d50f94c
--- /dev/null
+++ b/third_party/pexpect/tests/platform_checks/README
@@ -0,0 +1,2 @@
+These scripts are for checking how the underlying system behaves, not for
+testing Pexpect itself.
\ No newline at end of file
diff --git a/third_party/pexpect/tests/platform_checks/check.py b/third_party/pexpect/tests/platform_checks/check.py
new file mode 100755
index 0000000..b41755a
--- /dev/null
+++ b/third_party/pexpect/tests/platform_checks/check.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+import signal
+import os
+import time
+import pty
+
+def signal_handler (signum, frame):
+    print 'Signal handler called with signal:', signum
+    print 'signal.SIGCHLD=', signal.SIGKILL
+
+# First thing we do is set up a handler for SIGCHLD.
+signal.signal (signal.SIGCHLD, signal.SIG_IGN)
+
+print 'PART 1 -- Test signal handling with empty pipe.'
+# Create a child process for us to kill.
+try:
+    pid, fd = pty.fork()
+except Exception as e:
+    print str(e)
+
+if pid == 0:
+#    os.write (sys.stdout.fileno(), 'This is a test.\n This is a test.')
+    time.sleep(10000)
+
+print 'Sending SIGKILL to child pid:', pid
+os.kill (pid, signal.SIGKILL)
+
+# SIGCHLD should interrupt sleep.
+# Note that this is a race.
+# It is possible that the signal handler will get called
+# before we try to sleep, but this has not happened yet.
+# But in that case we can only tell by order of printed output.
+print 'Entering sleep...'
+try:
+    time.sleep(10)
+except:
+    print 'sleep was interrupted by signal.'
+
+# Just for fun let's see if the process is alive.
+try:
+    os.kill(pid, 0)
+    print 'Child is alive. This is ambiguous because it may be a Zombie.'
+except OSError as e:
+    print 'Child appears to be dead.'
+
+print 'PART 2 -- Test signal handling with full pipe.'
+# Create a child process for us to kill.
+try:
+    pid, fd = pty.fork()
+except Exception as e:
+    print str(e)
+
+if pid == 0:
+    os.write (sys.stdout.fileno(), 'This is a test.\n This is a test.')
+    time.sleep(10000)
+
+print 'Sending SIGKILL to child pid:', pid
+os.kill (pid, signal.SIGKILL)
+
+# SIGCHLD should interrupt sleep.
+# Note that this is a race.
+# It is possible that the signal handler will get called
+# before we try to sleep, but this has not happened yet.
+# But in that case we can only tell by order of printed output.
+print 'Entering sleep...'
+try:
+    time.sleep(10)
+except:
+    print 'sleep was interrupted by signal.'
+
+# Just for fun let's see if the process is alive.
+try:
+    os.kill(pid, 0)
+    print 'Child is alive. This is ambiguous because it may be a Zombie.'
+except OSError as e:
+    print 'Child appears to be dead.'
+
diff --git a/third_party/pexpect/tests/platform_checks/check2.py b/third_party/pexpect/tests/platform_checks/check2.py
new file mode 100755
index 0000000..0a7d5f8
--- /dev/null
+++ b/third_party/pexpect/tests/platform_checks/check2.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+import signal
+import os
+import time
+
+def signal_handler (signum, frame):
+	print 'Signal handler called with signal:', signum
+	print 'signal.SIGCHLD=', signal.SIGKILL
+
+# Create a child process for us to kill.
+pid = os.fork()
+if pid == 0:
+	time.sleep(10000)
+
+#signal.signal (signal.SIGCHLD, signal.SIG_IGN)
+signal.signal (signal.SIGCHLD, signal_handler)
+
+print 'Sending SIGKILL to child pid:', pid
+os.kill (pid, signal.SIGKILL)
+
+# SIGCHLD should interrupt sleep.
+# Note that this is a race.
+# It is possible that the signal handler will get called
+# before we try to sleep, but this has not happened yet.
+# But in that case we can only tell by order of printed output.
+interrupted = 0
+try:
+	time.sleep(10)
+except:
+	print 'sleep was interrupted by signal.'
+	interrupted = 1
+
+if not interrupted:
+	print 'ERROR. Signal did not interrupt sleep.'
+else:
+	print 'Signal interrupted sleep. This is good.'
+
+# Let's see if the process is alive.
+try:
+	os.kill(pid, 0)
+	print 'Child is alive. This is ambiguous because it may be a Zombie.'
+except OSError as e:
+	print 'Child appears to be dead.'
+
diff --git a/third_party/pexpect/tests/platform_checks/check_control_terminal.py b/third_party/pexpect/tests/platform_checks/check_control_terminal.py
new file mode 100755
index 0000000..9598fd7
--- /dev/null
+++ b/third_party/pexpect/tests/platform_checks/check_control_terminal.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+
+import termios, fcntl, struct, os, sys
+
+def getwinsize():	
+	s = struct.pack("HHHH", 0, 0, 0, 0)
+	x = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, s)
+	rows, cols = struct.unpack("HHHH", x)[:2]
+	return rows, cols
+
+def setwinsize(r,c):
+	# Assume ws_xpixel and ws_ypixel are zero.
+	s = struct.pack("HHHH", r,c,0,0)
+	x = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCSWINSZ, s)
+print 'stdin tty:', os.ttyname(0)
+print 'stdout tty:', os.ttyname(1)
+print 'controlling terminal:', os.ctermid() 
+print 'winsize %d,%d' % getwinsize()
+print 'ENDTEST'
diff --git a/third_party/pexpect/tests/platform_checks/check_handler.py b/third_party/pexpect/tests/platform_checks/check_handler.py
new file mode 100755
index 0000000..c0633eb
--- /dev/null
+++ b/third_party/pexpect/tests/platform_checks/check_handler.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+import signal
+import os
+import time
+import pty
+import sys
+import fcntl
+import tty
+GLOBAL_SIGCHLD_RECEIVED = 0
+                                                                                 
+def nonblock (fd):                                                           
+	# if O_NDELAY is set read() returns 0 (ambiguous with EOF).
+	# if O_NONBLOCK is set read() returns -1 and sets errno to EAGAIN
+	original_flags = fcntl.fcntl (fd, fcntl.F_GETFL, 0)
+	flags = original_flags | os.O_NONBLOCK
+	fcntl.fcntl(fd, fcntl.F_SETFL, flags)
+	return original_flags
+
+def signal_handler (signum, frame):
+	print '<HANDLER>'
+	global GLOBAL_SIGCHLD_RECEIVED
+	status = os.waitpid (-1, os.WNOHANG)
+	if status[0] == 0:
+		print 'No process for waitpid:', status
+	else:
+		print 'Status:', status
+	print 'WIFEXITED(status):', os.WIFEXITED(status[1])
+	print 'WEXITSTATUS(status):', os.WEXITSTATUS(status[1]) 
+	GLOBAL_SIGCHLD_RECEIVED = 1
+
+def main ():
+	signal.signal (signal.SIGCHLD, signal_handler)
+	pid, fd = pty.fork()
+	if pid == 0:
+		os.write (sys.stdout.fileno(), 'This is a test.\nThis is a test.')
+		time.sleep(10000)
+	nonblock (fd)
+	tty.setraw(fd) #STDIN_FILENO)
+	print 'Sending SIGKILL to child pid:', pid
+	time.sleep(2)
+	os.kill (pid, signal.SIGKILL)
+
+	print 'Entering to sleep...'
+	try:
+		time.sleep(2)
+	except:
+		print 'Sleep interrupted'
+	try:
+		os.kill(pid, 0)
+		print '\tChild is alive. This is ambiguous because it may be a Zombie.'
+	except OSError as e:
+		print '\tChild appears to be dead.'
+#		print str(e)
+	print
+	print 'Reading from master fd:', os.read (fd, 1000)
+
+
+
+if __name__ == '__main__':
+	main ()
diff --git a/third_party/pexpect/tests/platform_checks/check_read.py b/third_party/pexpect/tests/platform_checks/check_read.py
new file mode 100755
index 0000000..9598aa7
--- /dev/null
+++ b/third_party/pexpect/tests/platform_checks/check_read.py
@@ -0,0 +1,35 @@
+import os
+
+filename = os.tmpnam()
+print 'filename:', filename
+
+fd_out = os.open(filename, os.O_CREAT | os.O_WRONLY)
+print 'fd_out:', fd_out
+os.write (fd_out, 'This is a test.\n')
+os.close(fd_out)
+print
+print 'testing read on good fd...'
+fd_in = os.open (filename, os.O_RDONLY)
+print 'fd_in:', fd_in
+while 1:
+	data_in = os.read(fd_in, 1)
+	print 'data_in:', data_in
+	if data_in == '':
+		print 'data_in was empty'
+		break #sys.exit(1)
+os.close(fd_in)
+print
+print
+print 'testing read on closed fd...'
+fd_in = os.open ('test_read.py', os.O_RDONLY)
+print 'fd_in:', fd_in
+while 1:
+	data_in = os.read(fd_in, 1)
+	print 'data_in:', data_in
+	if data_in == '':
+		print 'data_in was empty'
+		break
+os.close(fd_in)
+d = os.read(fd_in, 1) # fd_in should be closed now...
+if s == '':
+	print 'd is empty. good.'
diff --git a/third_party/pexpect/tests/platform_checks/check_signals.py b/third_party/pexpect/tests/platform_checks/check_signals.py
new file mode 100755
index 0000000..d45bc8a
--- /dev/null
+++ b/third_party/pexpect/tests/platform_checks/check_signals.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+import signal
+import os
+import time
+import pty
+import sys
+GLOBAL_SIGCHLD_RECEIVED = 0
+
+def signal_handler (signum, frame):
+    print '<HANDLER>'
+    global GLOBAL_SIGCHLD_RECEIVED
+    status = os.waitpid (-1, os.WNOHANG)
+    print 'WIFEXITED(status):', os.WIFEXITED(status)
+    print 'WEXITSTATUS(status):', os.WEXITSTATUS(status) 
+    GLOBAL_SIGCHLD_RECEIVED = 1
+
+def main ():
+#	sig_test ('SIG_IGN', 'ptyfork', 'yes')
+	sig_test ('handler', 'ptyfork', 'yes')
+#	sig_test ('SIG_IGN', 'ptyfork', 'no')
+#	sig_test ('handler', 'ptyfork', 'no')
+#	sig_test ('SIG_IGN', 'osfork', 'yes')
+#	sig_test ('handler', 'osfork', 'yes')
+#	sig_test ('SIG_IGN', 'osfork', 'no')
+#	sig_test ('handler', 'osfork', 'no')
+
+def sig_test (sig_handler_type, fork_type, child_output):
+	print 'Testing with:'
+	print '\tsig_handler_type:', sig_handler_type
+	print '\tfork_type:', fork_type
+	print '\tchild_output:', child_output
+
+	if sig_handler_type == 'SIG_IGN':
+		signal.signal (signal.SIGCHLD, signal.SIG_IGN)
+	else:
+		signal.signal (signal.SIGCHLD, signal_handler)
+	pid = -1
+	fd = -1
+	if fork_type == 'ptyfork':
+		pid, fd = pty.fork()
+	else:
+		pid = os.fork()
+
+	if pid == 0:
+		if child_output == 'yes':
+			os.write (sys.stdout.fileno(), 'This is a test.\nThis is a test.')
+		time.sleep(10000)
+
+	#print 'Sending SIGKILL to child pid:', pid
+	time.sleep(2)
+	os.kill (pid, signal.SIGKILL)
+
+	#print 'Entering to sleep...'
+	try:
+		time.sleep(2)
+	except:
+		pass
+	try:
+		os.kill(pid, 0)
+		print '\tChild is alive. This is ambiguous because it may be a Zombie.'
+	except OSError as e:
+		print '\tChild appears to be dead.'
+#		print str(e)
+	print
+
+if __name__ == '__main__':
+	main ()
diff --git a/third_party/pexpect/tests/qa.py b/third_party/pexpect/tests/qa.py
new file mode 100755
index 0000000..f50e3ed
--- /dev/null
+++ b/third_party/pexpect/tests/qa.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import commands
+import signal
+
+signal.signal(signal.SIGCHLD, signal.SIG_IGN)
+print(commands.getoutput('/bin/ls -l'))
+
diff --git a/third_party/pexpect/tests/sigwinch_report.py b/third_party/pexpect/tests/sigwinch_report.py
new file mode 100755
index 0000000..626d424
--- /dev/null
+++ b/third_party/pexpect/tests/sigwinch_report.py
@@ -0,0 +1,49 @@
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from  __future__ import print_function
+
+import signal, time, struct, fcntl, termios, sys
+
+def getwinsize():
+    '''This returns the window size of the child tty.
+    The return value is a tuple of (rows, cols).
+    '''
+    if 'TIOCGWINSZ' in dir(termios):
+        TIOCGWINSZ = termios.TIOCGWINSZ
+    else:
+        TIOCGWINSZ = 1074295912 # Assume
+    s = struct.pack('HHHH', 0, 0, 0, 0)
+    x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s)
+    return struct.unpack('HHHH', x)[0:2]
+
+def handler(signum, frame):
+    print('signal')
+    sys.stdout.flush()
+    print('SIGWINCH:', getwinsize ())
+    sys.stdout.flush()
+
+print("setting handler for SIGWINCH")
+signal.signal(signal.SIGWINCH, handler)
+print("READY")
+
+while 1:
+    sys.stdout.flush()
+    time.sleep(1)
+
diff --git a/third_party/pexpect/tests/sleep_for.py b/third_party/pexpect/tests/sleep_for.py
new file mode 100755
index 0000000..9027105
--- /dev/null
+++ b/third_party/pexpect/tests/sleep_for.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+from  __future__ import print_function
+
+import time
+import sys
+
+def main():
+    """
+        This script sleeps for the number of seconds (float) specified by the
+        command line argument.
+    """
+    if len(sys.argv) < 2:
+        print("Usage: %s seconds_to_sleep" % (sys.argv[0],))
+        sys.exit(1)
+    timeout = float(sys.argv[1])
+    print("READY")
+    time.sleep(timeout)
+    print("END")
+
+if __name__ == '__main__':
+    main()
diff --git a/third_party/pexpect/tests/swapcase_echo.py b/third_party/pexpect/tests/swapcase_echo.py
new file mode 100755
index 0000000..aaac442
--- /dev/null
+++ b/third_party/pexpect/tests/swapcase_echo.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import sys, time
+while True:
+    x = raw_input ()
+    time.sleep(1) # without this delay the test would fail about 75% of the time. Why?
+    print(x.swapcase())
+    sys.stdout.flush()
diff --git a/third_party/pexpect/tests/test_FSM.py b/third_party/pexpect/tests/test_FSM.py
new file mode 100644
index 0000000..3425fd2
--- /dev/null
+++ b/third_party/pexpect/tests/test_FSM.py
@@ -0,0 +1,34 @@
+import io
+import sys
+import unittest
+try:
+    import builtins
+except ImportError:
+    import __builtin__ as builtins
+
+PY3 = (sys.version_info[0] >= 3)
+input_name = 'input' if PY3 else 'raw_input'
+
+from pexpect import FSM
+
+class FSMTestCase(unittest.TestCase):
+    def test_run_fsm(self):
+        def _input(prompt):
+            return "167 3 2 2 * * * 1 - ="
+        orig_input = getattr(builtins, input_name)
+        orig_stdout = sys.stdout
+        setattr(builtins, input_name, _input)
+        sys.stdout = sio = (io.StringIO if PY3 else io.BytesIO)()
+        
+        try:
+            FSM.main()
+        finally:
+            setattr(builtins, input_name, orig_input)
+            sys.stdout = orig_stdout
+        
+        printed = sio.getvalue()
+        assert '2003' in printed, printed
+        
+        
+if __name__ == '__main__':
+    unittest.main()
\ No newline at end of file
diff --git a/third_party/pexpect/tests/test_ansi.py b/third_party/pexpect/tests/test_ansi.py
new file mode 100755
index 0000000..a9d445e
--- /dev/null
+++ b/third_party/pexpect/tests/test_ansi.py
@@ -0,0 +1,228 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from pexpect import ANSI
+import unittest
+from . import PexpectTestCase
+import sys
+
+PY3 = (sys.version_info[0] >= 3)
+
+write_target = 'I\'ve got a ferret sticking up my nose.                           \n' +\
+'(He\'s got a ferret sticking up his nose.)                        \n' +\
+'How it got there I can\'t tell                                    \n' +\
+'But now it\'s there it hurts like hell                            \n' +\
+'And what is more it radically affects my sense of smell.         \n' +\
+'(His sense of smell.)                                            '
+
+write_text = 'I\'ve got a ferret sticking up my nose.\n' + \
+'(He\'s got a ferret sticking up his nose.)\n' + \
+'How it got there I can\'t tell\n' + \
+'But now it\'s there it hurts like hell\n' + \
+'And what is more it radically affects my sense of smell.\n' + \
+'(His sense of smell.)\n' + \
+'I can see a bare-bottomed mandril.\n' + \
+'(Slyly eyeing his other nostril.)\n' + \
+'If it jumps inside there too I really don\'t know what to do\n' + \
+'I\'ll be the proud posessor of a kind of nasal zoo.\n' + \
+'(A nasal zoo.)\n' + \
+'I\'ve got a ferret sticking up my nose.\n' + \
+'(And what is worst of all it constantly explodes.)\n' + \
+'"Ferrets don\'t explode," you say\n' + \
+'But it happened nine times yesterday\n' + \
+'And I should know for each time I was standing in the way.\n' + \
+'I\'ve got a ferret sticking up my nose.\n' + \
+'(He\'s got a ferret sticking up his nose.)\n' + \
+'How it got there I can\'t tell\n' + \
+'But now it\'s there it hurts like hell\n' + \
+'And what is more it radically affects my sense of smell.\n' + \
+'(His sense of smell.)'
+
+tetris_target='                           XX            XXXX    XX                             \n' +\
+'                           XXXXXX    XXXXXXXX    XX                             \n' +\
+'                           XXXXXX    XXXXXXXX    XX                             \n' +\
+'                           XX  XX    XX  XXXX    XX                             \n' +\
+'                           XXXXXX  XXXX  XXXX    XX                             \n' +\
+'                           XXXXXXXXXX    XXXX    XX                             \n' +\
+'                           XX  XXXXXX      XX    XX                             \n' +\
+'                           XXXXXX          XX    XX                             \n' +\
+'                           XXXX    XXXXXX  XX    XX                             \n' +\
+'                           XXXXXX    XXXX  XX    XX                             \n' +\
+'                           XX  XX    XXXX  XX    XX                             \n' +\
+'                           XX  XX      XX  XX    XX                             \n' +\
+'                           XX  XX    XXXX  XXXX  XX                             \n' +\
+'                           XXXXXXXX  XXXX  XXXX  XX                             \n' +\
+'                           XXXXXXXXXXXXXX  XXXXXXXX                             \n' +\
+'                           XX    XXXXXXXX  XX    XX                             \n' +\
+'                           XXXXXXXXXXXXXX  XX    XX                             \n' +\
+'                           XX  XXXX    XXXXXX    XX                             \n' +\
+'                           XXXXXX          XXXXXXXX                             \n' +\
+'                           XXXXXXXXXX      XX    XX                             \n' +\
+'                           XXXXXXXXXXXXXXXXXXXXXXXX                             \n' +\
+'                                                                                \n' +\
+'  J->LEFT  K->ROTATE  L->RIGHT  SPACE->DROP  P->PAUSE  Q->QUIT                  \n' +\
+'                                                                                '
+
+torture_target='+--------------------------------------------------------------------------------+\n' +\
+'|a`opqrs`      This is the       `srqpo`a                                        |\n' +\
+'|VT100 series Torture Test Demonstration.                                        |\n' +\
+'|VT100 series Torture Test Demonstration.                                        |\n' +\
+'|This is a normal line __________________________________________________y_      |\n' +\
+'|This is a bold line (normal unless the Advanced Video Option is installed)      |\n' +\
+'|This line is underlined _ "       "       "       "       "       "    _y_      |\n' +\
+'|This is a blinking line _ "       "       "       "       "       "    _y_      |\n' +\
+'|This is inverse video _ (underlined if no AVO and cursor is underline) _y_      |\n' +\
+'|Normal gjpqy Underline   Blink   Underline+Blink gjpqy                          |\n' +\
+'|Bold   gjpqy Underline   Blink   Underline+Blink gjpqy                          |\n' +\
+'|Inverse      Underline   Blink   Underline+Blink                                |\n' +\
+'|Bold+Inverse Underline   Blink   Underline+Blink                                |\n' +\
+'|This is double width                                                            |\n' +\
+'|This is double height                                                           |\n' +\
+'|This is double height                                                           |\n' +\
+'|_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy                                        |\n' +\
+'|_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy                                        |\n' +\
+'|_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy                                        |\n' +\
+'|`abcdefghijklmnopqrstuvwxyz{|}~ lqwqk                                           |\n' +\
+'|`abcdefghijklmnopqrstuvwxyz{|}~ tqnqu                                           |\n' +\
+'|`abcdefghijklmnopqrstuvwxyz{|}~ tqnqu                                           |\n' +\
+'|`abcdefghijklmnopqrstuvwxyz{|}~ mqvqj                                           |\n' +\
+'|   This test created by Joe Smith, 8-May-85                                     |\n' +\
+'|                                                                                |\n' +\
+'+--------------------------------------------------------------------------------+\n'
+
+class ansiTestCase (PexpectTestCase.PexpectTestCase):
+    def test_write (self):
+        s = ANSI.ANSI (6,65)
+        s.fill('.')
+        s.cursor_home()
+        for c in write_text:
+            s.write (c)
+        assert str(s) == write_target
+
+    def test_torturet (self):
+        s = ANSI.ANSI (24,80)
+        with open('torturet.vt') as f:
+            sample_text = f.read()
+        for c in sample_text:
+            s.process (c)
+        assert s.pretty() == torture_target, 'processed: \n' + s.pretty() + '\nexpected:\n' + torture_target
+
+    def test_tetris (self):
+        s = ANSI.ANSI (24,80)
+        with open('tetris.data') as f:
+            tetris_text = f.read()
+        for c in tetris_text:
+            s.process (c)
+        assert str(s) == tetris_target
+
+    def test_lines(self):
+        s = ANSI.ANSI(5, 5)
+        s.write('a'*6 + '\n')
+        s.write('ab\bcd\n')
+        s.write('ab\rcd\n')
+        assert str(s) == ('aaaaa\n'
+                          'a    \n'
+                          'acd  \n'
+                          'cd   \n'
+                          '     ')
+
+    def test_number_x(self):
+        """Test the FSM state used to handle more than 2 numeric parameters."""
+        class TestANSI(ANSI.ANSI):
+            captured_memory = None
+            def do_sgr(self, fsm):
+                assert self.captured_memory is None
+                self.captured_memory = fsm.memory
+
+        s = TestANSI(1, 20)
+        s.write('\x1b[0;1;32;45mtest')
+        assert str(s) == ('test                ')
+        assert s.captured_memory is not None
+        assert s.captured_memory == [s, '0', '1', '32', '45']
+
+    def test_fsm_memory(self):
+        """Test the FSM stack/memory does not have numbers left on it
+        after some sequences with numbers are passed in."""
+        s = ANSI.ANSI(1, 20)
+        s.write('\x1b[0;1;2;3m\x1b[4;5;6;7q\x1b[?8h\x1b[?9ltest')
+        assert str(s) == ('test                ')
+        assert s.state.memory == [s]
+
+    def test_utf8_bytes(self):
+        """Test that when bytes are passed in containing UTF-8 encoded
+        characters, where the encoding of each character consists of
+        multiple bytes, the characters are correctly decoded.
+        Incremental decoding is also tested."""
+        s = ANSI.ANSI(2, 10, encoding='utf-8')
+        # This is the UTF-8 encoding of the UCS character "HOURGLASS"
+        # followed by the UTF-8 encoding of the UCS character
+        # "KEYBOARD".  These characters can't be encoded in cp437 or
+        # latin-1.  The "KEYBOARD" character is split into two
+        # separate writes.
+        s.write(b'\xe2\x8c\x9b')
+        s.write(b'\xe2\x8c')
+        s.write(b'\xa8')
+        if PY3:
+            assert str(s) == u'\u231b\u2328        \n          '
+        else:
+            assert unicode(s) == u'\u231b\u2328        \n          '
+            assert str(s) == b'\xe2\x8c\x9b\xe2\x8c\xa8        \n          '
+        assert s.dump() == u'\u231b\u2328                  '
+        assert s.pretty() == u'+----------+\n|\u231b\u2328        |\n|          |\n+----------+\n'
+        assert s.get_abs(1, 1) == u'\u231b'
+        assert s.get_region(1, 1, 1, 5) == [u'\u231b\u2328   ']
+
+    def test_unicode(self):
+        """Test passing in of a unicode string."""
+        s = ANSI.ANSI(2, 10, encoding="utf-8")
+        s.write(u'\u231b\u2328')
+        if PY3:
+            assert str(s) == u'\u231b\u2328        \n          '
+        else:
+            assert unicode(s) == u'\u231b\u2328        \n          '
+            assert str(s) == b'\xe2\x8c\x9b\xe2\x8c\xa8        \n          '
+        assert s.dump() == u'\u231b\u2328                  '
+        assert s.pretty() == u'+----------+\n|\u231b\u2328        |\n|          |\n+----------+\n'
+        assert s.get_abs(1, 1) == u'\u231b'
+        assert s.get_region(1, 1, 1, 5) == [u'\u231b\u2328   ']
+
+    def test_decode_error(self):
+        """Test that default handling of decode errors replaces the
+        invalid characters."""
+        s = ANSI.ANSI(2, 10, encoding="ascii")
+        s.write(b'\xff') # a non-ASCII character
+        # In unicode, the non-ASCII character is replaced with
+        # REPLACEMENT CHARACTER.
+        if PY3:
+            assert str(s) == u'\ufffd         \n          '
+        else:
+            assert unicode(s) == u'\ufffd         \n          '
+            assert str(s) == b'?         \n          '
+        assert s.dump() == u'\ufffd                   '
+        assert s.pretty() == u'+----------+\n|\ufffd         |\n|          |\n+----------+\n'
+        assert s.get_abs(1, 1) == u'\ufffd'
+        assert s.get_region(1, 1, 1, 5) == [u'\ufffd    ']
+
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(ansiTestCase,'test')
+
diff --git a/third_party/pexpect/tests/test_async.py b/third_party/pexpect/tests/test_async.py
new file mode 100644
index 0000000..ce75572
--- /dev/null
+++ b/third_party/pexpect/tests/test_async.py
@@ -0,0 +1,51 @@
+try:
+    import asyncio
+except ImportError:
+    asyncio = None
+
+import sys
+import unittest
+
+import pexpect
+from .PexpectTestCase import PexpectTestCase
+
+def run(coro):
+    return asyncio.get_event_loop().run_until_complete(coro)
+
+ at unittest.skipIf(asyncio is None, "Requires asyncio")
+class AsyncTests(PexpectTestCase):
+    def test_simple_expect(self):
+        p = pexpect.spawn('cat')
+        p.sendline('Hello asyncio')
+        coro = p.expect(['Hello', pexpect.EOF] , async=True)
+        assert run(coro) == 0
+        print('Done')
+
+    def test_timeout(self):
+        p = pexpect.spawn('cat')
+        coro = p.expect('foo', timeout=1, async=True)
+        with self.assertRaises(pexpect.TIMEOUT):
+            run(coro)
+        
+        p = pexpect.spawn('cat')
+        coro = p.expect(['foo', pexpect.TIMEOUT], timeout=1, async=True)
+        assert run(coro) == 1
+
+    def test_eof(self):
+        p = pexpect.spawn('cat')
+        p.sendline('Hi')
+        coro = p.expect(pexpect.EOF, async=True)
+        p.sendeof()
+        assert run(coro) == 0
+
+        p = pexpect.spawn('cat')
+        p.sendeof()
+        coro = p.expect('Blah', async=True)
+        with self.assertRaises(pexpect.EOF):
+            run(coro)
+    
+    def test_expect_exact(self):
+        p = pexpect.spawn('%s list100.py' % sys.executable)
+        assert run(p.expect_exact(b'5', async=True)) == 0
+        assert run(p.expect_exact(['wpeok', b'11'], async=True)) == 1
+        assert run(p.expect_exact([b'foo', pexpect.EOF], async=True)) == 1
diff --git a/third_party/pexpect/tests/test_command_list_split.py b/third_party/pexpect/tests/test_command_list_split.py
new file mode 100755
index 0000000..370f46e
--- /dev/null
+++ b/third_party/pexpect/tests/test_command_list_split.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+from . import PexpectTestCase
+
+class SplitCommandLineTestCase(PexpectTestCase.PexpectTestCase):
+    def testSplitSizes(self):
+        assert len(pexpect.split_command_line(r'')) == 0
+        assert len(pexpect.split_command_line(r'one')) == 1
+        assert len(pexpect.split_command_line(r'one two')) == 2
+        assert len(pexpect.split_command_line(r'one  two')) == 2
+        assert len(pexpect.split_command_line(r'one   two')) == 2
+        assert len(pexpect.split_command_line(r'one\ one')) == 1
+        assert len(pexpect.split_command_line('\'one one\'')) == 1
+        assert len(pexpect.split_command_line(r'one\"one')) == 1
+        assert len(pexpect.split_command_line(r'This\' is a\'\ test')) == 3
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(SplitCommandLineTestCase,'test')
diff --git a/third_party/pexpect/tests/test_constructor.py b/third_party/pexpect/tests/test_constructor.py
new file mode 100755
index 0000000..98c473a
--- /dev/null
+++ b/third_party/pexpect/tests/test_constructor.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+from . import PexpectTestCase
+
+class TestCaseConstructor(PexpectTestCase.PexpectTestCase):
+    def test_constructor (self):
+        '''This tests that the constructor will work and give
+        the same results for different styles of invoking __init__().
+        This assumes that the root directory / is static during the test.
+        '''
+        p1 = pexpect.spawn('uname -m -n -p -r -s -v')
+        p2 = pexpect.spawn('uname', ['-m', '-n', '-p', '-r', '-s', '-v'])
+        p1.expect(pexpect.EOF)
+        p2.expect(pexpect.EOF)
+        assert p1.before == p2.before
+
+    def test_named_parameters (self):
+        '''This tests that named parameters work.
+        '''
+        p = pexpect.spawn ('/bin/ls',timeout=10)
+        p = pexpect.spawn (timeout=10, command='/bin/ls')
+        p = pexpect.spawn (args=[], command='/bin/ls')
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(TestCaseConstructor,'test')
+
diff --git a/third_party/pexpect/tests/test_ctrl_chars.py b/third_party/pexpect/tests/test_ctrl_chars.py
new file mode 100755
index 0000000..10d03db
--- /dev/null
+++ b/third_party/pexpect/tests/test_ctrl_chars.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from __future__ import print_function
+
+import pexpect
+import unittest
+from . import PexpectTestCase
+import time
+import sys
+
+from ptyprocess import ptyprocess
+ptyprocess._make_eof_intr()
+
+if sys.version_info[0] >= 3:
+    def byte(i):
+        return bytes([i])
+else:
+    byte = chr
+
+class TestCtrlChars(PexpectTestCase.PexpectTestCase):
+
+    def test_control_chars(self):
+        '''This tests that we can send all 256 8-bit characters to a child
+        process.'''
+        child = pexpect.spawn('python getch.py', echo=False, timeout=5)
+        child.expect('READY')
+        for i in range(1, 256):
+            child.send(byte(i))
+            child.expect ('%d<STOP>' % (i,))
+
+        # This needs to be last, as getch.py exits on \x00
+        child.send(byte(0))
+        child.expect('0<STOP>')
+        child.expect(pexpect.EOF)
+        assert not child.isalive()
+        assert child.exitstatus == 0
+
+    def test_sendintr (self):
+        child = pexpect.spawn('python getch.py', echo=False, timeout=5)
+        child.expect('READY')
+        child.sendintr()
+        child.expect(str(ord(ptyprocess._INTR)) + '<STOP>')
+
+        child.send(byte(0))
+        child.expect('0<STOP>')
+        child.expect(pexpect.EOF)
+        assert not child.isalive()
+        assert child.exitstatus == 0
+
+    def test_sendeof(self):
+        child = pexpect.spawn('python getch.py', echo=False, timeout=5)
+        child.expect('READY')
+        child.sendeof()
+        child.expect(str(ord(ptyprocess._EOF)) + '<STOP>')
+
+        child.send(byte(0))
+        child.expect('0<STOP>')
+        child.expect(pexpect.EOF)
+        assert not child.isalive()
+        assert child.exitstatus == 0
+
+    def test_bad_sendcontrol_chars (self):
+        '''This tests that sendcontrol will return 0 for an unknown char. '''
+
+        child = pexpect.spawn('python getch.py', echo=False, timeout=5)
+        child.expect('READY')
+        assert 0 == child.sendcontrol('1')
+
+    def test_sendcontrol(self):
+        '''This tests that we can send all special control codes by name.
+        '''
+        child = pexpect.spawn('python getch.py', echo=False, timeout=5)
+        child.expect('READY')
+        for ctrl in 'abcdefghijklmnopqrstuvwxyz':
+            assert child.sendcontrol(ctrl) == 1
+            val = ord(ctrl) - ord('a') + 1
+            child.expect_exact(str(val)+'<STOP>')
+
+        # escape character
+        assert child.sendcontrol('[') == 1
+        child.expect('27<STOP>')
+        assert child.sendcontrol('\\') == 1
+        child.expect('28<STOP>')
+        # telnet escape character
+        assert child.sendcontrol(']') == 1
+        child.expect('29<STOP>')
+        assert child.sendcontrol('^') == 1
+        child.expect('30<STOP>')
+        # irc protocol uses this to underline ...
+        assert child.sendcontrol('_') == 1
+        child.expect('31<STOP>')
+        # the real "backspace is delete"
+        assert child.sendcontrol('?') == 1
+        child.expect('127<STOP>')
+
+        # NUL, same as ctrl + ' '
+        assert child.sendcontrol('@') == 1
+        child.expect('0<STOP>')
+        child.expect(pexpect.EOF)
+        assert not child.isalive()
+        assert child.exitstatus == 0
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(TestCtrlChars,'test')
+
diff --git a/third_party/pexpect/tests/test_destructor.py b/third_party/pexpect/tests/test_destructor.py
new file mode 100755
index 0000000..d27b6f6
--- /dev/null
+++ b/third_party/pexpect/tests/test_destructor.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+from . import PexpectTestCase
+import gc
+import platform
+import time
+
+class TestCaseDestructor(PexpectTestCase.PexpectTestCase):
+    def test_destructor (self):
+        if platform.python_implementation() != 'CPython':
+            # Details of garbage collection are different on other implementations
+            return 'SKIP'
+        gc.collect()
+        time.sleep(3)
+        p1 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+        p2 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+        p3 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+        p4 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+        fd_t1 = (p1.child_fd,p2.child_fd,p3.child_fd,p4.child_fd)
+        p1.expect(pexpect.EOF)
+        p2.expect(pexpect.EOF)
+        p3.expect(pexpect.EOF)
+        p4.expect(pexpect.EOF)
+        p1.kill(9)
+        p2.kill(9)
+        p3.kill(9)
+        p4.kill(9)
+        p1 = None
+        p2 = None
+        p3 = None
+        p4 = None
+        gc.collect()
+        time.sleep(3) # Some platforms are slow at gc... Solaris!
+
+        p1 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+        p2 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+        p3 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+        p4 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+        fd_t2 = (p1.child_fd,p2.child_fd,p3.child_fd,p4.child_fd)
+        p1.kill(9)
+        p2.kill(9)
+        p3.kill(9)
+        p4.kill(9)
+        del (p1)
+        del (p2)
+        del (p3)
+        del (p4)
+        gc.collect()
+        time.sleep(3)
+
+        p1 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+        p2 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+        p3 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+        p4 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+        fd_t3 = (p1.child_fd,p2.child_fd,p3.child_fd,p4.child_fd)
+
+        assert (fd_t1 == fd_t2 == fd_t3), "pty file descriptors not properly garbage collected (fd_t1,fd_t2,fd_t3)=(%s,%s,%s)" % (str(fd_t1),str(fd_t2),str(fd_t3))
+
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(TestCaseDestructor,'test')
+
diff --git a/third_party/pexpect/tests/test_dotall.py b/third_party/pexpect/tests/test_dotall.py
new file mode 100755
index 0000000..68aef3f
--- /dev/null
+++ b/third_party/pexpect/tests/test_dotall.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import re
+from . import PexpectTestCase
+
+testdata = 'BEGIN\nHello world\nEND'
+class TestCaseDotall(PexpectTestCase.PexpectTestCase):
+    def test_dotall (self):
+        p = pexpect.spawn('echo "%s"' % testdata)
+        i = p.expect ([b'BEGIN(.*)END', pexpect.EOF])
+        assert i==0, 'DOTALL does not seem to be working.'
+
+    def test_precompiled (self):
+        p = pexpect.spawn('echo "%s"' % testdata)
+        pat = re.compile(b'BEGIN(.*)END') # This overrides the default DOTALL.
+        i = p.expect ([pat, pexpect.EOF])
+        assert i==1, 'Precompiled pattern to override DOTALL does not seem to be working.'
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(TestCaseDotall,'test')
+
diff --git a/third_party/pexpect/tests/test_expect.py b/third_party/pexpect/tests/test_expect.py
new file mode 100755
index 0000000..3f4c9d8
--- /dev/null
+++ b/third_party/pexpect/tests/test_expect.py
@@ -0,0 +1,583 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import multiprocessing
+import unittest
+import subprocess
+import time
+import signal
+import sys
+import os
+
+import pexpect
+from . import PexpectTestCase
+from .utils import no_coverage_env
+
+# Many of these test cases blindly assume that sequential directory
+# listings of the /bin directory will yield the same results.
+# This may not be true, but seems adequate for testing now.
+# I should fix this at some point.
+
+FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)])
+def hex_dump(src, length=16):
+    result=[]
+    for i in xrange(0, len(src), length):
+       s = src[i:i+length]
+       hexa = ' '.join(["%02X"%ord(x) for x in s])
+       printable = s.translate(FILTER)
+       result.append("%04X   %-*s   %s\n" % (i, length*3, hexa, printable))
+    return ''.join(result)
+
+def hex_diff(left, right):
+        diff = ['< %s\n> %s' % (_left, _right,) for _left, _right in zip(
+            hex_dump(left).splitlines(), hex_dump(right).splitlines())
+            if _left != _right]
+        return '\n' + '\n'.join(diff,)
+
+
+class ExpectTestCase (PexpectTestCase.PexpectTestCase):
+
+    def test_expect_basic (self):
+        p = pexpect.spawn('cat', echo=False, timeout=5)
+        p.sendline (b'Hello')
+        p.sendline (b'there')
+        p.sendline (b'Mr. Python')
+        p.expect (b'Hello')
+        p.expect (b'there')
+        p.expect (b'Mr. Python')
+        p.sendeof ()
+        p.expect (pexpect.EOF)
+
+    def test_expect_exact_basic (self):
+        p = pexpect.spawn('cat', echo=False, timeout=5)
+        p.sendline (b'Hello')
+        p.sendline (b'there')
+        p.sendline (b'Mr. Python')
+        p.expect_exact (b'Hello')
+        p.expect_exact (b'there')
+        p.expect_exact (b'Mr. Python')
+        p.sendeof ()
+        p.expect_exact (pexpect.EOF)
+
+    def test_expect_ignore_case(self):
+        '''This test that the ignorecase flag will match patterns
+        even if case is different using the regex (?i) directive.
+        '''
+        p = pexpect.spawn('cat', echo=False, timeout=5)
+        p.sendline (b'HELLO')
+        p.sendline (b'there')
+        p.expect (b'(?i)hello')
+        p.expect (b'(?i)THERE')
+        p.sendeof ()
+        p.expect (pexpect.EOF)
+
+    def test_expect_ignore_case_flag(self):
+        '''This test that the ignorecase flag will match patterns
+        even if case is different using the ignorecase flag.
+        '''
+        p = pexpect.spawn('cat', echo=False, timeout=5)
+        p.ignorecase = True
+        p.sendline (b'HELLO')
+        p.sendline (b'there')
+        p.expect (b'hello')
+        p.expect (b'THERE')
+        p.sendeof ()
+        p.expect (pexpect.EOF)
+
+    def test_expect_order (self):
+        '''This tests that patterns are matched in the same order as given in the pattern_list.
+
+        (Or does it?  Doesn't it also pass if expect() always chooses
+        (one of the) the leftmost matches in the input? -- grahn)
+        ... agreed! -jquast, the buffer ptr isn't forwarded on match, see first two test cases
+        '''
+        p = pexpect.spawn('cat', echo=False, timeout=5)
+        self._expect_order(p)
+
+    def test_expect_order_exact (self):
+        '''Like test_expect_order(), but using expect_exact().
+        '''
+        p = pexpect.spawn('cat', echo=False, timeout=5)
+        p.expect = p.expect_exact
+        self._expect_order(p)
+
+    def _expect_order (self, p):
+        p.sendline (b'1234')
+        p.sendline (b'abcd')
+        p.sendline (b'wxyz')
+        p.sendline (b'7890')
+        p.sendeof ()
+        index = p.expect ([
+            b'1234',
+            b'abcd',
+            b'wxyz',
+            pexpect.EOF,
+            b'7890' ])
+        assert index == 0, (index, p.before, p.after)
+        index = p.expect ([
+            b'54321',
+            pexpect.TIMEOUT,
+            b'1234',
+            b'abcd',
+            b'wxyz',
+            pexpect.EOF], timeout=5)
+        assert index == 3, (index, p.before, p.after)
+        index = p.expect ([
+            b'54321',
+            pexpect.TIMEOUT,
+            b'1234',
+            b'abcd',
+            b'wxyz',
+            pexpect.EOF], timeout=5)
+        assert index == 4, (index, p.before, p.after)
+        index = p.expect ([
+            pexpect.EOF,
+            b'abcd',
+            b'wxyz',
+            b'7890' ])
+        assert index == 3, (index, p.before, p.after)
+
+        index = p.expect ([
+            b'abcd',
+            b'wxyz',
+            b'7890',
+            pexpect.EOF])
+        assert index == 3, (index, p.before, p.after)
+
+    def test_expect_setecho_off(self):
+        '''This tests that echo may be toggled off.
+        '''
+        p = pexpect.spawn('cat', echo=True, timeout=5)
+        try:
+            self._expect_echo_toggle(p)
+        except IOError:
+            if sys.platform.lower().startswith('sunos'):
+                if hasattr(unittest, 'SkipTest'):
+                    raise unittest.SkipTest("Not supported on this platform.")
+                return 'skip'
+            raise
+
+    def test_expect_setecho_off_exact(self):
+        p = pexpect.spawn('cat', echo=True, timeout=5)
+        p.expect = p.expect_exact
+        try:
+            self._expect_echo_toggle(p)
+        except IOError:
+            if sys.platform.lower().startswith('sunos'):
+                if hasattr(unittest, 'SkipTest'):
+                    raise unittest.SkipTest("Not supported on this platform.")
+                return 'skip'
+            raise
+
+    def test_waitnoecho(self):
+        " Tests setecho(False) followed by waitnoecho() "
+        p = pexpect.spawn('cat', echo=False, timeout=5)
+        try:
+            p.setecho(False)
+            p.waitnoecho()
+        except IOError:
+            if sys.platform.lower().startswith('sunos'):
+                if hasattr(unittest, 'SkipTest'):
+                    raise unittest.SkipTest("Not supported on this platform.")
+                return 'skip'
+            raise
+
+    def test_waitnoecho_order(self):
+
+        ''' This tests that we can wait on a child process to set echo mode.
+        For example, this tests that we could wait for SSH to set ECHO False
+        when asking of a password. This makes use of an external script
+        echo_wait.py. '''
+
+        p1 = pexpect.spawn('%s echo_wait.py' % self.PYTHONBIN)
+        start = time.time()
+        try:
+            p1.waitnoecho(timeout=10)
+        except IOError:
+            if sys.platform.lower().startswith('sunos'):
+                if hasattr(unittest, 'SkipTest'):
+                    raise unittest.SkipTest("Not supported on this platform.")
+                return 'skip'
+            raise
+
+
+        end_time = time.time() - start
+        assert end_time < 10 and end_time > 2, "waitnoecho did not set ECHO off in the expected window of time."
+
+        # test that we actually timeout and return False if ECHO is never set off.
+        p1 = pexpect.spawn('cat')
+        start = time.time()
+        retval = p1.waitnoecho(timeout=4)
+        end_time = time.time() - start
+        assert end_time > 3, "waitnoecho should have waited longer than 2 seconds. retval should be False, retval=%d"%retval
+        assert retval==False, "retval should be False, retval=%d"%retval
+
+        # This one is mainly here to test default timeout for code coverage.
+        p1 = pexpect.spawn('%s echo_wait.py' % self.PYTHONBIN)
+        start = time.time()
+        p1.waitnoecho()
+        end_time = time.time() - start
+        assert end_time < 10, "waitnoecho did not set ECHO off in the expected window of time."
+
+    def test_expect_echo (self):
+        '''This tests that echo is on by default.
+        '''
+        p = pexpect.spawn('cat', echo=True, timeout=5)
+        self._expect_echo(p)
+
+    def test_expect_echo_exact (self):
+        '''Like test_expect_echo(), but using expect_exact().
+        '''
+        p = pexpect.spawn('cat', echo=True, timeout=5)
+        p.expect = p.expect_exact
+        self._expect_echo(p)
+
+    def _expect_echo (self, p):
+        p.sendline (b'1234') # Should see this twice (once from tty echo and again from cat).
+        index = p.expect ([
+            b'1234',
+            b'abcd',
+            b'wxyz',
+            pexpect.EOF,
+            pexpect.TIMEOUT])
+        assert index == 0, "index="+str(index)+"\n"+p.before
+        index = p.expect ([
+            b'1234',
+            b'abcd',
+            b'wxyz',
+            pexpect.EOF])
+        assert index == 0, "index="+str(index)
+
+    def _expect_echo_toggle(self, p):
+        p.sendline (b'1234') # Should see this twice (once from tty echo and again from cat).
+        index = p.expect ([
+            b'1234',
+            b'abcd',
+            b'wxyz',
+            pexpect.EOF,
+            pexpect.TIMEOUT])
+        assert index == 0, "index="+str(index)+"\n"+p.before
+        index = p.expect ([
+            b'1234',
+            b'abcd',
+            b'wxyz',
+            pexpect.EOF])
+        assert index == 0, "index="+str(index)
+        p.setecho(0) # Turn off tty echo
+        p.waitnoecho()
+        p.sendline (b'abcd') # Now, should only see this once.
+        p.sendline (b'wxyz') # Should also be only once.
+        index = p.expect ([
+            pexpect.EOF,
+            pexpect.TIMEOUT,
+            b'abcd',
+            b'wxyz',
+            b'1234'])
+        assert index == 2, "index="+str(index)
+        index = p.expect ([
+            pexpect.EOF,
+            b'abcd',
+            b'wxyz',
+            b'7890'])
+        assert index == 2, "index="+str(index)
+        p.setecho(1) # Turn on tty echo
+        p.sendline (b'7890') # Should see this twice.
+        index = p.expect ([pexpect.EOF,b'abcd',b'wxyz',b'7890'])
+        assert index == 3, "index="+str(index)
+        index = p.expect ([pexpect.EOF,b'abcd',b'wxyz',b'7890'])
+        assert index == 3, "index="+str(index)
+        p.sendeof()
+
+    def test_expect_index (self):
+        '''This tests that mixed list of regex strings, TIMEOUT, and EOF all
+        return the correct index when matched.
+        '''
+        p = pexpect.spawn('cat', echo=False, timeout=5)
+        self._expect_index(p)
+
+    def test_expect_index_exact (self):
+        '''Like test_expect_index(), but using expect_exact().
+        '''
+        p = pexpect.spawn('cat', echo=False, timeout=5)
+        p.expect = p.expect_exact
+        self._expect_index(p)
+
+    def _expect_index (self, p):
+        p.sendline (b'1234')
+        index = p.expect ([b'abcd',b'wxyz',b'1234',pexpect.EOF])
+        assert index == 2, "index="+str(index)
+        p.sendline (b'abcd')
+        index = p.expect ([pexpect.TIMEOUT,b'abcd',b'wxyz',b'1234',pexpect.EOF])
+        assert index == 1, "index="+str(index)+str(p)
+        p.sendline (b'wxyz')
+        index = p.expect ([b'54321',pexpect.TIMEOUT,b'abcd',b'wxyz',b'1234',pexpect.EOF])
+        assert index == 3, "index="+str(index) # Expect 'wxyz'
+        p.sendline (b'$*!@?')
+        index = p.expect ([b'54321',pexpect.TIMEOUT,b'abcd',b'wxyz',b'1234',pexpect.EOF],
+                          timeout=1)
+        assert index == 1, "index="+str(index) # Expect TIMEOUT
+        p.sendeof ()
+        index = p.expect ([b'54321',pexpect.TIMEOUT,b'abcd',b'wxyz',b'1234',pexpect.EOF])
+        assert index == 5, "index="+str(index) # Expect EOF
+
+    def test_expect (self):
+        the_old_way = subprocess.Popen(args=['ls', '-l', '/bin'],
+                stdout=subprocess.PIPE).communicate()[0].rstrip()
+        p = pexpect.spawn('ls -l /bin')
+        the_new_way = b''
+        while 1:
+            i = p.expect ([b'\n', pexpect.EOF])
+            the_new_way = the_new_way + p.before
+            if i == 1:
+                break
+        the_new_way = the_new_way.rstrip()
+        the_new_way = the_new_way.replace(b'\r\n', b'\n'
+                ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip()
+        the_old_way = the_old_way.replace(b'\r\n', b'\n'
+                ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip()
+        assert the_old_way == the_new_way, hex_diff(the_old_way, the_new_way)
+
+    def test_expect_exact (self):
+        the_old_way = subprocess.Popen(args=['ls', '-l', '/bin'],
+                stdout=subprocess.PIPE).communicate()[0].rstrip()
+        p = pexpect.spawn('ls -l /bin')
+        the_new_way = b''
+        while 1:
+            i = p.expect_exact ([b'\n', pexpect.EOF])
+            the_new_way = the_new_way + p.before
+            if i == 1:
+                break
+        the_new_way = the_new_way.replace(b'\r\n', b'\n'
+                ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip()
+        the_old_way = the_old_way.replace(b'\r\n', b'\n'
+                ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip()
+        assert the_old_way == the_new_way, hex_diff(the_old_way, the_new_way)
+        p = pexpect.spawn('echo hello.?world')
+        i = p.expect_exact(b'.?')
+        self.assertEqual(p.before, b'hello')
+        self.assertEqual(p.after, b'.?')
+
+    def test_expect_eof (self):
+        the_old_way = subprocess.Popen(args=['/bin/ls', '-l', '/bin'],
+                stdout=subprocess.PIPE).communicate()[0].rstrip()
+        p = pexpect.spawn('/bin/ls -l /bin')
+        p.expect(pexpect.EOF) # This basically tells it to read everything. Same as pexpect.run() function.
+        the_new_way = p.before
+        the_new_way = the_new_way.replace(b'\r\n', b'\n'
+                ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip()
+        the_old_way = the_old_way.replace(b'\r\n', b'\n'
+                ).replace(b'\r', b'\n').replace(b'\n\n', b'\n').rstrip()
+        assert the_old_way == the_new_way, hex_diff(the_old_way, the_new_way)
+
+    def test_expect_timeout (self):
+        p = pexpect.spawn('cat', timeout=5)
+        p.expect(pexpect.TIMEOUT) # This tells it to wait for timeout.
+        self.assertEqual(p.after, pexpect.TIMEOUT)
+
+    def test_unexpected_eof (self):
+        p = pexpect.spawn('ls -l /bin')
+        try:
+            p.expect('_Z_XY_XZ') # Probably never see this in ls output.
+        except pexpect.EOF:
+            pass
+        else:
+            self.fail ('Expected an EOF exception.')
+
+    def _before_after(self, p):
+        p.timeout = 5
+
+        p.expect(b'5')
+        self.assertEqual(p.after, b'5')
+        assert p.before.startswith(b'[0, 1, 2'), p.before
+
+        p.expect(b'50')
+        self.assertEqual(p.after, b'50')
+        assert p.before.startswith(b', 6, 7, 8'), p.before[:20]
+        assert p.before.endswith(b'48, 49, '), p.before[-20:]
+
+        p.expect(pexpect.EOF)
+        self.assertEqual(p.after, pexpect.EOF)
+        assert p.before.startswith(b', 51, 52'), p.before[:20]
+        assert p.before.endswith(b', 99]\r\n'), p.before[-20:]
+
+    def test_before_after(self):
+        '''This tests expect() for some simple before/after things.
+        '''
+        p = pexpect.spawn('%s -Wi list100.py' % self.PYTHONBIN, env=no_coverage_env())
+        self._before_after(p)
+
+    def test_before_after_exact(self):
+        '''This tests some simple before/after things, for
+        expect_exact(). (Grahn broke it at one point.)
+        '''
+        p = pexpect.spawn('%s -Wi list100.py' % self.PYTHONBIN, env=no_coverage_env())
+        # mangle the spawn so we test expect_exact() instead
+        p.expect = p.expect_exact
+        self._before_after(p)
+
+    def _ordering(self, p):
+        p.timeout = 5
+        p.expect(b'>>> ')
+
+        p.sendline('list(range(4*3))')
+        self.assertEqual(p.expect([b'5,', b'5,']), 0)
+        p.expect(b'>>> ')
+
+        p.sendline(b'list(range(4*3))')
+        self.assertEqual(p.expect([b'7,', b'5,']), 1)
+        p.expect(b'>>> ')
+
+        p.sendline(b'list(range(4*3))')
+        self.assertEqual(p.expect([b'5,', b'7,']), 0)
+        p.expect(b'>>> ')
+
+        p.sendline(b'list(range(4*5))')
+        self.assertEqual(p.expect([b'2,', b'12,']), 0)
+        p.expect(b'>>> ')
+
+        p.sendline(b'list(range(4*5))')
+        self.assertEqual(p.expect([b'12,', b'2,']), 1)
+
+    def test_ordering(self):
+        '''This tests expect() for which pattern is returned
+        when many may eventually match. I (Grahn) am a bit
+        confused about what should happen, but this test passes
+        with pexpect 2.1.
+        '''
+        p = pexpect.spawn(self.PYTHONBIN)
+        self._ordering(p)
+
+    def test_ordering_exact(self):
+        '''This tests expect_exact() for which pattern is returned
+        when many may eventually match. I (Grahn) am a bit
+        confused about what should happen, but this test passes
+        for the expect() method with pexpect 2.1.
+        '''
+        p = pexpect.spawn(self.PYTHONBIN)
+        # mangle the spawn so we test expect_exact() instead
+        p.expect = p.expect_exact
+        self._ordering(p)
+
+    def _greed(self, expect):
+        # End at the same point: the one with the earliest start should win
+        self.assertEqual(expect([b'3, 4', b'2, 3, 4']), 1)
+
+        # Start at the same point: first pattern passed wins
+        self.assertEqual(expect([b'5,', b'5, 6']), 0)
+
+        # Same pattern passed twice: first instance wins
+        self.assertEqual(expect([b'7, 8', b'7, 8, 9', b'7, 8']), 0)
+
+    def _greed_read1(self, expect):
+        # Here, one has an earlier start and a later end. When processing
+        # one character at a time, the one that finishes first should win,
+        # because we don't know about the other match when it wins.
+        # If maxread > 1, this behaviour is currently undefined, although in
+        # most cases the one that starts first will win.
+        self.assertEqual(expect([b'1, 2, 3', b'2,']), 1)
+
+    def test_greed(self):
+        p = pexpect.spawn(self.PYTHONBIN + ' list100.py')
+        self._greed(p.expect)
+
+        p = pexpect.spawn(self.PYTHONBIN + ' list100.py', maxread=1)
+        self._greed_read1(p.expect)
+
+    def test_greed_exact(self):
+        p = pexpect.spawn(self.PYTHONBIN + ' list100.py')
+        self._greed(p.expect_exact)
+
+        p = pexpect.spawn(self.PYTHONBIN + ' list100.py', maxread=1)
+        self._greed_read1(p.expect_exact)
+
+    def test_bad_arg(self):
+        p = pexpect.spawn('cat')
+        with self.assertRaisesRegexp(TypeError, '.*must be one of'):
+            p.expect(1)
+        with self.assertRaisesRegexp(TypeError, '.*must be one of'):
+            p.expect([1, b'2'])
+        with self.assertRaisesRegexp(TypeError, '.*must be one of'):
+            p.expect_exact(1)
+        with self.assertRaisesRegexp(TypeError, '.*must be one of'):
+            p.expect_exact([1, b'2'])
+
+    def test_timeout_none(self):
+        p = pexpect.spawn('echo abcdef', timeout=None)
+        p.expect('abc')
+        p.expect_exact('def')
+        p.expect(pexpect.EOF)
+
+    def test_signal_handling(self):
+        '''
+            This tests the error handling of a signal interrupt (usually a
+            SIGWINCH generated when a window is resized), but in this test, we
+            are substituting an ALARM signal as this is much easier for testing
+            and is treated the same as a SIGWINCH.
+
+            To ensure that the alarm fires during the expect call, we are
+            setting the signal to alarm after 1 second while the spawned process
+            sleeps for 2 seconds prior to sending the expected output.
+        '''
+        def noop(x, y):
+            pass
+        signal.signal(signal.SIGALRM, noop)
+
+        p1 = pexpect.spawn('%s sleep_for.py 2' % self.PYTHONBIN, timeout=5)
+        p1.expect('READY')
+        signal.alarm(1)
+        p1.expect('END')
+
+    def test_stdin_closed(self):
+        '''
+        Ensure pexpect continues to operate even when stdin is closed
+        '''
+        class Closed_stdin_proc(multiprocessing.Process):
+            def run(self):
+                sys.__stdin__.close()
+                cat = pexpect.spawn('cat')
+                cat.sendeof()
+                cat.expect(pexpect.EOF)
+
+        proc = Closed_stdin_proc()
+        proc.start()
+        proc.join()
+        assert proc.exitcode == 0
+
+    def test_stdin_stdout_closed(self):
+        '''
+        Ensure pexpect continues to operate even when stdin and stdout is closed
+        '''
+        class Closed_stdin_stdout_proc(multiprocessing.Process):
+            def run(self):
+                sys.__stdin__.close()
+                sys.__stdout__.close()
+                cat = pexpect.spawn('cat')
+                cat.sendeof()
+                cat.expect(pexpect.EOF)
+
+        proc = Closed_stdin_stdout_proc()
+        proc.start()
+        proc.join()
+        assert proc.exitcode == 0
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase, 'test')
diff --git a/third_party/pexpect/tests/test_filedescriptor.py b/third_party/pexpect/tests/test_filedescriptor.py
new file mode 100755
index 0000000..d9164e1
--- /dev/null
+++ b/third_party/pexpect/tests/test_filedescriptor.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+from pexpect import fdpexpect
+import unittest
+from . import PexpectTestCase
+import os
+
+class ExpectTestCase(PexpectTestCase.PexpectTestCase):
+    def setUp(self):
+        print(self.id())
+        PexpectTestCase.PexpectTestCase.setUp(self)
+
+    def test_fd (self):
+        fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+        s = fdpexpect.fdspawn (fd)
+        s.expect(b'This is the end of test data:')
+        s.expect(pexpect.EOF)
+        self.assertEqual(s.before, b' END\n')
+
+    def test_maxread (self):
+        fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+        s = fdpexpect.fdspawn (fd)
+        s.maxread = 100
+        s.expect('2')
+        s.expect ('This is the end of test data:')
+        s.expect (pexpect.EOF)
+        self.assertEqual(s.before, b' END\n')
+
+    def test_fd_isalive (self):
+        fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+        s = fdpexpect.fdspawn(fd)
+        assert s.isalive()
+        os.close(fd)
+        assert not s.isalive(), "Should not be alive after close()"
+
+    def test_fd_isatty (self):
+        fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+        s = fdpexpect.fdspawn (fd)
+        assert not s.isatty()
+        s.close()
+
+    def test_fileobj(self):
+        f = open('TESTDATA.txt', 'r')
+        s = fdpexpect.fdspawn(f)  # Should get the fileno from the file handle
+        s.expect('2')
+        s.close()
+        assert not s.isalive()
+        s.close()  # Smoketest - should be able to call this again
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase, 'test')
diff --git a/third_party/pexpect/tests/test_interact.py b/third_party/pexpect/tests/test_interact.py
new file mode 100755
index 0000000..06fc44a
--- /dev/null
+++ b/third_party/pexpect/tests/test_interact.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import os
+import pexpect
+import unittest
+import sys
+from . import PexpectTestCase
+
+
+class InteractTestCase (PexpectTestCase.PexpectTestCase):
+    def setUp(self):
+        super(InteractTestCase, self).setUp()
+        self.env = env = os.environ.copy()
+
+        # Ensure 'import pexpect' works in subprocess interact*.py
+        if 'PYTHONPATH' in env:
+            env['PYTHONPATH'] = os.pathsep.join((self.project_dir,
+                                                    env['PYTHONPATH']))
+        else:
+            env['PYTHONPATH'] = self.project_dir
+
+        self.interact_py = ' '.join((sys.executable,
+                                     'interact.py',))
+        self.interact_ucs_py = ' '.join((sys.executable,
+                                         'interact_unicode.py',))
+
+    def test_interact_escape(self):
+        " Ensure `escape_character' value exits interactive mode. "
+        p = pexpect.spawn(self.interact_py, timeout=5, env=self.env)
+        p.expect('<in >')
+        p.sendcontrol(']')  # chr(29), the default `escape_character'
+                            # value of pexpect.interact().
+        p.expect_exact('Escaped interact')
+        p.expect(pexpect.EOF)
+        assert not p.isalive()
+        assert p.exitstatus == 0
+
+    def test_interact_spawn_eof(self):
+        " Ensure subprocess receives EOF and exit. "
+        p = pexpect.spawn(self.interact_py, timeout=5, env=self.env)
+        p.expect('<in >')
+        p.sendline(b'alpha')
+        p.sendline(b'beta')
+        p.expect(b'<out>alpha')
+        p.expect(b'<out>beta')
+        p.sendeof()
+        p.expect_exact('<eof>')
+        p.expect_exact('Escaped interact')
+        p.expect(pexpect.EOF)
+        assert not p.isalive()
+        assert p.exitstatus == 0
+
+    def test_interact_spawnu_eof(self):
+        " Ensure subprocess receives unicode, EOF, and exit. "
+        p = pexpect.spawnu(self.interact_ucs_py, timeout=5, env=self.env)
+        p.expect('<in >')
+        p.sendline('É‘lpha')
+        p.sendline('Î’eta')
+        p.expect('<out>É‘lpha')
+        p.expect('<out>Î’eta')
+        p.sendeof()
+        p.expect_exact('<eof>')
+        p.expect_exact('Escaped interact')
+        p.expect(pexpect.EOF)
+        assert not p.isalive()
+        assert p.exitstatus == 0
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(InteractTestCase, 'test')
+
diff --git a/third_party/pexpect/tests/test_isalive.py b/third_party/pexpect/tests/test_isalive.py
new file mode 100755
index 0000000..5168a52
--- /dev/null
+++ b/third_party/pexpect/tests/test_isalive.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import signal
+import sys
+import time
+from . import PexpectTestCase
+
+class IsAliveTestCase(PexpectTestCase.PexpectTestCase):
+
+    def test_expect_wait (self):
+        '''This tests that calling wait on a finished process works as expected.
+        '''
+        p = pexpect.spawn('sleep 3')
+        assert p.isalive()
+        p.wait()
+        assert not p.isalive()
+
+        p = pexpect.spawn('sleep 3')
+        assert p.isalive()
+        p.kill(9)
+        time.sleep(1)
+        with self.assertRaises(pexpect.ExceptionPexpect):
+            p.wait()
+
+    def test_signal_wait(self):
+        '''Test calling wait with a process terminated by a signal.'''
+        if not hasattr(signal, 'SIGALRM'):
+            return 'SKIP'
+        p = pexpect.spawn(sys.executable, ['alarm_die.py'])
+        p.wait()
+        assert p.exitstatus is None
+        self.assertEqual(p.signalstatus, signal.SIGALRM)
+
+    def test_expect_isalive_dead_after_normal_termination (self):
+        p = pexpect.spawn('ls', timeout=15)
+        p.expect(pexpect.EOF)
+        assert not p.isalive()
+
+    def test_expect_isalive_dead_after_SIGHUP(self):
+        p = pexpect.spawn('cat', timeout=5, ignore_sighup=False)
+        assert p.isalive()
+        force = False
+        if sys.platform.lower().startswith('sunos'):
+            # On Solaris (SmartOs), and only when executed from cron(1), SIGKILL
+            # is required to end the sub-process. This is done using force=True
+            force = True
+        assert p.terminate(force) == True
+        p.expect(pexpect.EOF)
+        assert not p.isalive()
+
+    def test_expect_isalive_dead_after_SIGINT(self):
+        p = pexpect.spawn('cat', timeout=5)
+        assert p.isalive()
+        force = False
+        if sys.platform.lower().startswith('sunos'):
+            # On Solaris (SmartOs), and only when executed from cron(1), SIGKILL
+            # is required to end the sub-process. This is done using force=True
+            force = True
+        assert p.terminate(force) == True
+        p.expect(pexpect.EOF)
+        assert not p.isalive()
+
+    def test_expect_isalive_dead_after_SIGKILL(self):
+        p = pexpect.spawn('cat', timeout=5)
+        assert p.isalive()
+        p.kill(9)
+        p.expect(pexpect.EOF)
+        assert not p.isalive()
+
+    def test_forced_terminate(self):
+        p = pexpect.spawn(sys.executable, ['needs_kill.py'])
+        p.expect('READY')
+        assert p.terminate(force=True) == True
+        p.expect(pexpect.EOF)
+        assert not p.isalive()
+
+### Some platforms allow this. Some reset status after call to waitpid.
+### probably not necessary, isalive() returns early when terminate is False.
+    def test_expect_isalive_consistent_multiple_calls (self):
+        '''This tests that multiple calls to isalive() return same value.
+        '''
+        p = pexpect.spawn('cat')
+        assert p.isalive()
+        assert p.isalive()
+        p.kill(9)
+        p.expect(pexpect.EOF)
+        assert not p.isalive()
+        assert not p.isalive()
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(IsAliveTestCase, 'test')
+
diff --git a/third_party/pexpect/tests/test_log.py b/third_party/pexpect/tests/test_log.py
new file mode 100755
index 0000000..4ad2256
--- /dev/null
+++ b/third_party/pexpect/tests/test_log.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import os
+import tempfile
+from . import PexpectTestCase
+
+# the program cat(1) may display ^D\x08\x08 when \x04 (EOF, Ctrl-D) is sent
+_CAT_EOF = b'^D\x08\x08'
+
+class TestCaseLog(PexpectTestCase.PexpectTestCase):
+
+    def test_log (self):
+        log_message = 'This is a test.'
+        filename = tempfile.mktemp()
+        mylog = open(filename, 'wb')
+        p = pexpect.spawn('echo', [log_message])
+        p.logfile = mylog
+        p.expect(pexpect.EOF)
+        p.logfile = None
+        mylog.close()
+        with open(filename, 'rb') as f:
+            lf = f.read()
+        os.unlink(filename)
+        self.assertEqual(lf.rstrip(), log_message.encode('ascii'))
+
+    def test_log_logfile_read (self):
+        log_message = 'This is a test.'
+        filename = tempfile.mktemp()
+        mylog = open(filename, 'wb')
+        p = pexpect.spawn('cat')
+        p.logfile_read = mylog
+        p.sendline(log_message)
+        p.sendeof()
+        p.expect(pexpect.EOF)
+        p.logfile = None
+        mylog.close()
+        with open(filename, 'rb') as f:
+            lf = f.read()
+        os.unlink (filename)
+        lf = lf.replace(_CAT_EOF, b'')
+        self.assertEqual(lf, b'This is a test.\r\nThis is a test.\r\n')
+
+    def test_log_logfile_send (self):
+        log_message = b'This is a test.'
+        filename = tempfile.mktemp()
+        mylog = open (filename, 'wb')
+        p = pexpect.spawn('cat')
+        p.logfile_send = mylog
+        p.sendline(log_message)
+        p.sendeof()
+        p.expect (pexpect.EOF)
+        p.logfile = None
+        mylog.close()
+        with open(filename, 'rb') as f:
+            lf = f.read()
+        os.unlink(filename)
+        lf = lf.replace(b'\x04', b'')
+        self.assertEqual(lf.rstrip(), log_message)
+
+    def test_log_send_and_received (self):
+
+        '''The logfile should have the test message three time -- once for the
+        data we sent. Once for the data that cat echos back as characters are
+        typed. And once for the data that cat prints after we send a linefeed
+        (sent by sendline). '''
+
+        log_message = 'This is a test.'
+        filename = tempfile.mktemp()
+        mylog = open(filename, 'wb')
+        p = pexpect.spawn('cat')
+        p.logfile = mylog
+        p.sendline(log_message)
+        p.sendeof()
+        p.expect (pexpect.EOF)
+        p.logfile = None
+        mylog.close()
+        with open(filename, 'rb') as f:
+            lf = f.read()
+        os.unlink(filename)
+        lf = lf.replace(b'\x04', b'').replace(_CAT_EOF, b'')
+        self.assertEqual(lf,
+                b'This is a test.\nThis is a test.\r\nThis is a test.\r\n')
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(TestCaseLog,'test')
+
diff --git a/third_party/pexpect/tests/test_maxcanon.py b/third_party/pexpect/tests/test_maxcanon.py
new file mode 100644
index 0000000..bbd08f3
--- /dev/null
+++ b/third_party/pexpect/tests/test_maxcanon.py
@@ -0,0 +1,152 @@
+""" Module for canonical-mode tests. """
+import sys
+import os
+
+
+import pexpect
+from . import PexpectTestCase
+
+
+class TestCaseCanon(PexpectTestCase.PexpectTestCase):
+    """
+    Test expected Canonical mode behavior (limited input line length).
+
+    All systems use the value of MAX_CANON which can be found using
+    fpathconf(3) value PC_MAX_CANON -- with the exception of Linux.
+
+    Linux, though defining a value of 255, actually honors the value
+    of 4096 from linux kernel include file tty.h definition
+    N_TTY_BUF_SIZE.
+
+    Linux also does not honor IMAXBEL. termios(3) states, "Linux does not
+    implement this bit, and acts as if it is always set." Although these
+    tests ensure it is enabled, this is a non-op for Linux.
+
+    These tests only ensure the correctness of the behavior described by
+    the sendline() docstring. pexpect is not particularly involved in
+    these scenarios, though if we wish to expose some kind of interface
+    to tty.setraw, for example, these tests may be re-purposed as such.
+
+    Lastly, portions of these tests are skipped on Travis-CI. It produces
+    unexpected behavior not reproduced on Debian/GNU Linux.
+    """
+
+    def setUp(self):
+        super(TestCaseCanon, self).setUp()
+
+        self.echo = False
+        if sys.platform.lower().startswith('linux'):
+            # linux is 4096, N_TTY_BUF_SIZE.
+            self.max_input = 4096
+            self.echo = True
+        elif sys.platform.lower().startswith('sunos'):
+            # SunOS allows PC_MAX_CANON + 1; see
+            # https://bitbucket.org/illumos/illumos-gate/src/d07a59219ab7fd2a7f39eb47c46cf083c88e932f/usr/src/uts/common/io/ldterm.c?at=default#cl-1888
+            self.max_input = os.fpathconf(0, 'PC_MAX_CANON') + 1
+        else:
+            # All others (probably) limit exactly at PC_MAX_CANON
+            self.max_input = os.fpathconf(0, 'PC_MAX_CANON')
+
+    def test_under_max_canon(self):
+        " BEL is not sent by terminal driver at maximum bytes - 1. "
+        # given,
+        child = pexpect.spawn('bash', echo=self.echo, timeout=5)
+        child.sendline('echo READY')
+        child.sendline('stty icanon imaxbel')
+        child.sendline('echo BEGIN; cat')
+
+        # some systems BEL on (maximum - 1), not able to receive CR,
+        # even though all characters up until then were received, they
+        # simply cannot be transmitted, as CR is part of the transmission.
+        send_bytes = self.max_input - 1
+
+        # exercise,
+        child.sendline('_' * send_bytes)
+
+        # fast forward beyond 'cat' command, as ^G can be found as part of
+        # set-xterm-title sequence of $PROMPT_COMMAND or $PS1.
+        child.expect_exact('BEGIN')
+
+        # verify, all input is found in echo output,
+        child.expect_exact('_' * send_bytes)
+
+        # BEL is not found,
+        with self.assertRaises(pexpect.TIMEOUT, timeout=5):
+            child.expect_exact('\a')
+
+        # cleanup,
+        child.sendeof()           # exit cat(1)
+        child.sendline('exit 0')  # exit bash(1)
+        child.expect(pexpect.EOF)
+        assert not child.isalive()
+        assert child.exitstatus == 0
+
+    def test_beyond_max_icanon(self):
+        " a single BEL is sent when maximum bytes is reached. "
+        # given,
+        child = pexpect.spawn('bash', echo=self.echo, timeout=5)
+        child.sendline('stty icanon imaxbel erase ^H')
+        child.sendline('cat')
+        send_bytes = self.max_input
+
+        # exercise,
+        child.sendline('_' * send_bytes)
+        child.expect_exact('\a')
+
+        # exercise, we must now backspace to send CR.
+        child.sendcontrol('h')
+        child.sendline()
+
+        if os.environ.get('TRAVIS', None) == 'true':
+            # Travis-CI has intermittent behavior here, possibly
+            # because the master process is itself, a PTY?
+            return
+
+        # verify the length of (maximum - 1) received by cat(1),
+        # which has written it back out,
+        child.expect_exact('_' * (send_bytes - 1))
+        # and not a byte more.
+        with self.assertRaises(pexpect.TIMEOUT):
+            child.expect_exact('_', timeout=1)
+
+        # cleanup,
+        child.sendeof()           # exit cat(1)
+        child.sendline('exit 0')  # exit bash(1)
+        child.expect_exact(pexpect.EOF)
+        assert not child.isalive()
+        assert child.exitstatus == 0
+
+    def test_max_no_icanon(self):
+        " may exceed maximum input bytes if canonical mode is disabled. "
+        # given,
+        child = pexpect.spawn('bash', echo=self.echo, timeout=5)
+        child.sendline('stty -icanon imaxbel')
+        child.sendline('echo BEGIN; cat')
+        send_bytes = self.max_input + 11
+
+        # exercise,
+        child.sendline('_' * send_bytes)
+
+        # fast forward beyond 'cat' command, as ^G can be found as part of
+        # set-xterm-title sequence of $PROMPT_COMMAND or $PS1.
+        child.expect_exact('BEGIN')
+
+        if os.environ.get('TRAVIS', None) == 'true':
+            # Travis-CI has intermittent behavior here, possibly
+            # because the master process is itself, a PTY?
+            return
+
+        # BEL is *not* found,
+        with self.assertRaises(pexpect.TIMEOUT):
+            child.expect_exact('\a', timeout=1)
+
+        # verify, all input is found in output,
+        child.expect_exact('_' * send_bytes)
+
+        # cleanup,
+        child.sendcontrol('c')    # exit cat(1) (eof wont work in -icanon)
+        child.sendcontrol('c')
+        child.sendline('exit 0')  # exit bash(1)
+        child.expect(pexpect.EOF)
+        assert not child.isalive()
+        assert child.exitstatus == 0
diff --git a/third_party/pexpect/tests/test_misc.py b/third_party/pexpect/tests/test_misc.py
new file mode 100755
index 0000000..d5a707c
--- /dev/null
+++ b/third_party/pexpect/tests/test_misc.py
@@ -0,0 +1,351 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import unittest
+import sys
+import re
+import signal
+import time
+import tempfile
+import os
+
+import pexpect
+from . import PexpectTestCase
+
+# the program cat(1) may display ^D\x08\x08 when \x04 (EOF, Ctrl-D) is sent
+_CAT_EOF = b'^D\x08\x08'
+
+
+if (sys.version_info[0] >= 3):
+    def _u(s):
+        return s.decode('utf-8')
+else:
+    def _u(s):
+        return s
+
+
+class TestCaseMisc(PexpectTestCase.PexpectTestCase):
+
+    def test_isatty(self):
+        " Test isatty() is True after spawning process on most platforms. "
+        child = pexpect.spawn('cat')
+        if not child.isatty() and sys.platform.lower().startswith('sunos'):
+            if hasattr(unittest, 'SkipTest'):
+                raise unittest.SkipTest("Not supported on this platform.")
+            return 'skip'
+        assert child.isatty()
+
+    def test_read(self):
+        " Test spawn.read by calls of various size. "
+        child = pexpect.spawn('cat')
+        child.sendline("abc")
+        child.sendeof()
+        self.assertEqual(child.read(0), b'')
+        self.assertEqual(child.read(1), b'a')
+        self.assertEqual(child.read(1), b'b')
+        self.assertEqual(child.read(1), b'c')
+        self.assertEqual(child.read(2), b'\r\n')
+        remaining = child.read().replace(_CAT_EOF, b'')
+        self.assertEqual(remaining, b'abc\r\n')
+
+    def test_readline_bin_echo(self):
+        " Test spawn('echo'). "
+        # given,
+        child = pexpect.spawn('echo', ['alpha', 'beta'])
+
+        # exercise,
+        assert child.readline() == b'alpha beta' + child.crlf
+
+    def test_readline(self):
+        " Test spawn.readline(). "
+        # when argument 0 is sent, nothing is returned.
+        # Otherwise the argument value is meaningless.
+        child = pexpect.spawn('cat', echo=False)
+        child.sendline("alpha")
+        child.sendline("beta")
+        child.sendline("gamma")
+        child.sendline("delta")
+        child.sendeof()
+        assert child.readline(0) == b''
+        assert child.readline().rstrip() == b'alpha'
+        assert child.readline(1).rstrip() == b'beta'
+        assert child.readline(2).rstrip() == b'gamma'
+        assert child.readline().rstrip() == b'delta'
+        child.expect(pexpect.EOF)
+        assert not child.isalive()
+        assert child.exitstatus == 0
+
+    def test_iter(self):
+        " iterating over lines of spawn.__iter__(). "
+        child = pexpect.spawn('cat', echo=False)
+        child.sendline("abc")
+        child.sendline("123")
+        child.sendeof()
+        # Don't use ''.join() because we want to test __iter__().
+        page = b''
+        for line in child:
+            page += line
+        page = page.replace(_CAT_EOF, b'')
+        assert page == b'abc\r\n123\r\n'
+
+    def test_readlines(self):
+        " reading all lines of spawn.readlines(). "
+        child = pexpect.spawn('cat', echo=False)
+        child.sendline("abc")
+        child.sendline("123")
+        child.sendeof()
+        page = b''.join(child.readlines()).replace(_CAT_EOF, b'')
+        assert page == b'abc\r\n123\r\n'
+        child.expect(pexpect.EOF)
+        assert not child.isalive()
+        assert child.exitstatus == 0
+
+    def test_write(self):
+        " write a character and return it in return. "
+        child = pexpect.spawn('cat', echo=False)
+        child.write('a')
+        child.write('\r')
+        self.assertEqual(child.readline(), b'a\r\n')
+
+    def test_writelines(self):
+        " spawn.writelines() "
+        child = pexpect.spawn('cat')
+        # notice that much like file.writelines, we do not delimit by newline
+        # -- it is equivalent to calling write(''.join([args,]))
+        child.writelines(['abc', '123', 'xyz', '\r'])
+        child.sendeof()
+        line = child.readline()
+        assert line == b'abc123xyz\r\n'
+
+    def test_eof(self):
+        " call to expect() after EOF is received raises pexpect.EOF "
+        child = pexpect.spawn('cat')
+        child.sendeof()
+        with self.assertRaises(pexpect.EOF):
+            child.expect('the unexpected')
+
+    def test_with(self):
+        "spawn can be used as a context manager"
+        with pexpect.spawn(sys.executable + ' echo_w_prompt.py') as p:
+            p.expect('<in >')
+            p.sendline(b'alpha')
+            p.expect(b'<out>alpha')
+            assert p.isalive()
+        
+        assert not p.isalive()
+
+    def test_terminate(self):
+        " test force terminate always succeeds (SIGKILL). "
+        child = pexpect.spawn('cat')
+        child.terminate(force=1)
+        assert child.terminated
+
+    def test_sighup(self):
+        " validate argument `ignore_sighup=True` and `ignore_sighup=False`. "
+        getch = sys.executable + ' getch.py'
+        child = pexpect.spawn(getch, ignore_sighup=True)
+        child.expect('READY')
+        child.kill(signal.SIGHUP)
+        for _ in range(10):
+            if not child.isalive():
+                self.fail('Child process should not have exited.')
+            time.sleep(0.1)
+
+        child = pexpect.spawn(getch, ignore_sighup=False)
+        child.expect('READY')
+        child.kill(signal.SIGHUP)
+        for _ in range(10):
+            if not child.isalive():
+                break
+            time.sleep(0.1)
+        else:
+            self.fail('Child process should have exited.')
+
+    def test_bad_child_pid(self):
+        " assert bad condition error in isalive(). "
+        expect_errmsg = re.escape("isalive() encountered condition where ")
+        child = pexpect.spawn('cat')
+        child.terminate(force=1)
+        # Force an invalid state to test isalive
+        child.ptyproc.terminated = 0
+        try:
+            with self.assertRaisesRegexp(pexpect.ExceptionPexpect,
+                                         ".*" + expect_errmsg):
+                child.isalive()
+        finally:
+            # Force valid state for child for __del__
+            child.terminated = 1
+
+    def test_bad_arguments_suggest_fdpsawn(self):
+        " assert custom exception for spawn(int). "
+        expect_errmsg = "maybe you want to use fdpexpect.fdspawn"
+        with self.assertRaisesRegexp(pexpect.ExceptionPexpect,
+                                     ".*" + expect_errmsg):
+            pexpect.spawn(1)
+
+    def test_bad_arguments_second_arg_is_list(self):
+        " Second argument to spawn, if used, must be only a list."
+        with self.assertRaises(TypeError):
+            pexpect.spawn('ls', '-la')
+
+        with self.assertRaises(TypeError):
+            # not even a tuple,
+            pexpect.spawn('ls', ('-la',))
+
+    def test_read_after_close_raises_value_error(self):
+        " Calling read_nonblocking after close raises ValueError. "
+        # as read_nonblocking underlies all other calls to read,
+        # ValueError should be thrown for all forms of read.
+        with self.assertRaises(ValueError):
+            p = pexpect.spawn('cat')
+            p.close()
+            p.read_nonblocking()
+
+        with self.assertRaises(ValueError):
+            p = pexpect.spawn('cat')
+            p.close()
+            p.read()
+
+        with self.assertRaises(ValueError):
+            p = pexpect.spawn('cat')
+            p.close()
+            p.readline()
+
+        with self.assertRaises(ValueError):
+            p = pexpect.spawn('cat')
+            p.close()
+            p.readlines()
+
+    def test_isalive(self):
+        " check isalive() before and after EOF. (True, False) "
+        child = pexpect.spawn('cat')
+        assert child.isalive() is True
+        child.sendeof()
+        child.expect(pexpect.EOF)
+        assert child.isalive() is False
+
+    def test_bad_type_in_expect(self):
+        " expect() does not accept dictionary arguments. "
+        child = pexpect.spawn('cat')
+        with self.assertRaises(TypeError):
+            child.expect({})
+
+    def test_env(self):
+        " check keyword argument `env=' of pexpect.run() "
+        default_env_output = pexpect.run('env')
+        custom_env_output = pexpect.run('env', env={'_key': '_value'})
+        assert custom_env_output != default_env_output
+        assert b'_key=_value' in custom_env_output
+
+    def test_cwd(self):
+        " check keyword argument `cwd=' of pexpect.run() "
+        tmp_dir = os.path.realpath(tempfile.gettempdir())
+        default = pexpect.run('pwd')
+        pwd_tmp = pexpect.run('pwd', cwd=tmp_dir).rstrip()
+        assert default != pwd_tmp
+        assert tmp_dir == _u(pwd_tmp)
+
+    def _test_searcher_as(self, searcher, plus=None):
+        # given,
+        given_words = ['alpha', 'beta', 'gamma', 'delta', ]
+        given_search = given_words
+        if searcher == pexpect.searcher_re:
+            given_search = [re.compile(word) for word in given_words]
+        if plus is not None:
+            given_search = given_search + [plus]
+        search_string = searcher(given_search)
+        basic_fmt = '\n    {0}: {1}'
+        fmt = basic_fmt
+        if searcher is pexpect.searcher_re:
+            fmt = '\n    {0}: re.compile({1})'
+        expected_output = '{0}:'.format(searcher.__name__)
+        idx = 0
+        for word in given_words:
+            expected_output += fmt.format(idx, '"{0}"'.format(word))
+            idx += 1
+        if plus is not None:
+            if plus == pexpect.EOF:
+                expected_output += basic_fmt.format(idx, 'EOF')
+            elif plus == pexpect.TIMEOUT:
+                expected_output += basic_fmt.format(idx, 'TIMEOUT')
+
+        # exercise,
+        assert search_string.__str__() == expected_output
+
+    def test_searcher_as_string(self):
+        " check searcher_string(..).__str__() "
+        self._test_searcher_as(pexpect.searcher_string)
+
+    def test_searcher_as_string_with_EOF(self):
+        " check searcher_string(..).__str__() that includes EOF "
+        self._test_searcher_as(pexpect.searcher_string, plus=pexpect.EOF)
+
+    def test_searcher_as_string_with_TIMEOUT(self):
+        " check searcher_string(..).__str__() that includes TIMEOUT "
+        self._test_searcher_as(pexpect.searcher_string, plus=pexpect.TIMEOUT)
+
+    def test_searcher_re_as_string(self):
+        " check searcher_re(..).__str__() "
+        self._test_searcher_as(pexpect.searcher_re)
+
+    def test_searcher_re_as_string_with_EOF(self):
+        " check searcher_re(..).__str__() that includes EOF "
+        self._test_searcher_as(pexpect.searcher_re, plus=pexpect.EOF)
+
+    def test_searcher_re_as_string_with_TIMEOUT(self):
+        " check searcher_re(..).__str__() that includes TIMEOUT "
+        self._test_searcher_as(pexpect.searcher_re, plus=pexpect.TIMEOUT)
+
+    def test_nonnative_pty_fork(self):
+        " test forced self.__fork_pty() and __pty_make_controlling_tty "
+        # given,
+        class spawn_ourptyfork(pexpect.spawn):
+            def _spawn(self, command, args=[], preexec_fn=None):
+                self.use_native_pty_fork = False
+                pexpect.spawn._spawn(self, command, args, preexec_fn)
+
+        # exercise,
+        p = spawn_ourptyfork('cat', echo=False)
+        # verify,
+        p.sendline('abc')
+        p.expect('abc')
+        p.sendeof()
+        p.expect(pexpect.EOF)
+        assert not p.isalive()
+
+    def test_exception_tb(self):
+        " test get_trace() filters away pexpect/__init__.py calls. "
+        p = pexpect.spawn('sleep 1')
+        try:
+            p.expect('BLAH')
+        except pexpect.ExceptionPexpect as e:
+            # get_trace should filter out frames in pexpect's own code
+            tb = e.get_trace()
+            # exercise,
+            assert 'raise ' not in tb
+            assert 'pexpect/__init__.py' not in tb
+        else:
+            assert False, "Should have raised an exception."
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(TestCaseMisc,'test')
+
diff --git a/third_party/pexpect/tests/test_missing_command.py b/third_party/pexpect/tests/test_missing_command.py
new file mode 100755
index 0000000..92e4733
--- /dev/null
+++ b/third_party/pexpect/tests/test_missing_command.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+from . import PexpectTestCase
+
+class MissingCommandTestCase (PexpectTestCase.PexpectTestCase):
+    def testMissingCommand(self):
+        try:
+            i = pexpect.spawn ('ZXQYQZX')
+        except Exception:
+            pass
+        else:
+            self.fail('Expected an Exception.')
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(MissingCommandTestCase,'test')
+
diff --git a/third_party/pexpect/tests/test_performance.py b/third_party/pexpect/tests/test_performance.py
new file mode 100755
index 0000000..7be0cf6
--- /dev/null
+++ b/third_party/pexpect/tests/test_performance.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from __future__ import print_function
+
+import unittest, time, sys
+import platform
+import pexpect
+from . import PexpectTestCase
+
+# This isn't exactly a unit test, but it fits in nicely with the rest of the tests.
+
+class PerformanceTestCase (PexpectTestCase.PexpectTestCase):
+
+    '''Testing the performance of expect, with emphasis on wading through long
+    inputs. '''
+
+    if sys.version_info[0] >= 3:
+        @staticmethod
+        def _iter_n(n):
+            s = 'for n in range(1, %d+1): print(n)' % n
+            return s.encode('ascii')
+
+    else:
+        @staticmethod
+        def _iter_n(n):
+            return 'for n in range(1, %d+1): print(n)' % n
+
+    def plain_range(self, n):
+        e = pexpect.spawn('python', timeout=100)
+        self.assertEqual(e.expect(b'>>>'), 0)
+        e.sendline(self._iter_n(n))
+        self.assertEqual(e.expect(br'\.{3}'), 0)
+        e.sendline(b'')
+        self.assertEqual(e.expect([b'inquisition', '%d' % n]), 1)
+
+    def window_range(self, n):
+        e = pexpect.spawn('python', timeout=100)
+        self.assertEqual(e.expect(b'>>>'), 0)
+        e.sendline(self._iter_n(n))
+        self.assertEqual(e.expect(r'\.{3}'), 0)
+        e.sendline(b'')
+        self.assertEqual(e.expect([b'inquisition', '%d' % n], searchwindowsize=20), 1)
+
+    def exact_range(self, n):
+        e = pexpect.spawn('python', timeout=100)
+        self.assertEqual(e.expect_exact([b'>>>']), 0)
+        e.sendline(self._iter_n(n))
+        self.assertEqual(e.expect_exact([b'...']), 0)
+        e.sendline(b'')
+        self.assertEqual(e.expect_exact([b'inquisition', '%d' % n],timeout=520), 1)
+
+    def ewin_range(self, n):
+        e = pexpect.spawn('python', timeout=100)
+        self.assertEqual(e.expect_exact([b'>>>']), 0)
+        e.sendline(self._iter_n(n))
+        self.assertEqual(e.expect_exact([b'...']), 0)
+        e.sendline(b'')
+        self.assertEqual(e.expect_exact([b'inquisition', '%d' % n], searchwindowsize=20), 1)
+
+    def faster_range(self, n):
+        e = pexpect.spawn('python', timeout=100)
+        self.assertEqual(e.expect(b'>>>'), 0)
+        e.sendline(('list(range(1, %d+1))' % n).encode('ascii'))
+        self.assertEqual(e.expect([b'inquisition', '%d' % n]), 1)
+
+    def test_100000(self):
+        if platform.python_implementation() == 'PyPy':
+            raise unittest.SkipTest("This test fails on PyPy because of REPL differences")
+        print()
+        start_time = time.time()
+        self.plain_range (100000)
+        print("100000 calls to plain_range:", (time.time() - start_time))
+        start_time = time.time()
+        self.window_range(100000)
+        print("100000 calls to window_range:", (time.time() - start_time))
+        start_time = time.time()
+        self.exact_range (100000)
+        print("100000 calls to exact_range:", (time.time() - start_time))
+        start_time = time.time()
+        self.ewin_range  (100000)
+        print("100000 calls to ewin_range:", (time.time() - start_time))
+        start_time = time.time()
+        self.faster_range(100000)
+        print("100000 calls to faster_range:", (time.time() - start_time))
+
+if __name__ == "__main__":
+    unittest.main()
+
+suite = unittest.makeSuite(PerformanceTestCase,'test')
diff --git a/third_party/pexpect/tests/test_pickling.py b/third_party/pexpect/tests/test_pickling.py
new file mode 100644
index 0000000..6538677
--- /dev/null
+++ b/third_party/pexpect/tests/test_pickling.py
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+import pickle
+import unittest
+
+from pexpect import ExceptionPexpect
+
+class PickleTest(unittest.TestCase):
+    def test_picking(self):
+        e = ExceptionPexpect('Oh noes!')
+        clone = pickle.loads(pickle.dumps(e))
+        self.assertEqual(e.value, clone.value)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/third_party/pexpect/tests/test_pxssh.py b/third_party/pexpect/tests/test_pxssh.py
new file mode 100644
index 0000000..0ff092c
--- /dev/null
+++ b/third_party/pexpect/tests/test_pxssh.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+import os
+
+import unittest
+
+from pexpect import pxssh
+
+class SSHTestBase(unittest.TestCase):
+    def setUp(self):
+        self.orig_path = os.environ.get('PATH')
+        fakessh_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'fakessh'))
+        os.environ['PATH'] = fakessh_dir + \
+                    ((os.pathsep + self.orig_path) if self.orig_path else '')
+
+    def tearDown(self):
+        if self.orig_path:
+            os.environ['PATH'] = self.orig_path
+        else:
+            del os.environ['PATH']
+
+class PxsshTestCase(SSHTestBase):
+    def test_fake_ssh(self):
+        ssh = pxssh.pxssh()
+        #ssh.logfile_read = sys.stdout  # DEBUG
+        ssh.login('server', 'me', password='s3cret')
+        ssh.sendline('ping')
+        ssh.expect('pong', timeout=10)
+        assert ssh.prompt(timeout=10)
+        ssh.logout()
+
+    def test_wrong_pw(self):
+        ssh = pxssh.pxssh()
+        try:
+            ssh.login('server', 'me', password='wr0ng')
+        except pxssh.ExceptionPxssh:
+            pass
+        else:
+            assert False, 'Password should have been refused'
+
+    def test_failed_set_unique_prompt(self):
+        ssh = pxssh.pxssh()
+        ssh.set_unique_prompt = lambda: False
+        try:
+            ssh.login('server', 'me', password='s3cret',
+                      auto_prompt_reset=True)
+        except pxssh.ExceptionPxssh:
+            pass
+        else:
+            assert False, 'should have raised exception, pxssh.ExceptionPxssh'
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/third_party/pexpect/tests/test_replwrap.py b/third_party/pexpect/tests/test_replwrap.py
new file mode 100644
index 0000000..28c7599
--- /dev/null
+++ b/third_party/pexpect/tests/test_replwrap.py
@@ -0,0 +1,84 @@
+import platform
+import unittest
+import re
+import os
+
+import pexpect
+from pexpect import replwrap
+
+
+class REPLWrapTestCase(unittest.TestCase):
+    def setUp(self):
+        super(REPLWrapTestCase, self).setUp()
+        self.save_ps1 = os.getenv('PS1', r'\$')
+        self.save_ps2 = os.getenv('PS2', '>')
+        os.putenv('PS1', r'\$')
+        os.putenv('PS2', '>')
+
+    def tearDown(self):
+        super(REPLWrapTestCase, self).tearDown()
+        os.putenv('PS1', self.save_ps1)
+        os.putenv('PS2', self.save_ps2)
+
+    def test_bash(self):
+        bash = replwrap.bash()
+        res = bash.run_command("time")
+        assert 'real' in res, res
+
+        # PAGER should be set to cat, otherwise man hangs
+        res = bash.run_command('man sleep', timeout=5)
+        assert 'SLEEP' in res, res
+
+    def test_multiline(self):
+        bash = replwrap.bash()
+        res = bash.run_command("echo '1 2\n3 4'")
+        self.assertEqual(res.strip().splitlines(), ['1 2', '3 4'])
+
+        # Should raise ValueError if input is incomplete
+        try:
+            bash.run_command("echo '5 6")
+        except ValueError:
+            pass
+        else:
+            assert False, "Didn't raise ValueError for incomplete input"
+
+        # Check that the REPL was reset (SIGINT) after the incomplete input
+        res = bash.run_command("echo '1 2\n3 4'")
+        self.assertEqual(res.strip().splitlines(), ['1 2', '3 4'])
+
+    def test_existing_spawn(self):
+        child = pexpect.spawnu("bash", timeout=5, echo=False)
+        repl = replwrap.REPLWrapper(child, re.compile('[$#]'),
+                                    "PS1='{0}' PS2='{1}' "
+                                    "PROMPT_COMMAND=''")
+
+        res = repl.run_command("echo $HOME")
+        assert res.startswith('/'), res
+
+    def test_python(self):
+        if platform.python_implementation() == 'PyPy':
+            raise unittest.SkipTest("This test fails on PyPy because of REPL differences")
+
+        p = replwrap.python()
+        res = p.run_command('4+7')
+        assert res.strip() == '11'
+
+        res = p.run_command('for a in range(3): print(a)\n')
+        assert res.strip().splitlines() == ['0', '1', '2']
+
+    def test_no_change_prompt(self):
+        if platform.python_implementation() == 'PyPy':
+            raise unittest.SkipTest("This test fails on PyPy because of REPL differences")
+
+        child = pexpect.spawnu('python', echo=False, timeout=5)
+        # prompt_change=None should mean no prompt change
+        py = replwrap.REPLWrapper(child, replwrap.u(">>> "), prompt_change=None,
+                                  continuation_prompt=replwrap.u("... "))
+        assert py.prompt == ">>> "
+
+        res = py.run_command("for a in range(3): print(a)\n")
+        assert res.strip().splitlines() == ['0', '1', '2']
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/third_party/pexpect/tests/test_repr.py b/third_party/pexpect/tests/test_repr.py
new file mode 100644
index 0000000..ce618d4
--- /dev/null
+++ b/third_party/pexpect/tests/test_repr.py
@@ -0,0 +1,26 @@
+""" Test __str__ methods. """
+import pexpect
+
+from . import PexpectTestCase
+
+
+class TestCaseMisc(PexpectTestCase.PexpectTestCase):
+
+    def test_str_spawnu(self):
+        """ Exercise spawnu.__str__() """
+        # given,
+        p = pexpect.spawnu('cat')
+        # exercise,
+        value = str(p)
+        # verify
+        assert isinstance(value, str)
+
+    def test_str_spawn(self):
+        """ Exercise spawn.__str__() """
+        # given,
+        p = pexpect.spawn('cat')
+        # exercise,
+        value = str(p)
+        # verify
+        assert isinstance(value, str)
+
diff --git a/third_party/pexpect/tests/test_run.py b/third_party/pexpect/tests/test_run.py
new file mode 100755
index 0000000..c018b4d
--- /dev/null
+++ b/third_party/pexpect/tests/test_run.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+# encoding: utf-8
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import subprocess
+import tempfile
+import sys
+import os
+from . import PexpectTestCase
+
+unicode_type = str if pexpect.PY3 else unicode
+
+def timeout_callback (d):
+#    print d["event_count"],
+    if d["event_count"]>3:
+        return 1
+    return 0
+
+class RunFuncTestCase(PexpectTestCase.PexpectTestCase):
+    runfunc = staticmethod(pexpect.run)
+    cr = b'\r'
+    empty = b''
+    prep_subprocess_out = staticmethod(lambda x: x)
+
+    def setUp(self):
+        fd, self.rcfile = tempfile.mkstemp()
+        os.write(fd, b'PS1=GO: \n')
+        os.close(fd)
+        super(RunFuncTestCase, self).setUp()
+
+    def tearDown(self):
+        os.unlink(self.rcfile)
+        super(RunFuncTestCase, self).tearDown()
+
+    def test_run_exit (self):
+        (data, exitstatus) = self.runfunc('python exit1.py', withexitstatus=1)
+        assert exitstatus == 1, "Exit status of 'python exit1.py' should be 1."
+
+    def test_run (self):
+        the_old_way = subprocess.Popen(args=['uname', '-m', '-n'],
+                stdout=subprocess.PIPE).communicate()[0].rstrip()
+        (the_new_way, exitstatus) = self.runfunc('uname -m -n', withexitstatus=1)
+        the_new_way = the_new_way.replace(self.cr, self.empty).rstrip()
+        self.assertEqual(self.prep_subprocess_out(the_old_way), the_new_way)
+        self.assertEqual(exitstatus, 0)
+
+    def test_run_callback (self): # TODO it seems like this test could block forever if run fails...
+        self.runfunc("cat", timeout=1, events={pexpect.TIMEOUT:timeout_callback})
+
+    def test_run_bad_exitstatus (self):
+        (the_new_way, exitstatus) = self.runfunc('ls -l /najoeufhdnzkxjd',
+                                                    withexitstatus=1)
+        assert exitstatus != 0
+
+    def test_run_tuple_list (self):
+        events = [
+            # second match on 'abc', echo 'def'
+            ('abc\r\n.*GO:', 'echo "def"\n'),
+            # final match on 'def': exit
+            ('def\r\n.*GO:', 'exit\n'),
+            # first match on 'GO:' prompt, echo 'abc'
+            ('GO:', 'echo "abc"\n')
+        ]
+
+        (data, exitstatus) = pexpect.run(
+            'bash --rcfile {0}'.format(self.rcfile),
+            withexitstatus=True,
+            events=events,
+            timeout=10)
+        assert exitstatus == 0
+
+class RunUnicodeFuncTestCase(RunFuncTestCase):
+    runfunc = staticmethod(pexpect.runu)
+    cr = b'\r'.decode('ascii')
+    empty = b''.decode('ascii')
+    prep_subprocess_out = staticmethod(lambda x: x.decode('utf-8', 'replace'))
+    def test_run_unicode(self):
+        if pexpect.PY3:
+            c = chr(254)   # þ
+            pattern = '<in >'
+        else:
+            c = unichr(254)  # analysis:ignore
+            pattern = '<in >'.decode('ascii')
+
+        def callback(d):
+            if d['event_count'] == 0:
+                return c + '\n'
+            else:
+                return True  # Stop the child process
+
+        output = pexpect.runu(sys.executable + ' echo_w_prompt.py',
+                              env={'PYTHONIOENCODING':'utf-8'},
+                              events={pattern:callback})
+        assert isinstance(output, unicode_type), type(output)
+        assert '<out>'+c in output, output
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/third_party/pexpect/tests/test_run_out_of_pty.py b/third_party/pexpect/tests/test_run_out_of_pty.py
new file mode 100755
index 0000000..3090147
--- /dev/null
+++ b/third_party/pexpect/tests/test_run_out_of_pty.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+from . import PexpectTestCase
+
+class ExpectTestCase(PexpectTestCase.PexpectTestCase):
+    # This takes too long to run and isn't all that interesting of a test.
+    def OFF_test_run_out_of_pty (self):
+        '''This assumes that the tested platform has < 10000 pty devices.
+        This test currently does not work under Solaris.
+        Under Solaris it runs out of file descriptors first and
+        ld.so starts to barf:
+            ld.so.1: pt_chmod: fatal: /usr/lib/libc.so.1: Too many open files
+        '''
+        plist=[]
+        for count in range (0,10000):
+                try:
+                        plist.append (pexpect.spawn('ls -l'))
+                except pexpect.ExceptionPexpect:
+                        for c in range (0, count):
+                            plist[c].close()
+                        return
+                except Exception:
+                        err = sys.exc_info()[1]
+                        self.fail ('Expected ExceptionPexpect. ' + str(err))
+        self.fail ('Could not run out of pty devices. This may be OK.')
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase,'test')
+
diff --git a/third_party/pexpect/tests/test_screen.py b/third_party/pexpect/tests/test_screen.py
new file mode 100755
index 0000000..2429e57
--- /dev/null
+++ b/third_party/pexpect/tests/test_screen.py
@@ -0,0 +1,287 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import sys
+
+from pexpect import screen
+import unittest
+from . import PexpectTestCase
+
+PY3 = (sys.version_info[0] >= 3)
+
+fill1_target='XXXXXXXXXX\n' + \
+'XOOOOOOOOX\n' + \
+'XO::::::OX\n' + \
+'XO:oooo:OX\n' + \
+'XO:o..o:OX\n' + \
+'XO:o..o:OX\n' + \
+'XO:oooo:OX\n' + \
+'XO::::::OX\n' + \
+'XOOOOOOOOX\n' + \
+'XXXXXXXXXX'
+fill2_target = 'XXXXXXXXXXX\n' + \
+'XOOOOOOOOOX\n' + \
+'XO:::::::OX\n' + \
+'XO:ooooo:OX\n' + \
+'XO:o...o:OX\n' + \
+'XO:o.+.o:OX\n' + \
+'XO:o...o:OX\n' + \
+'XO:ooooo:OX\n' + \
+'XO:::::::OX\n' + \
+'XOOOOOOOOOX\n' + \
+'XXXXXXXXXXX'
+put_target = '\\.3.5.7.9/\n' + \
+'.........2\n' + \
+'3.........\n' + \
+'.........4\n' + \
+'5...\\/....\n' + \
+'..../\\...6\n' + \
+'7.........\n' + \
+'.........8\n' + \
+'9.........\n' + \
+'/2.4.6.8.\\'
+scroll_target = '\\.3.5.7.9/\n' + \
+'\\.3.5.7.9/\n' + \
+'\\.3.5.7.9/\n' + \
+'\\.3.5.7.9/\n' + \
+'5...\\/....\n' + \
+'..../\\...6\n' + \
+'/2.4.6.8.\\\n' + \
+'/2.4.6.8.\\\n' + \
+'/2.4.6.8.\\\n' + \
+'/2.4.6.8.\\'
+insert_target = 'ZXZZZZZZXZ\n' +\
+'.........2\n' +\
+'3.........\n' +\
+'.........4\n' +\
+'Z5...\\/...\n' +\
+'..../Z\\...\n' +\
+'7.........\n' +\
+'.........8\n' +\
+'9.........\n' +\
+'ZZ/2.4.6ZZ'
+get_region_target = ['......', '.\\/...', './\\...', '......']
+
+unicode_box_unicode_result = u'\u2554\u2557\n\u255A\u255D'
+unicode_box_pretty_result = u'''\
++--+
+|\u2554\u2557|
+|\u255A\u255D|
++--+
+'''
+unicode_box_ascii_bytes_result = b'??\n??'
+unicode_box_cp437_bytes_result = b'\xc9\xbb\n\xc8\xbc'
+unicode_box_utf8_bytes_result = b'\xe2\x95\x94\xe2\x95\x97\n\xe2\x95\x9a\xe2\x95\x9d'
+
+class screenTestCase (PexpectTestCase.PexpectTestCase):
+    def make_screen_with_put (self):
+        s = screen.screen(10,10)
+        s.fill ('.')
+        for r in range (1,s.rows + 1):
+            if r % 2:
+                s.put_abs (r, 1, str(r))
+            else:
+                s.put_abs (r, s.cols, str(r))
+        for c in range (1,s.cols + 1):
+            if c % 2:
+                s.put_abs (1, c, str(c))
+            else:
+                s.put_abs (s.rows, c, str(c))
+        s.put_abs(1,1, '\\')
+        s.put_abs(1,s.cols, '/')
+        s.put_abs(s.rows,1,'/')
+        s.put_abs(s.rows, s.cols, '\\')
+        s.put_abs(5,5,'\\')
+        s.put_abs(5,6,'/')
+        s.put_abs(6,5,'/')
+        s.put_abs(6,6,'\\')
+        return s
+
+    def test_fill (self):
+        s = screen.screen (10,10)
+        s.fill_region (10,1,1,10,'X')
+        s.fill_region (2,2,9,9,'O')
+        s.fill_region (8,8,3,3,':')
+        s.fill_region (4,7,7,4,'o')
+        s.fill_region (6,5,5,6,'.')
+        assert str(s) == fill1_target
+
+        s = screen.screen (11,11)
+        s.fill_region (1,1,11,11,'X')
+        s.fill_region (2,2,10,10,'O')
+        s.fill_region (9,9,3,3,':')
+        s.fill_region (4,8,8,4,'o')
+        s.fill_region (7,5,5,7,'.')
+        s.fill_region (6,6,6,6,'+')
+        assert str(s) == fill2_target
+    def test_put (self):
+        s = self.make_screen_with_put()
+        assert str(s) == put_target
+    def test_get_region (self):
+        s = self.make_screen_with_put()
+        r = s.get_region (4,4,7,9)
+        assert r == get_region_target
+
+    def test_cursor_save (self):
+        s = self.make_screen_with_put()
+        s.cursor_home (5,5)
+        c = s.get()
+        s.cursor_save()
+        s.cursor_home()
+        s.cursor_forward()
+        s.cursor_down()
+        s.cursor_unsave()
+        assert s.cur_r == 5 and s.cur_c == 5
+        assert c == s.get()
+    def test_scroll (self):
+        s = self.make_screen_with_put()
+        s.scroll_screen_rows (1,4)
+        s.scroll_down(); s.scroll_down(); s.scroll_down()
+        s.scroll_down(); s.scroll_down(); s.scroll_down()
+        s.scroll_screen_rows (7,10)
+        s.scroll_up(); s.scroll_up(); s.scroll_up()
+        s.scroll_up(); s.scroll_up(); s.scroll_up()
+        assert str(s) == scroll_target
+    def test_insert (self):
+        s = self.make_screen_with_put()
+        s.insert_abs (10,1,'Z')
+        s.insert_abs (1,1,'Z')
+        s.insert_abs (1,1,'Z')
+        s.insert_abs (1,1,'Z')
+        s.insert_abs (1,1,'Z')
+        s.insert_abs (1,1,'Z')
+        s.insert_abs (10,1,'Z')
+        s.insert_abs (1,1,'Z')
+        s.insert_abs (1,1,'Z')
+        s.insert_abs (5,1,'Z')
+        s.insert_abs (6,6,'Z')
+        s.cursor_home (1,1) # Also test relative insert.
+        s.insert ('Z')
+        s.insert ('Z')
+        s.insert ('Z')
+        s.insert ('Z')
+        s.insert_abs (1,8,'X')
+        s.insert_abs (1,2,'X')
+        s.insert_abs (10,9,'Z')
+        s.insert_abs (10,9,'Z')
+        assert str(s) == insert_target
+
+    def make_screen_with_box_unicode(self, *args, **kwargs):
+        '''Creates a screen containing a box drawn using double-line
+        line drawing characters. The characters are fed in as
+        unicode. '''
+        s = screen.screen (2,2,*args,**kwargs)
+        s.put_abs (1,1,u'\u2554')
+        s.put_abs (1,2,u'\u2557')
+        s.put_abs (2,1,u'\u255A')
+        s.put_abs (2,2,u'\u255D')
+        return s
+
+    def make_screen_with_box_cp437(self, *args, **kwargs):
+        '''Creates a screen containing a box drawn using double-line
+        line drawing characters. The characters are fed in as
+        CP437. '''
+        s = screen.screen (2,2,*args,**kwargs)
+        s.put_abs (1,1,b'\xc9')
+        s.put_abs (1,2,b'\xbb')
+        s.put_abs (2,1,b'\xc8')
+        s.put_abs (2,2,b'\xbc')
+        return s
+
+    def make_screen_with_box_utf8(self, *args, **kwargs):
+        '''Creates a screen containing a box drawn using double-line
+        line drawing characters. The characters are fed in as
+        UTF-8. '''
+        s = screen.screen (2,2,*args,**kwargs)
+        s.put_abs (1,1,b'\xe2\x95\x94')
+        s.put_abs (1,2,b'\xe2\x95\x97')
+        s.put_abs (2,1,b'\xe2\x95\x9a')
+        s.put_abs (2,2,b'\xe2\x95\x9d')
+        return s
+
+    def test_unicode_ascii (self):
+        # With the default encoding set to ASCII, we should still be
+        # able to feed in unicode strings and get them back out:
+        s = self.make_screen_with_box_unicode('ascii')
+        if PY3:
+            assert str(s) == unicode_box_unicode_result
+        else:
+            assert unicode(s) == unicode_box_unicode_result
+            # And we should still get something for Python 2 str(), though
+            # it might not be very useful
+            str(s)
+
+        assert s.pretty() == unicode_box_pretty_result
+
+    def test_decoding_errors(self):
+        # With strict error handling, it should reject bytes it can't decode
+        with self.assertRaises(UnicodeDecodeError):
+            self.make_screen_with_box_cp437('ascii', 'strict')
+
+        # replace should turn them into unicode replacement characters, U+FFFD
+        s = self.make_screen_with_box_cp437('ascii', 'replace')
+        expected = u'\ufffd\ufffd\n\ufffd\ufffd'
+        if PY3:
+            assert str(s) == expected
+        else:
+            assert unicode(s) == expected
+
+    def test_unicode_cp437 (self):
+        # Verify decoding from and re-encoding to CP437.
+        s = self.make_screen_with_box_cp437('cp437','strict')
+        if PY3:
+            assert str(s) == unicode_box_unicode_result
+        else:
+            assert unicode(s) == unicode_box_unicode_result
+            assert str(s) == unicode_box_cp437_bytes_result
+        assert s.pretty() == unicode_box_pretty_result
+
+    def test_unicode_utf8 (self):
+        # Verify decoding from and re-encoding to UTF-8.
+        s = self.make_screen_with_box_utf8('utf-8','strict')
+        if PY3:
+            assert str(s) == unicode_box_unicode_result
+        else:
+            assert unicode(s) == unicode_box_unicode_result
+            assert str(s) == unicode_box_utf8_bytes_result
+        assert s.pretty() == unicode_box_pretty_result
+
+    def test_no_bytes(self):
+        s = screen.screen(2, 2, encoding=None)
+        s.put_abs(1, 1, u'A')
+        s.put_abs(2, 2, u'D')
+
+        with self.assertRaises(TypeError):
+            s.put_abs(1, 2, b'B')
+
+        if PY3:
+            assert str(s) == u'A \n D'
+        else:
+            assert unicode(s) == u'A \n D'
+            # This will still work if it's limited to ascii
+            assert str(s) == b'A \n D'
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(screenTestCase,'test')
+
+
diff --git a/third_party/pexpect/tests/test_timeout_pattern.py b/third_party/pexpect/tests/test_timeout_pattern.py
new file mode 100755
index 0000000..5f610ef
--- /dev/null
+++ b/third_party/pexpect/tests/test_timeout_pattern.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+from __future__ import with_statement  # bring 'with' stmt to py25
+import pexpect
+import unittest
+from . import PexpectTestCase
+import sys
+
+class Exp_TimeoutTestCase(PexpectTestCase.PexpectTestCase):
+    def test_matches_exp_timeout (self):
+        '''This tests that we can raise and catch TIMEOUT.
+        '''
+        try:
+            raise pexpect.TIMEOUT("TIMEOUT match test")
+        except pexpect.TIMEOUT:
+            pass
+            #print "Correctly caught TIMEOUT when raising TIMEOUT."
+        else:
+            self.fail('TIMEOUT not caught by an except TIMEOUT clause.')
+
+    def test_pattern_printout (self):
+        '''Verify that a TIMEOUT returns the proper patterns it is trying to match against.
+        Make sure it is returning the pattern from the correct call.'''
+        try:
+            p = pexpect.spawn('cat')
+            p.sendline('Hello')
+            p.expect('Hello')
+            p.expect('Goodbye',timeout=5)
+        except pexpect.TIMEOUT:
+            assert p.match_index == None
+        else:
+            self.fail("Did not generate a TIMEOUT exception.")
+
+    def test_exp_timeout_notThrown (self):
+        '''Verify that a TIMEOUT is not thrown when we match what we expect.'''
+        try:
+            p = pexpect.spawn('cat')
+            p.sendline('Hello')
+            p.expect('Hello')
+        except pexpect.TIMEOUT:
+            self.fail("TIMEOUT caught when it shouldn't be raised because we match the proper pattern.")
+
+    def test_stacktraceMunging (self):
+        '''Verify that the stack trace returned with a TIMEOUT instance does not contain references to pexpect.'''
+        try:
+            p = pexpect.spawn('cat')
+            p.sendline('Hello')
+            p.expect('Goodbye',timeout=5)
+        except pexpect.TIMEOUT:
+            err = sys.exc_info()[1]
+            if err.get_trace().count("pexpect/__init__.py") != 0:
+                self.fail("The TIMEOUT get_trace() referenced pexpect.py. "
+                    "It should only reference the caller.\n" + err.get_trace())
+
+    def test_correctStackTrace (self):
+        '''Verify that the stack trace returned with a TIMEOUT instance correctly handles function calls.'''
+        def nestedFunction (spawnInstance):
+            spawnInstance.expect("junk", timeout=3)
+
+        try:
+            p = pexpect.spawn('cat')
+            p.sendline('Hello')
+            nestedFunction(p)
+        except pexpect.TIMEOUT:
+            err = sys.exc_info()[1]
+            if err.get_trace().count("nestedFunction") == 0:
+                self.fail("The TIMEOUT get_trace() did not show the call "
+                    "to the nestedFunction function.\n" + str(err) + "\n"
+                    + err.get_trace())
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(Exp_TimeoutTestCase,'test')
diff --git a/third_party/pexpect/tests/test_unicode.py b/third_party/pexpect/tests/test_unicode.py
new file mode 100644
index 0000000..f342bf9
--- /dev/null
+++ b/third_party/pexpect/tests/test_unicode.py
@@ -0,0 +1,179 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+import platform
+import tempfile
+import sys
+import time
+
+import pexpect
+import unittest
+from . import PexpectTestCase
+
+# the program cat(1) may display ^D\x08\x08 when \x04 (EOF, Ctrl-D) is sent
+_CAT_EOF = '^D\x08\x08'
+
+class UnicodeTests(PexpectTestCase.PexpectTestCase):
+    def test_expect_basic (self):
+        p = pexpect.spawnu('cat')
+        p.sendline('Hello')
+        p.sendline('there')
+        p.sendline('Mr. þython') # þ is more like th than p, but never mind
+        p.expect('Hello')
+        p.expect('there')
+        p.expect('Mr. þython')
+        p.sendeof ()
+        p.expect (pexpect.EOF)
+
+    def test_expect_exact_basic (self):
+        p = pexpect.spawnu('cat')
+        p.sendline('Hello')
+        p.sendline('there')
+        p.sendline('Mr. þython')
+        p.expect_exact('Hello')
+        p.expect_exact('there')
+        p.expect_exact('Mr. þython')
+        p.sendeof()
+        p.expect_exact (pexpect.EOF)
+
+    def test_expect_setecho_toggle(self):
+        '''This tests that echo may be toggled off.
+        '''
+        p = pexpect.spawnu('cat', timeout=5)
+        try:
+            self._expect_echo_toggle_off(p)
+        except IOError:
+            if sys.platform.lower().startswith('sunos'):
+                if hasattr(unittest, 'SkipTest'):
+                    raise unittest.SkipTest("Not supported on this platform.")
+                return 'skip'
+            raise
+        self._expect_echo_toggle_on(p)
+
+    def test_expect_echo_exact (self):
+        '''Like test_expect_echo(), but using expect_exact().
+        '''
+        p = pexpect.spawnu('cat', timeout=5)
+        p.expect = p.expect_exact
+        self._expect_echo(p)
+
+    def test_expect_setecho_toggle_exact(self):
+        p = pexpect.spawnu('cat', timeout=5)
+        p.expect = p.expect_exact
+        try:
+            self._expect_echo_toggle_off(p)
+        except IOError:
+            if sys.platform.lower().startswith('sunos'):
+                if hasattr(unittest, 'SkipTest'):
+                    raise unittest.SkipTest("Not supported on this platform.")
+                return 'skip'
+            raise
+        self._expect_echo_toggle_on(p)
+
+    def _expect_echo (self, p):
+        p.sendline('1234') # Should see this twice (once from tty echo and again from cat).
+        index = p.expect (['1234', 'abcdé', 'wxyz', pexpect.EOF, pexpect.TIMEOUT])
+        assert index == 0, (index, p.before)
+        index = p.expect (['1234', 'abcdé', 'wxyz', pexpect.EOF])
+        assert index == 0, index
+
+    def _expect_echo_toggle_off(self, p):
+        p.setecho(0) # Turn off tty echo
+        p.waitnoecho()
+        p.sendline('abcdé') # Now, should only see this once.
+        p.sendline('wxyz') # Should also be only once.
+        index = p.expect ([pexpect.EOF,pexpect.TIMEOUT, 'abcdé', 'wxyz', '1234'])
+        assert index == 2, index
+        index = p.expect ([pexpect.EOF, 'abcdé', 'wxyz', '7890'])
+        assert index == 2, index
+
+    def _expect_echo_toggle_on(self, p):
+        p.setecho(1) # Turn on tty echo
+        time.sleep(0.2) # there is no waitecho() !
+        p.sendline('7890') # Should see this twice.
+        index = p.expect ([pexpect.EOF, 'abcdé', 'wxyz', '7890'])
+        assert index == 3, index
+        index = p.expect ([pexpect.EOF, 'abcdé', 'wxyz', '7890'])
+        assert index == 3, index
+        p.sendeof()
+
+    def test_log_unicode(self):
+        msg = "abcΩ÷"
+        filename_send = tempfile.mktemp()
+        filename_read = tempfile.mktemp()
+        p = pexpect.spawnu('cat')
+        if platform.python_version_tuple() < ('3', '0', '0'):
+            import codecs
+            def open(fname, mode, **kwargs):
+                if 'newline' in kwargs:
+                    del kwargs['newline']
+                return codecs.open(fname, mode, **kwargs)
+        else:
+            import io
+            open = io.open
+
+        p.logfile_send = open(filename_send, 'w', encoding='utf-8')
+        p.logfile_read = open(filename_read, 'w', encoding='utf-8')
+        p.sendline(msg)
+        p.sendeof()
+        p.expect(pexpect.EOF)
+        p.close()
+        p.logfile_send.close()
+        p.logfile_read.close()
+
+        # ensure the 'send' log is correct,
+        with open(filename_send, 'r', encoding='utf-8') as f:
+            self.assertEqual(f.read(), msg + '\n\x04')
+
+        # ensure the 'read' log is correct,
+        with open(filename_read, 'r', encoding='utf-8', newline='') as f:
+            output = f.read().replace(_CAT_EOF, '')
+            self.assertEqual(output, (msg + '\r\n')*2 )
+
+
+    def test_spawn_expect_ascii_unicode(self):
+        # A bytes-based spawn should be able to handle ASCII-only unicode, for
+        # backwards compatibility.
+        p = pexpect.spawn('cat')
+        p.sendline('Camelot')
+        p.expect('Camelot')
+
+        p.sendline('Aargh')
+        p.sendline('AÃ¥rgh')
+        p.expect_exact('Aargh')
+
+        p.sendeof()
+        p.expect(pexpect.EOF)
+
+    def test_spawn_send_unicode(self):
+        # A bytes-based spawn should be able to send arbitrary unicode
+        p = pexpect.spawn('cat')
+        p.sendline('3½')
+        p.sendeof()
+        p.expect(pexpect.EOF)
+
+    def test_spawn_utf8_incomplete(self):
+        # This test case ensures correct incremental decoding, which
+        # otherwise fails when the stream inspected by os.read()
+        # does not align exactly at a utf-8 multibyte boundry:
+        #    UnicodeDecodeError: 'utf8' codec can't decode byte 0xe2 in
+        #                        position 0: unexpected end of data
+        p = pexpect.spawnu('cat', maxread=1)
+        p.sendline('▁▂▃▄▅▆▇█')
+        p.sendeof()
+        p.expect('▁▂▃▄▅▆▇█')
+
+    def test_readline_bin_echo(self):
+        # Test using readline() with spawnu objects. pexpect 3.2 had threw
+        # a TypeError when concatenating a bytestring to a unicode type.
+
+        # given,
+        child = pexpect.spawnu('echo', ['input', ])
+
+        # exercise,
+        assert child.readline() == 'input' + child.crlf
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(UnicodeTests, 'test')
diff --git a/third_party/pexpect/tests/test_which.py b/third_party/pexpect/tests/test_which.py
new file mode 100644
index 0000000..bda3333
--- /dev/null
+++ b/third_party/pexpect/tests/test_which.py
@@ -0,0 +1,269 @@
+import subprocess
+import tempfile
+import shutil
+import errno
+import os
+
+import pexpect
+from . import PexpectTestCase
+
+import pytest
+
+
+class TestCaseWhich(PexpectTestCase.PexpectTestCase):
+    " Tests for pexpect.which(). "
+
+    def test_which_finds_ls(self):
+        " which() can find ls(1). "
+        exercise = pexpect.which("ls")
+        assert exercise is not None
+        assert exercise.startswith('/')
+
+    def test_os_defpath_which(self):
+        " which() finds an executable in $PATH and returns its abspath. "
+        fname = 'cc'
+        bin_dir = tempfile.mkdtemp()
+        bin_path = os.path.join(bin_dir, fname)
+        save_path = os.environ['PATH']
+        save_defpath = os.defpath
+
+        try:
+            # setup
+            os.environ['PATH'] = ''
+            os.defpath = bin_dir
+            with open(bin_path, 'w') as fp:
+                pass
+
+            # given non-executable,
+            os.chmod(bin_path, 0o400)
+
+            # exercise absolute and relative,
+            assert pexpect.which(bin_path) is None
+            assert pexpect.which(fname) is None
+
+            # given executable,
+            os.chmod(bin_path, 0o700)
+
+            # exercise absolute and relative,
+            assert pexpect.which(bin_path) == bin_path
+            assert pexpect.which(fname) == bin_path
+
+        finally:
+            # restore,
+            os.environ['PATH'] = save_path
+            os.defpath = save_defpath
+
+            # destroy scratch files and folders,
+            if os.path.exists(bin_path):
+                os.unlink(bin_path)
+            if os.path.exists(bin_dir):
+                os.rmdir(bin_dir)
+
+    def test_path_search_which(self):
+        " which() finds an executable in $PATH and returns its abspath. "
+        fname = 'gcc'
+        bin_dir = tempfile.mkdtemp()
+        bin_path = os.path.join(bin_dir, fname)
+        save_path = os.environ['PATH']
+        try:
+            # setup
+            os.environ['PATH'] = bin_dir
+            with open(bin_path, 'w') as fp:
+                pass
+
+            # given non-executable,
+            os.chmod(bin_path, 0o400)
+
+            # exercise absolute and relative,
+            assert pexpect.which(bin_path) is None
+            assert pexpect.which(fname) is None
+
+            # given executable,
+            os.chmod(bin_path, 0o700)
+
+            # exercise absolute and relative,
+            assert pexpect.which(bin_path) == bin_path
+            assert pexpect.which(fname) == bin_path
+
+        finally:
+            # restore,
+            os.environ['PATH'] = save_path
+
+            # destroy scratch files and folders,
+            if os.path.exists(bin_path):
+                os.unlink(bin_path)
+            if os.path.exists(bin_dir):
+                os.rmdir(bin_dir)
+
+    def test_which_follows_symlink(self):
+        " which() follows symlinks and returns its path. "
+        fname = 'original'
+        symname = 'extra-crispy'
+        bin_dir = tempfile.mkdtemp()
+        bin_path = os.path.join(bin_dir, fname)
+        sym_path = os.path.join(bin_dir, symname)
+        save_path = os.environ['PATH']
+        try:
+            # setup
+            os.environ['PATH'] = bin_dir
+            with open(bin_path, 'w') as fp:
+                pass
+            os.chmod(bin_path, 0o400)
+            os.symlink(bin_path, sym_path)
+
+            # should not be found because symlink points to non-executable
+            assert pexpect.which(symname) is None
+
+            # but now it should -- because it is executable
+            os.chmod(bin_path, 0o700)
+            assert pexpect.which(symname) == sym_path
+
+        finally:
+            # restore,
+            os.environ['PATH'] = save_path
+
+            # destroy scratch files, symlinks, and folders,
+            if os.path.exists(sym_path):
+                os.unlink(sym_path)
+            if os.path.exists(bin_path):
+                os.unlink(bin_path)
+            if os.path.exists(bin_dir):
+                os.rmdir(bin_dir)
+
+    def test_which_should_not_match_folders(self):
+        " Which does not match folders, even though they are executable. "
+        # make up a path and insert a folder that is 'executable', a naive
+        # implementation might match (previously pexpect versions 3.2 and
+        # sh versions 1.0.8, reported by @lcm337.)
+        fname = 'g++'
+        bin_dir = tempfile.mkdtemp()
+        bin_dir2 = os.path.join(bin_dir, fname)
+        save_path = os.environ['PATH']
+        try:
+            os.environ['PATH'] = bin_dir
+            os.mkdir(bin_dir2, 0o755)
+            # should not be found because it is not executable *file*,
+            # but rather, has the executable bit set, as a good folder
+            # should -- it should not be returned because it fails isdir()
+            exercise = pexpect.which(fname)
+            assert exercise is None
+
+        finally:
+            # restore,
+            os.environ['PATH'] = save_path
+            # destroy scratch folders,
+            for _dir in (bin_dir2, bin_dir,):
+                if os.path.exists(_dir):
+                    os.rmdir(_dir)
+
+    def test_which_should_match_other_group_user(self):
+        " which() returns executables by other, group, and user ownership. "
+        # create an executable and test that it is found using which() for
+        # each of the 'other', 'group', and 'user' permission bits.
+        fname = 'g77'
+        bin_dir = tempfile.mkdtemp()
+        bin_path = os.path.join(bin_dir, fname)
+        save_path = os.environ['PATH']
+        try:
+            # setup
+            os.environ['PATH'] = bin_dir
+
+            # an interpreted script requires the ability to read,
+            # whereas a binary program requires only to be executable.
+            #
+            # to gain access to a binary program, we make a copy of
+            # the existing system program echo(1).
+            bin_echo = None
+            for pth in ('/bin/echo', '/usr/bin/echo'):
+                if os.path.exists(pth):
+                    bin_echo = pth
+                    break
+            bin_which = None
+            for pth in ('/bin/which', '/usr/bin/which'):
+                if os.path.exists(pth):
+                    bin_which = pth
+                    break
+            if not bin_echo or not bin_which:
+                pytest.skip('needs `echo` and `which` binaries')
+            shutil.copy(bin_echo, bin_path)
+            isroot = os.getuid() == 0
+            for should_match, mode in (
+                # note that although the file may have matching 'group' or
+                # 'other' executable permissions, it is *not* executable
+                # because the current uid is the owner of the file -- which
+                # takes precedence
+                (False,  0o000),   # ----------, no
+                (isroot, 0o001),   # ---------x, no
+                (isroot, 0o010),   # ------x---, no
+                (True,   0o100),   # ---x------, yes
+                (False,  0o002),   # --------w-, no
+                (False,  0o020),   # -----w----, no
+                (False,  0o200),   # --w-------, no
+                (isroot, 0o003),   # --------wx, no
+                (isroot, 0o030),   # -----wx---, no
+                (True,   0o300),   # --wx------, yes
+                (False,  0o004),   # -------r--, no
+                (False,  0o040),   # ----r-----, no
+                (False,  0o400),   # -r--------, no
+                (isroot, 0o005),   # -------r-x, no
+                (isroot, 0o050),   # ----r-x---, no
+                (True,   0o500),   # -r-x------, yes
+                (False,  0o006),   # -------rw-, no
+                (False,  0o060),   # ----rw----, no
+                (False,  0o600),   # -rw-------, no
+                (isroot, 0o007),   # -------rwx, no
+                (isroot, 0o070),   # ----rwx---, no
+                (True,   0o700),   # -rwx------, yes
+                (isroot, 0o4001),  # ---S-----x, no
+                (isroot, 0o4010),  # ---S--x---, no
+                (True,   0o4100),  # ---s------, yes
+                (isroot, 0o4003),  # ---S----wx, no
+                (isroot, 0o4030),  # ---S-wx---, no
+                (True,   0o4300),  # --ws------, yes
+                (isroot, 0o2001),  # ------S--x, no
+                (isroot, 0o2010),  # ------s---, no
+                (True,   0o2100),  # ---x--S---, yes
+
+            ):
+                mode_str = '{0:0>4o}'.format(mode)
+
+                # given file mode,
+                os.chmod(bin_path, mode)
+
+                # exercise whether we may execute
+                can_execute = True
+                try:
+                    subprocess.Popen(fname).wait() == 0
+                except OSError as err:
+                    if err.errno != errno.EACCES:
+                        raise
+                    # permission denied
+                    can_execute = False
+
+                assert should_match == can_execute, (
+                    should_match, can_execute, mode_str)
+
+                # exercise whether which(1) would match
+                proc = subprocess.Popen((bin_which, fname),
+                                        env={'PATH': bin_dir},
+                                        stdout=subprocess.PIPE)
+                bin_which_match = bool(not proc.wait())
+                assert should_match == bin_which_match, (
+                    should_match, bin_which_match, mode_str)
+
+                # finally, exercise pexpect's which(1) matches
+                # the same.
+                pexpect_match = bool(pexpect.which(fname))
+
+                assert should_match == pexpect_match == bin_which_match, (
+                    should_match, pexpect_match, bin_which_match, mode_str)
+
+        finally:
+            # restore,
+            os.environ['PATH'] = save_path
+
+            # destroy scratch files and folders,
+            if os.path.exists(bin_path):
+                os.unlink(bin_path)
+            if os.path.exists(bin_dir):
+                os.rmdir(bin_dir)
diff --git a/third_party/pexpect/tests/test_winsize.py b/third_party/pexpect/tests/test_winsize.py
new file mode 100755
index 0000000..75f8c0e
--- /dev/null
+++ b/third_party/pexpect/tests/test_winsize.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+from . import PexpectTestCase
+import time
+
+class TestCaseWinsize(PexpectTestCase.PexpectTestCase):
+
+    def test_winsize (self):
+        '''
+        This tests that the child process can set and get the windows size.
+        This makes use of an external script sigwinch_report.py.
+        '''
+        p1 = pexpect.spawn('%s sigwinch_report.py' % self.PYTHONBIN)
+        p1.expect('READY', timeout=10)
+
+        p1.setwinsize (11,22)
+        index = p1.expect ([pexpect.TIMEOUT, b'SIGWINCH: \(([0-9]*), ([0-9]*)\)'],
+                                       timeout=30)
+        if index == 0:
+            self.fail("TIMEOUT -- this platform may not support sigwinch properly.\n" + str(p1))
+        self.assertEqual(p1.match.group(1, 2), (b"11" ,b"22"))
+        self.assertEqual(p1.getwinsize(), (11, 22))
+
+        time.sleep(1)
+        p1.setwinsize (24,80)
+        index = p1.expect ([pexpect.TIMEOUT, b'SIGWINCH: \(([0-9]*), ([0-9]*)\)'],
+                                       timeout=10)
+        if index == 0:
+            self.fail ("TIMEOUT -- this platform may not support sigwinch properly.\n" + str(p1))
+        self.assertEqual(p1.match.group(1, 2), (b"24" ,b"80"))
+        self.assertEqual(p1.getwinsize(), (24, 80))
+
+        p1.close()
+
+#    def test_parent_resize (self):
+#        pid = os.getpid()
+#        p1 = pexpect.spawn('%s sigwinch_report.py' % self.PYTHONBIN)
+#        time.sleep(10)
+#        p1.setwinsize (11,22)
+#        os.kill (pid, signal.SIGWINCH)
+
+if __name__ == '__main__':
+    unittest.main()
+
+suite = unittest.makeSuite(TestCaseWinsize,'test')
+
+
diff --git a/third_party/pexpect/tests/tetris.data b/third_party/pexpect/tests/tetris.data
new file mode 100644
index 0000000..06b6ce6
--- /dev/null
+++ b/third_party/pexpect/tests/tetris.data
@@ -0,0 +1,3 @@
+
+  J->LEFT  K->ROTATE  L->RIGHT  SPACE->DROP  P->PAUSE  Q->QUIT
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX        XXXXXXXXXX        XXXXXXXXXX        XXXXXXXXXX        XXXXXXXXXXXX  XX        XXXXXXXXXXXX  XXXX  XX        XXXXXXXXXXXXXXXX        XXXXXXXXXX        XXXXXXXXXXXXXXXXXXXX      XXXXXXXX  XX  XXXX    
   [3;40
 HXXXXXXXX  XX  XXXX  XX  XXXX  XX  XXXXXXXXXXXXXXXX      XXXXXXXX      XXXXXXXX        XXXXXXXXXXXXXXXXXXXX      XXXXXXXX  XX  XXXX  XX  XXXX      XXXXXXXXXX      XXXXXX  XXXXXX    XX      XXXXXXXX        XXXXXXXXXXXXXXXX  XXXXXXXXXX  XX  XX      XXXXXXXXXX  XX  XXXX  XX  XX[2
 1;50HXX
 [2;32H      XXXXXXXXXX        XXXXXXXXXXXXXXXXXXXX  XX  XXXX      XXXXXXXX  XX  XXXX  XX  XXXX  XX  XXXX      XXXXXXXXXXXX        XXXXXXXXXXXXXXXXXXXXXX  XX        XXXXXXXXXXXX  XXXX  XXXXXXXXXX        XXXXXXXXXX        XXXXXXXXXXXXXXXX    XXXXXXXXXXXXXXXXXX  XXXXXXXXXX  XX  XXXX  XX  XXXX  
 XX[2;42
 H  XXXX    XXXXXX        XXXXXXXXXXXXXXXXXXXXXX  XX  XX      XXXXXXXXXX  XX  XXXX  XX  XXXXXXXX        XXXXXXXXXXXXXXXXXXXX  XXXX        XXXXXXXXXXXX      XXXXXX  XXXX  XXXXXX    XXXX      XXXXXX  XXXX        XXXXXXXXXXXXXXXXXXXXXX  XX  XXXX  XX  XX  XX  XXXXXXXX  XX  
 X
 X  XXXX  XX      XXXXXXXX        XXXXXXXXXXXXXXXXXXXX  XXXX      XXXXXX  XX  XX  XXXXXXXX  XXXXXX    XX  XXXXXX      XXXXXX  XXXX        XXXXXXXXXXXXXXXXXXXX      XXXXXXXX  XX  XXXXXX    XX    XXXXXXXXXX  XX  XXXXXX      XXXXXX  XX  XX  XX    XXXXXX        XXXXXXXX
 
 XXXXXXXXXXXX    XX  XXXXXX  XX    XXXXXXXX  XX    XXXXXX        XXXXXXXXXXXXXXXXXXXX  XX  XXXX      XXXXXXXXXX      XXXXXX  XX  XX  XXXX  XXXXXX    XX  XX  XXXX      XXXXXXXXXXXX      XXXX        XXXXXXXXXXXXXXXXXX  XXXXXX  XX  XX  XXXXXXXX  XX  XXXX  XX  XX  XX  
 XX[21;5
 0HXXXX  XX  XX  XX    XXXXXX        XXXXXXXXXXXXXXXXXX  XXXXXXXXXXXX  XX  XXXXXX  XX  XXXXXX    XXXXXX        XXXXXXXXXXXXXXXX  XXXXXXXX    XX  XXXXXX  XXXXXX        XXXXXXXXXXXXXXXXXXXX        XXXXXXXXXXXXXXXXXXXX  XXXXXX  XX  XX  XXXXXXXX  XX  XXXX
   [2;34
 HXX  XX        XXXXXXXXXXXXXXXXXXXX  XX  XXXX    XX  XX  XX  XXXXXXXX  XX    XXXXXXXX  XX  XXXX  XX    XXXXXXXXXXXXXXXX  XXXX  XXXXXXXX  XX  XX  XXXX  XX  XXXX  XX  XX  XX  XXXX    XXXXXXXX  XX  XX  XX        XXXXXXXXXXXXXXXXXXXX  XX  XXXX    XX  XX  XX  XXXXXXXX
 XX[21;5
 0HXXXXXX  XXXX      XXXXXXXXXXXXXXXXXXXX  XXXXXXXXXXXX  XX  XXXXXX  XX  XX    XXXXXXXXXXXXXX  XXXXXXXXXXXXXXXXXXXXXXXX    XXXXXXXXXXXXXX
diff --git a/third_party/pexpect/tests/ticker.py b/third_party/pexpect/tests/ticker.py
new file mode 100755
index 0000000..5ecc1c2
--- /dev/null
+++ b/third_party/pexpect/tests/ticker.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+    This license is approved by the OSI and FSF as GPL-compatible.
+        http://opensource.org/licenses/isc-license.txt
+
+    Copyright (c) 2012, Noah Spurrier <noah at noah.org>
+    PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+    PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+    COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import time, sys
+
+for i in range(5):
+  print "tick"
+  time.sleep(1)
+
+sys.exit(0)
diff --git a/third_party/pexpect/tests/torturet.vt b/third_party/pexpect/tests/torturet.vt
new file mode 100644
index 0000000..65f965b
--- /dev/null
+++ b/third_party/pexpect/tests/torturet.vt
@@ -0,0 +1,61 @@
+\<>PrEM1\[?4h
+#6(0a`opqrs`(B      This is the       (0`srqpo`a(B
+#3VT100 series Torture Test Demonstration.
+#4VT100 series Torture Test Demonstration.
+#6       Watch the blinking lights        
+
+
+
+PrEM0\
+
+This file is a VT100-series Torture Test.  It demonstrates all the visual
+attributes of the VT100 terminal.
+
+The top line is double-width/single-height with inverse-video line-drawing
+characters.  The 2nd and 3rd lines are double-width/double-height in bold
+inverse video.  They also show the limited scrolling region.
+
+The remaining lines will show NORMAL, BOLD, BLINK, INVERSE, and all 16
+combinations of those 4 attributes.  They show that there is a difference
+between an underscore character and the underline attribute, and that
+lower-case decenders go below the underline.
+
+A window pane is drawn in the lower right to show how the line-drawing set
+can be used.  At the lower left is the character set double-wide/double-high
+to show the dot-matrix used.  Upper-case characters are 8 by 7 in a 10 by 10
+character cell, with 1 blank row on top and 2 on the bottom.  The underline
+attribute uses the first bottom blank row, lower-case decenders use both.
+
+
+
+This is a normal line __________________________________________________y_
+This is a bold line (normal unless the Advanced Video Option is installed)
+This line is underlined _ "       "       "       "       "       "    _y_
+This is a blinking line _ "       "       "       "       "       "    _y_
+This is inverse video _ (underlined if no AVO and cursor is underline) _y_
+Normal gjpqy Underline   Blink   Underline+Blink gjpqy
+Bold   gjpqy Underline   Blink   Underline+Blink gjpqy
+Inverse      Underline   Blink   Underline+Blink
+Bold+Inverse Underline   Blink   Underline+Blink
+PrEM1\
+#6This is double width
+#3This is double height
+#4This is double height
+#6_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy
+#3_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy
+#4_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy
+ACEGIKMOQSUWY02468iy
+_BDFHJLNPRTVXZ13579o
+_BDFHJLNPRTVXZ13579o
+(0#6`abcdefghijklmnopqrstuvwxyz{|}~ lqwqk
+#3`abcdefghijklmnopqrstuvwxyz{|}~ tqnqu
+#4`abcdefghijklmnopqrstuvwxyz{|}~ tqnqu
+acegikmoqsuwy{}
+`bdfhjlnprtvxz|~
+`bdfhjlnprtvxz|~(B
+#6`abcdefghijklmnopqrstuvwxyz{|}~(0 mqvqj(B
+acegikmoqsuwy{}
+PrEM0\ $PrEM0 works on GIGI 
+   This test created by Joe Smith, 8-May-85   
+
+
diff --git a/third_party/pexpect/tests/utils.py b/third_party/pexpect/tests/utils.py
new file mode 100644
index 0000000..dcd3aa0
--- /dev/null
+++ b/third_party/pexpect/tests/utils.py
@@ -0,0 +1,7 @@
+import os
+
+def no_coverage_env():
+    "Return a copy of os.environ that won't trigger coverage measurement."
+    env = os.environ.copy()
+    env.pop('COV_CORE_SOURCE', None)
+    return env
\ No newline at end of file
diff --git a/third_party/pexpect/tools/display-sighandlers.py b/third_party/pexpect/tools/display-sighandlers.py
new file mode 100755
index 0000000..98445e9
--- /dev/null
+++ b/third_party/pexpect/tools/display-sighandlers.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+# Displays all signals, their values, and their handlers.
+from __future__ import print_function
+import signal
+FMT = '{name:<10} {value:<5} {description}'
+
+# header
+print(FMT.format(name='name', value='value', description='description'))
+print('-' * (33))
+
+for name, value in [(signal_name, getattr(signal, signal_name))
+                    for signal_name in dir(signal)
+                    if signal_name.startswith('SIG')
+                    and not signal_name.startswith('SIG_')]:
+    handler = signal.getsignal(value)
+    description = {
+        signal.SIG_IGN: "ignored(SIG_IGN)",
+        signal.SIG_DFL: "default(SIG_DFL)"
+    }.get(handler, handler)
+    print(FMT.format(name=name, value=value, description=description))
diff --git a/third_party/pexpect/tools/display-terminalinfo.py b/third_party/pexpect/tools/display-terminalinfo.py
new file mode 100755
index 0000000..15911d4
--- /dev/null
+++ b/third_party/pexpect/tools/display-terminalinfo.py
@@ -0,0 +1,209 @@
+#!/usr/bin/env python
+""" Display known information about our terminal. """
+from __future__ import print_function
+import termios
+import locale
+import sys
+import os
+
+BITMAP_IFLAG = {
+    'IGNBRK': 'ignore BREAK condition',
+    'BRKINT': 'map BREAK to SIGINTR',
+    'IGNPAR': 'ignore (discard) parity errors',
+    'PARMRK': 'mark parity and framing errors',
+    'INPCK': 'enable checking of parity errors',
+    'ISTRIP': 'strip 8th bit off chars',
+    'INLCR': 'map NL into CR',
+    'IGNCR': 'ignore CR',
+    'ICRNL': 'map CR to NL (ala CRMOD)',
+    'IXON': 'enable output flow control',
+    'IXOFF': 'enable input flow control',
+    'IXANY': 'any char will restart after stop',
+    'IMAXBEL': 'ring bell on input queue full',
+    'IUCLC': 'translate upper case to lower case',
+}
+
+BITMAP_OFLAG = {
+    'OPOST': 'enable following output processing',
+    'ONLCR': 'map NL to CR-NL (ala CRMOD)',
+    'OXTABS': 'expand tabs to spaces',
+    'ONOEOT': 'discard EOT\'s `^D\' on output)',
+    'OCRNL': 'map CR to NL',
+    'OLCUC': 'translate lower case to upper case',
+    'ONOCR': 'No CR output at column 0',
+    'ONLRET': 'NL performs CR function',
+}
+
+BITMAP_CFLAG = {
+    'CSIZE': 'character size mask',
+    'CS5': '5 bits (pseudo)',
+    'CS6': '6 bits',
+    'CS7': '7 bits',
+    'CS8': '8 bits',
+    'CSTOPB': 'send 2 stop bits',
+    'CREAD': 'enable receiver',
+    'PARENB': 'parity enable',
+    'PARODD': 'odd parity, else even',
+    'HUPCL': 'hang up on last close',
+    'CLOCAL': 'ignore modem status lines',
+    'CCTS_OFLOW': 'CTS flow control of output',
+    'CRTSCTS': 'same as CCTS_OFLOW',
+    'CRTS_IFLOW': 'RTS flow control of input',
+    'MDMBUF': 'flow control output via Carrier',
+}
+
+BITMAP_LFLAG = {
+    'ECHOKE': 'visual erase for line kill',
+    'ECHOE': 'visually erase chars',
+    'ECHO': 'enable echoing',
+    'ECHONL': 'echo NL even if ECHO is off',
+    'ECHOPRT': 'visual erase mode for hardcopy',
+    'ECHOCTL': 'echo control chars as ^(Char)',
+    'ISIG': 'enable signals INTR, QUIT, [D]SUSP',
+    'ICANON': 'canonicalize input lines',
+    'ALTWERASE': 'use alternate WERASE algorithm',
+    'IEXTEN': 'enable DISCARD and LNEXT',
+    'EXTPROC': 'external processing',
+    'TOSTOP': 'stop background jobs from output',
+    'FLUSHO': 'output being flushed (state)',
+    'NOKERNINFO': 'no kernel output from VSTATUS',
+    'PENDIN': 'XXX retype pending input (state)',
+    'NOFLSH': 'don\'t flush after interrupt',
+}
+
+CTLCHAR_INDEX = {
+    'VEOF': 'EOF',
+    'VEOL': 'EOL',
+    'VEOL2': 'EOL2',
+    'VERASE': 'ERASE',
+    'VWERASE': 'WERASE',
+    'VKILL': 'KILL',
+    'VREPRINT': 'REPRINT',
+    'VINTR': 'INTR',
+    'VQUIT': 'QUIT',
+    'VSUSP': 'SUSP',
+    'VDSUSP': 'DSUSP',
+    'VSTART': 'START',
+    'VSTOP': 'STOP',
+    'VLNEXT': 'LNEXT',
+    'VDISCARD': 'DISCARD',
+    'VMIN': '---',
+    'VTIME': '---',
+    'VSTATUS': 'STATUS',
+}
+
+
+def display_bitmask(kind, bitmap, value):
+    """ Display all matching bitmask values for ``value`` given ``bitmap``. """
+    col1_width = max(map(len, list(bitmap.keys()) + [kind]))
+    col2_width = 7
+    FMT = '{name:>{col1_width}} {value:>{col2_width}}   {description}'
+    print(FMT.format(name=kind,
+                     value='Value',
+                     description='Description',
+                     col1_width=col1_width,
+                     col2_width=col2_width))
+    print('{0} {1}   {2}'.format('-' * col1_width,
+                                 '-' * col2_width,
+                                 '-' * max(map(len, bitmap.values()))))
+    for flag_name, description in bitmap.items():
+        try:
+            bitmask = getattr(termios, flag_name)
+            bit_val = 'on' if bool(value & bitmask) else 'off'
+        except AttributeError:
+            bit_val = 'undef'
+        print(FMT.format(name=flag_name,
+                         value=bit_val,
+                         description=description,
+                         col1_width=col1_width,
+                         col2_width=col2_width))
+    print()
+
+
+def display_ctl_chars(index, cc):
+    """ Display all control character indicies, names, and values. """
+    title = 'Special Character'
+    col1_width = len(title)
+    col2_width = max(map(len, index.values()))
+    FMT = '{idx:<{col1_width}}   {name:<{col2_width}} {value}'
+    print('Special line Characters'.center(40).rstrip())
+    print(FMT.format(idx='Index',
+                     name='Name',
+                     value='Value',
+                     col1_width=col1_width,
+                     col2_width=col2_width))
+    print('{0}   {1} {2}'.format('-' * col1_width,
+                                 '-' * col2_width,
+                                 '-' * 10))
+    for index_name, name in index.items():
+        try:
+            index = getattr(termios, index_name)
+            value = cc[index]
+            if value == b'\xff':
+                value = '_POSIX_VDISABLE'
+            else:
+                value = repr(value)
+        except AttributeError:
+            value = 'undef'
+        print(FMT.format(idx=index_name,
+                         name=name,
+                         value=value,
+                         col1_width=col1_width,
+                         col2_width=col2_width))
+    print()
+
+
+def display_conf(kind, names, getter):
+    col1_width = max(map(len, names))
+    FMT = '{name:>{col1_width}}   {value}'
+    print(FMT.format(name=kind,
+                     value='value',
+                     col1_width=col1_width))
+    print('{0} {1}'.format('-' * col1_width, '-' * 27))
+    for name in names:
+        try:
+            value = getter(name)
+        except OSError as err:
+            value = err
+        print(FMT.format(name=name, value=value, col1_width=col1_width))
+    print()
+
+
+def main():
+    fd = sys.stdin.fileno()
+    locale.setlocale(locale.LC_ALL, '')
+    encoding = locale.getpreferredencoding()
+
+    print('os.isatty({0}) => {1}'.format(fd, os.isatty(fd)))
+    print('locale.getpreferredencoding() => {0}'.format(encoding))
+
+    display_conf(kind='pathconf',
+                 names=os.pathconf_names,
+                 getter=lambda name: os.fpathconf(fd, name))
+
+    try:
+        (iflag, oflag, cflag, lflag, ispeed, ospeed, cc
+         ) = termios.tcgetattr(fd)
+    except termios.error as err:
+        print('stdin is not a typewriter: {0}'.format(err))
+    else:
+        display_bitmask(kind='Input Mode',
+                        bitmap=BITMAP_IFLAG,
+                        value=iflag)
+        display_bitmask(kind='Output Mode',
+                        bitmap=BITMAP_OFLAG,
+                        value=oflag)
+        display_bitmask(kind='Control Mode',
+                        bitmap=BITMAP_CFLAG,
+                        value=cflag)
+        display_bitmask(kind='Local Mode',
+                        bitmap=BITMAP_LFLAG,
+                        value=lflag)
+        display_ctl_chars(index=CTLCHAR_INDEX,
+                          cc=cc)
+        print('os.ttyname({0}) => {1}'.format(fd, os.ttyname(fd)))
+        print('os.ctermid() => {0}'.format(os.ttyname(fd)))
+
+
+if __name__ == '__main__':
+    main()
diff --git a/third_party/pexpect/tools/teamcity-coverage-report.sh b/third_party/pexpect/tools/teamcity-coverage-report.sh
new file mode 100755
index 0000000..2e32241
--- /dev/null
+++ b/third_party/pexpect/tools/teamcity-coverage-report.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# This is to be executed by each individual OS test. It only
+# combines coverage files and reports locally to the given
+# TeamCity build configuration.
+set -e
+set -o pipefail
+[ -z ${TEMP} ] && TEMP=/tmp
+
+# combine all .coverage* files,
+coverage combine
+
+# create ascii report,
+report_file=$(mktemp $TEMP/coverage.XXXXX)
+coverage report --rcfile=`dirname $0`/../.coveragerc > "${report_file}" 2>/dev/null
+
+# Report Code Coverage for TeamCity, using 'Service Messages',
+# https://confluence.jetbrains.com/display/TCD8/How+To...#HowTo...-ImportcoverageresultsinTeamCity
+# https://confluence.jetbrains.com/display/TCD8/Custom+Chart#CustomChart-DefaultStatisticsValuesProvidedbyTeamCity
+total_no_lines=$(awk '/TOTAL/{printf("%s",$2)}' < "${report_file}")
+total_no_misses=$(awk '/TOTAL/{printf("%s",$3)}' < "${report_file}")
+total_no_covered=$((${total_no_lines} - ${total_no_misses}))
+echo "##teamcity[buildStatisticValue key='CodeCoverageAbsLTotal' value='""${total_no_lines}""']"
+echo "##teamcity[buildStatisticValue key='CodeCoverageAbsLCovered' value='""${total_no_covered}""']"
+
+# Display for human consumption and remove ascii file.
+cat "${report_file}"
+rm "${report_file}"
diff --git a/third_party/pexpect/tools/teamcity-runtests.sh b/third_party/pexpect/tools/teamcity-runtests.sh
new file mode 100755
index 0000000..b74f179
--- /dev/null
+++ b/third_party/pexpect/tools/teamcity-runtests.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+#
+# This script assumes that the project 'ptyprocess' is
+# available in the parent of the project's folder.
+set -e
+set -o pipefail
+
+if [ -z $1 ]; then
+	echo "$0 (2.6|2.7|3.3|3.4)"
+	exit 1
+fi
+
+export PYTHONIOENCODING=UTF8
+export LANG=en_US.UTF-8
+
+pyversion=$1
+here=$(cd `dirname $0`; pwd)
+osrel=$(uname -s)
+venv=teamcity-pexpect
+venv_wrapper=$(which virtualenvwrapper.sh)
+
+if [ -z $venv_wrapper ]; then
+	echo "virtualenvwrapper.sh not found in PATH." >&2
+	exit 1
+fi
+
+. ${venv_wrapper}
+workon ${venv} || mkvirtualenv -p `which python${pyversion}` ${venv} || true
+
+# install ptyprocess
+cd $here/../../ptyprocess
+pip uninstall --yes ptyprocess || true
+python setup.py install
+
+# install all test requirements
+pip install --upgrade pytest-cov coverage coveralls pytest-capturelog
+
+# run tests
+cd $here/..
+ret=0
+py.test \
+	--cov pexpect \
+	--cov-config .coveragerc \
+	--junit-xml=results.${osrel}.py${pyversion}.xml \
+	--verbose \
+	--verbose \
+	|| ret=$?
+
+if [ $ret -ne 0 ]; then
+	# we always exit 0, preferring instead the jUnit XML
+	# results to be the dominate cause of a failed build.
+	echo "py.test returned exit code ${ret}." >&2
+	echo "the build should detect and report these failing tests." >&2
+fi
+
+# combine all coverage to single file, report for this build,
+# then move into ./build-output/ as a unique artifact to allow
+# the final "Full build" step to combine and report to coveralls.io
+`dirname $0`/teamcity-coverage-report.sh
+mkdir -p build-output
+mv .coverage build-output/.coverage.${osrel}.py{$pyversion}.$RANDOM.$$
diff --git a/third_party/zlib/ChangeLog b/third_party/zlib/ChangeLog
index 7f6869d..f22aaba 100644
--- a/third_party/zlib/ChangeLog
+++ b/third_party/zlib/ChangeLog
@@ -1,6 +1,623 @@
 
                 ChangeLog file for zlib
 
+Changes in 1.2.8 (28 Apr 2013)
+- Update contrib/minizip/iowin32.c for Windows RT [Vollant]
+- Do not force Z_CONST for C++
+- Clean up contrib/vstudio [Ro§]
+- Correct spelling error in zlib.h
+- Fix mixed line endings in contrib/vstudio
+
+Changes in 1.2.7.3 (13 Apr 2013)
+- Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc
+
+Changes in 1.2.7.2 (13 Apr 2013)
+- Change check for a four-byte type back to hexadecimal
+- Fix typo in win32/Makefile.msc
+- Add casts in gzwrite.c for pointer differences
+
+Changes in 1.2.7.1 (24 Mar 2013)
+- Replace use of unsafe string functions with snprintf if available
+- Avoid including stddef.h on Windows for Z_SOLO compile [Niessink]
+- Fix gzgetc undefine when Z_PREFIX set [Turk]
+- Eliminate use of mktemp in Makefile (not always available)
+- Fix bug in 'F' mode for gzopen()
+- Add inflateGetDictionary() function
+- Correct comment in deflate.h
+- Use _snprintf for snprintf in Microsoft C
+- On Darwin, only use /usr/bin/libtool if libtool is not Apple
+- Delete "--version" file if created by "ar --version" [Richard G.]
+- Fix configure check for veracity of compiler error return codes
+- Fix CMake compilation of static lib for MSVC2010 x64
+- Remove unused variable in infback9.c
+- Fix argument checks in gzlog_compress() and gzlog_write()
+- Clean up the usage of z_const and respect const usage within zlib
+- Clean up examples/gzlog.[ch] comparisons of different types
+- Avoid shift equal to bits in type (caused endless loop)
+- Fix unintialized value bug in gzputc() introduced by const patches
+- Fix memory allocation error in examples/zran.c [Nor]
+- Fix bug where gzopen(), gzclose() would write an empty file
+- Fix bug in gzclose() when gzwrite() runs out of memory
+- Check for input buffer malloc failure in examples/gzappend.c
+- Add note to contrib/blast to use binary mode in stdio
+- Fix comparisons of differently signed integers in contrib/blast
+- Check for invalid code length codes in contrib/puff
+- Fix serious but very rare decompression bug in inftrees.c
+- Update inflateBack() comments, since inflate() can be faster
+- Use underscored I/O function names for WINAPI_FAMILY
+- Add _tr_flush_bits to the external symbols prefixed by --zprefix
+- Add contrib/vstudio/vc10 pre-build step for static only
+- Quote --version-script argument in CMakeLists.txt
+- Don't specify --version-script on Apple platforms in CMakeLists.txt
+- Fix casting error in contrib/testzlib/testzlib.c
+- Fix types in contrib/minizip to match result of get_crc_table()
+- Simplify contrib/vstudio/vc10 with 'd' suffix
+- Add TOP support to win32/Makefile.msc
+- Suport i686 and amd64 assembler builds in CMakeLists.txt
+- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h
+- Add vc11 and vc12 build files to contrib/vstudio
+- Add gzvprintf() as an undocumented function in zlib
+- Fix configure for Sun shell
+- Remove runtime check in configure for four-byte integer type
+- Add casts and consts to ease user conversion to C++
+- Add man pages for minizip and miniunzip
+- In Makefile uninstall, don't rm if preceding cd fails
+- Do not return Z_BUF_ERROR if deflateParam() has nothing to write
+
+Changes in 1.2.7 (2 May 2012)
+- Replace use of memmove() with a simple copy for portability
+- Test for existence of strerror
+- Restore gzgetc_ for backward compatibility with 1.2.6
+- Fix build with non-GNU make on Solaris
+- Require gcc 4.0 or later on Mac OS X to use the hidden attribute
+- Include unistd.h for Watcom C
+- Use __WATCOMC__ instead of __WATCOM__
+- Do not use the visibility attribute if NO_VIZ defined
+- Improve the detection of no hidden visibility attribute
+- Avoid using __int64 for gcc or solo compilation
+- Cast to char * in gzprintf to avoid warnings [Zinser]
+- Fix make_vms.com for VAX [Zinser]
+- Don't use library or built-in byte swaps
+- Simplify test and use of gcc hidden attribute
+- Fix bug in gzclose_w() when gzwrite() fails to allocate memory
+- Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen()
+- Fix bug in test/minigzip.c for configure --solo
+- Fix contrib/vstudio project link errors [Mohanathas]
+- Add ability to choose the builder in make_vms.com [Schweda]
+- Add DESTDIR support to mingw32 win32/Makefile.gcc
+- Fix comments in win32/Makefile.gcc for proper usage
+- Allow overriding the default install locations for cmake
+- Generate and install the pkg-config file with cmake
+- Build both a static and a shared version of zlib with cmake
+- Include version symbols for cmake builds
+- If using cmake with MSVC, add the source directory to the includes
+- Remove unneeded EXTRA_CFLAGS from win32/Makefile.gcc [Truta]
+- Move obsolete emx makefile to old [Truta]
+- Allow the use of -Wundef when compiling or using zlib
+- Avoid the use of the -u option with mktemp
+- Improve inflate() documentation on the use of Z_FINISH
+- Recognize clang as gcc
+- Add gzopen_w() in Windows for wide character path names
+- Rename zconf.h in CMakeLists.txt to move it out of the way
+- Add source directory in CMakeLists.txt for building examples
+- Look in build directory for zlib.pc in CMakeLists.txt
+- Remove gzflags from zlibvc.def in vc9 and vc10
+- Fix contrib/minizip compilation in the MinGW environment
+- Update ./configure for Solaris, support --64 [Mooney]
+- Remove -R. from Solaris shared build (possible security issue)
+- Avoid race condition for parallel make (-j) running example
+- Fix type mismatch between get_crc_table() and crc_table
+- Fix parsing of version with "-" in CMakeLists.txt [Snider, Ziegler]
+- Fix the path to zlib.map in CMakeLists.txt
+- Force the native libtool in Mac OS X to avoid GNU libtool [Beebe]
+- Add instructions to win32/Makefile.gcc for shared install [Torri]
+
+Changes in 1.2.6.1 (12 Feb 2012)
+- Avoid the use of the Objective-C reserved name "id"
+- Include io.h in gzguts.h for Microsoft compilers
+- Fix problem with ./configure --prefix and gzgetc macro
+- Include gz_header definition when compiling zlib solo
+- Put gzflags() functionality back in zutil.c
+- Avoid library header include in crc32.c for Z_SOLO
+- Use name in GCC_CLASSIC as C compiler for coverage testing, if set
+- Minor cleanup in contrib/minizip/zip.c [Vollant]
+- Update make_vms.com [Zinser]
+- Remove unnecessary gzgetc_ function
+- Use optimized byte swap operations for Microsoft and GNU [Snyder]
+- Fix minor typo in zlib.h comments [Rzesniowiecki]
+
+Changes in 1.2.6 (29 Jan 2012)
+- Update the Pascal interface in contrib/pascal
+- Fix function numbers for gzgetc_ in zlibvc.def files
+- Fix configure.ac for contrib/minizip [Schiffer]
+- Fix large-entry detection in minizip on 64-bit systems [Schiffer]
+- Have ./configure use the compiler return code for error indication
+- Fix CMakeLists.txt for cross compilation [McClure]
+- Fix contrib/minizip/zip.c for 64-bit architectures [Dalsnes]
+- Fix compilation of contrib/minizip on FreeBSD [Marquez]
+- Correct suggested usages in win32/Makefile.msc [Shachar, Horvath]
+- Include io.h for Turbo C / Borland C on all platforms [Truta]
+- Make version explicit in contrib/minizip/configure.ac [Bosmans]
+- Avoid warning for no encryption in contrib/minizip/zip.c [Vollant]
+- Minor cleanup up contrib/minizip/unzip.c [Vollant]
+- Fix bug when compiling minizip with C++ [Vollant]
+- Protect for long name and extra fields in contrib/minizip [Vollant]
+- Avoid some warnings in contrib/minizip [Vollant]
+- Add -I../.. -L../.. to CFLAGS for minizip and miniunzip
+- Add missing libs to minizip linker command
+- Add support for VPATH builds in contrib/minizip
+- Add an --enable-demos option to contrib/minizip/configure
+- Add the generation of configure.log by ./configure
+- Exit when required parameters not provided to win32/Makefile.gcc
+- Have gzputc return the character written instead of the argument
+- Use the -m option on ldconfig for BSD systems [Tobias]
+- Correct in zlib.map when deflateResetKeep was added
+
+Changes in 1.2.5.3 (15 Jan 2012)
+- Restore gzgetc function for binary compatibility
+- Do not use _lseeki64 under Borland C++ [Truta]
+- Update win32/Makefile.msc to build test/*.c [Truta]
+- Remove old/visualc6 given CMakefile and other alternatives
+- Update AS400 build files and documentation [Monnerat]
+- Update win32/Makefile.gcc to build test/*.c [Truta]
+- Permit stronger flushes after Z_BLOCK flushes
+- Avoid extraneous empty blocks when doing empty flushes
+- Permit Z_NULL arguments to deflatePending
+- Allow deflatePrime() to insert bits in the middle of a stream
+- Remove second empty static block for Z_PARTIAL_FLUSH
+- Write out all of the available bits when using Z_BLOCK
+- Insert the first two strings in the hash table after a flush
+
+Changes in 1.2.5.2 (17 Dec 2011)
+- fix ld error: unable to find version dependency 'ZLIB_1.2.5'
+- use relative symlinks for shared libs
+- Avoid searching past window for Z_RLE strategy
+- Assure that high-water mark initialization is always applied in deflate
+- Add assertions to fill_window() in deflate.c to match comments
+- Update python link in README
+- Correct spelling error in gzread.c
+- Fix bug in gzgets() for a concatenated empty gzip stream
+- Correct error in comment for gz_make()
+- Change gzread() and related to ignore junk after gzip streams
+- Allow gzread() and related to continue after gzclearerr()
+- Allow gzrewind() and gzseek() after a premature end-of-file
+- Simplify gzseek() now that raw after gzip is ignored
+- Change gzgetc() to a macro for speed (~40% speedup in testing)
+- Fix gzclose() to return the actual error last encountered
+- Always add large file support for windows
+- Include zconf.h for windows large file support
+- Include zconf.h.cmakein for windows large file support
+- Update zconf.h.cmakein on make distclean
+- Merge vestigial vsnprintf determination from zutil.h to gzguts.h
+- Clarify how gzopen() appends in zlib.h comments
+- Correct documentation of gzdirect() since junk at end now ignored
+- Add a transparent write mode to gzopen() when 'T' is in the mode
+- Update python link in zlib man page
+- Get inffixed.h and MAKEFIXED result to match
+- Add a ./config --solo option to make zlib subset with no libary use
+- Add undocumented inflateResetKeep() function for CAB file decoding
+- Add --cover option to ./configure for gcc coverage testing
+- Add #define ZLIB_CONST option to use const in the z_stream interface
+- Add comment to gzdopen() in zlib.h to use dup() when using fileno()
+- Note behavior of uncompress() to provide as much data as it can
+- Add files in contrib/minizip to aid in building libminizip
+- Split off AR options in Makefile.in and configure
+- Change ON macro to Z_ARG to avoid application conflicts
+- Facilitate compilation with Borland C++ for pragmas and vsnprintf
+- Include io.h for Turbo C / Borland C++
+- Move example.c and minigzip.c to test/
+- Simplify incomplete code table filling in inflate_table()
+- Remove code from inflate.c and infback.c that is impossible to execute
+- Test the inflate code with full coverage
+- Allow deflateSetDictionary, inflateSetDictionary at any time (in raw)
+- Add deflateResetKeep and fix inflateResetKeep to retain dictionary
+- Fix gzwrite.c to accommodate reduced memory zlib compilation
+- Have inflate() with Z_FINISH avoid the allocation of a window
+- Do not set strm->adler when doing raw inflate
+- Fix gzeof() to behave just like feof() when read is not past end of file
+- Fix bug in gzread.c when end-of-file is reached
+- Avoid use of Z_BUF_ERROR in gz* functions except for premature EOF
+- Document gzread() capability to read concurrently written files
+- Remove hard-coding of resource compiler in CMakeLists.txt [Blammo]
+
+Changes in 1.2.5.1 (10 Sep 2011)
+- Update FAQ entry on shared builds (#13)
+- Avoid symbolic argument to chmod in Makefile.in
+- Fix bug and add consts in contrib/puff [Oberhumer]
+- Update contrib/puff/zeros.raw test file to have all block types
+- Add full coverage test for puff in contrib/puff/Makefile
+- Fix static-only-build install in Makefile.in
+- Fix bug in unzGetCurrentFileInfo() in contrib/minizip [Kuno]
+- Add libz.a dependency to shared in Makefile.in for parallel builds
+- Spell out "number" (instead of "nb") in zlib.h for total_in, total_out
+- Replace $(...) with `...` in configure for non-bash sh [Bowler]
+- Add darwin* to Darwin* and solaris* to SunOS\ 5* in configure [Groffen]
+- Add solaris* to Linux* in configure to allow gcc use [Groffen]
+- Add *bsd* to Linux* case in configure [Bar-Lev]
+- Add inffast.obj to dependencies in win32/Makefile.msc
+- Correct spelling error in deflate.h [Kohler]
+- Change libzdll.a again to libz.dll.a (!) in win32/Makefile.gcc
+- Add test to configure for GNU C looking for gcc in output of $cc -v
+- Add zlib.pc generation to win32/Makefile.gcc [Weigelt]
+- Fix bug in zlib.h for _FILE_OFFSET_BITS set and _LARGEFILE64_SOURCE not
+- Add comment in zlib.h that adler32_combine with len2 < 0 makes no sense
+- Make NO_DIVIDE option in adler32.c much faster (thanks to John Reiser)
+- Make stronger test in zconf.h to include unistd.h for LFS
+- Apply Darwin patches for 64-bit file offsets to contrib/minizip [Slack]
+- Fix zlib.h LFS support when Z_PREFIX used
+- Add updated as400 support (removed from old) [Monnerat]
+- Avoid deflate sensitivity to volatile input data
+- Avoid division in adler32_combine for NO_DIVIDE
+- Clarify the use of Z_FINISH with deflateBound() amount of space
+- Set binary for output file in puff.c
+- Use u4 type for crc_table to avoid conversion warnings
+- Apply casts in zlib.h to avoid conversion warnings
+- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller]
+- Improve inflateSync() documentation to note indeterminancy
+- Add deflatePending() function to return the amount of pending output
+- Correct the spelling of "specification" in FAQ [Randers-Pehrson]
+- Add a check in configure for stdarg.h, use for gzprintf()
+- Check that pointers fit in ints when gzprint() compiled old style
+- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler]
+- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt]
+- Add debug records in assmebler code [Londer]
+- Update RFC references to use http://tools.ietf.org/html/... [Li]
+- Add --archs option, use of libtool to configure for Mac OS X [Borstel]
+
+Changes in 1.2.5 (19 Apr 2010)
+- Disable visibility attribute in win32/Makefile.gcc [Bar-Lev]
+- Default to libdir as sharedlibdir in configure [Nieder]
+- Update copyright dates on modified source files
+- Update trees.c to be able to generate modified trees.h
+- Exit configure for MinGW, suggesting win32/Makefile.gcc
+- Check for NULL path in gz_open [Homurlu]
+
+Changes in 1.2.4.5 (18 Apr 2010)
+- Set sharedlibdir in configure [Torok]
+- Set LDFLAGS in Makefile.in [Bar-Lev]
+- Avoid mkdir objs race condition in Makefile.in [Bowler]
+- Add ZLIB_INTERNAL in front of internal inter-module functions and arrays
+- Define ZLIB_INTERNAL to hide internal functions and arrays for GNU C
+- Don't use hidden attribute when it is a warning generator (e.g. Solaris)
+
+Changes in 1.2.4.4 (18 Apr 2010)
+- Fix CROSS_PREFIX executable testing, CHOST extract, mingw* [Torok]
+- Undefine _LARGEFILE64_SOURCE in zconf.h if it is zero, but not if empty
+- Try to use bash or ksh regardless of functionality of /bin/sh
+- Fix configure incompatibility with NetBSD sh
+- Remove attempt to run under bash or ksh since have better NetBSD fix
+- Fix win32/Makefile.gcc for MinGW [Bar-Lev]
+- Add diagnostic messages when using CROSS_PREFIX in configure
+- Added --sharedlibdir option to configure [Weigelt]
+- Use hidden visibility attribute when available [Frysinger]
+
+Changes in 1.2.4.3 (10 Apr 2010)
+- Only use CROSS_PREFIX in configure for ar and ranlib if they exist
+- Use CROSS_PREFIX for nm [Bar-Lev]
+- Assume _LARGEFILE64_SOURCE defined is equivalent to true
+- Avoid use of undefined symbols in #if with && and ||
+- Make *64 prototypes in gzguts.h consistent with functions
+- Add -shared load option for MinGW in configure [Bowler]
+- Move z_off64_t to public interface, use instead of off64_t
+- Remove ! from shell test in configure (not portable to Solaris)
+- Change +0 macro tests to -0 for possibly increased portability
+
+Changes in 1.2.4.2 (9 Apr 2010)
+- Add consistent carriage returns to readme.txt's in masmx86 and masmx64
+- Really provide prototypes for *64 functions when building without LFS
+- Only define unlink() in minigzip.c if unistd.h not included
+- Update README to point to contrib/vstudio project files
+- Move projects/vc6 to old/ and remove projects/
+- Include stdlib.h in minigzip.c for setmode() definition under WinCE
+- Clean up assembler builds in win32/Makefile.msc [Rowe]
+- Include sys/types.h for Microsoft for off_t definition
+- Fix memory leak on error in gz_open()
+- Symbolize nm as $NM in configure [Weigelt]
+- Use TEST_LDSHARED instead of LDSHARED to link test programs [Weigelt]
+- Add +0 to _FILE_OFFSET_BITS and _LFS64_LARGEFILE in case not defined
+- Fix bug in gzeof() to take into account unused input data
+- Avoid initialization of structures with variables in puff.c
+- Updated win32/README-WIN32.txt [Rowe]
+
+Changes in 1.2.4.1 (28 Mar 2010)
+- Remove the use of [a-z] constructs for sed in configure [gentoo 310225]
+- Remove $(SHAREDLIB) from LIBS in Makefile.in [Creech]
+- Restore "for debugging" comment on sprintf() in gzlib.c
+- Remove fdopen for MVS from gzguts.h
+- Put new README-WIN32.txt in win32 [Rowe]
+- Add check for shell to configure and invoke another shell if needed
+- Fix big fat stinking bug in gzseek() on uncompressed files
+- Remove vestigial F_OPEN64 define in zutil.h
+- Set and check the value of _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE
+- Avoid errors on non-LFS systems when applications define LFS macros
+- Set EXE to ".exe" in configure for MINGW [Kahle]
+- Match crc32() in crc32.c exactly to the prototype in zlib.h [Sherrill]
+- Add prefix for cross-compilation in win32/makefile.gcc [Bar-Lev]
+- Add DLL install in win32/makefile.gcc [Bar-Lev]
+- Allow Linux* or linux* from uname in configure [Bar-Lev]
+- Allow ldconfig to be redefined in configure and Makefile.in [Bar-Lev]
+- Add cross-compilation prefixes to configure [Bar-Lev]
+- Match type exactly in gz_load() invocation in gzread.c
+- Match type exactly of zcalloc() in zutil.c to zlib.h alloc_func
+- Provide prototypes for *64 functions when building zlib without LFS
+- Don't use -lc when linking shared library on MinGW
+- Remove errno.h check in configure and vestigial errno code in zutil.h
+
+Changes in 1.2.4 (14 Mar 2010)
+- Fix VER3 extraction in configure for no fourth subversion
+- Update zlib.3, add docs to Makefile.in to make .pdf out of it
+- Add zlib.3.pdf to distribution
+- Don't set error code in gzerror() if passed pointer is NULL
+- Apply destination directory fixes to CMakeLists.txt [Lowman]
+- Move #cmakedefine's to a new zconf.in.cmakein
+- Restore zconf.h for builds that don't use configure or cmake
+- Add distclean to dummy Makefile for convenience
+- Update and improve INDEX, README, and FAQ
+- Update CMakeLists.txt for the return of zconf.h [Lowman]
+- Update contrib/vstudio/vc9 and vc10 [Vollant]
+- Change libz.dll.a back to libzdll.a in win32/Makefile.gcc
+- Apply license and readme changes to contrib/asm686 [Raiter]
+- Check file name lengths and add -c option in minigzip.c [Li]
+- Update contrib/amd64 and contrib/masmx86/ [Vollant]
+- Avoid use of "eof" parameter in trees.c to not shadow library variable
+- Update make_vms.com for removal of zlibdefs.h [Zinser]
+- Update assembler code and vstudio projects in contrib [Vollant]
+- Remove outdated assembler code contrib/masm686 and contrib/asm586
+- Remove old vc7 and vc8 from contrib/vstudio
+- Update win32/Makefile.msc, add ZLIB_VER_SUBREVISION [Rowe]
+- Fix memory leaks in gzclose_r() and gzclose_w(), file leak in gz_open()
+- Add contrib/gcc_gvmat64 for longest_match and inflate_fast [Vollant]
+- Remove *64 functions from win32/zlib.def (they're not 64-bit yet)
+- Fix bug in void-returning vsprintf() case in gzwrite.c
+- Fix name change from inflate.h in contrib/inflate86/inffas86.c
+- Check if temporary file exists before removing in make_vms.com [Zinser]
+- Fix make install and uninstall for --static option
+- Fix usage of _MSC_VER in gzguts.h and zutil.h [Truta]
+- Update readme.txt in contrib/masmx64 and masmx86 to assemble
+
+Changes in 1.2.3.9 (21 Feb 2010)
+- Expunge gzio.c
+- Move as400 build information to old
+- Fix updates in contrib/minizip and contrib/vstudio
+- Add const to vsnprintf test in configure to avoid warnings [Weigelt]
+- Delete zconf.h (made by configure) [Weigelt]
+- Change zconf.in.h to zconf.h.in per convention [Weigelt]
+- Check for NULL buf in gzgets()
+- Return empty string for gzgets() with len == 1 (like fgets())
+- Fix description of gzgets() in zlib.h for end-of-file, NULL return
+- Update minizip to 1.1 [Vollant]
+- Avoid MSVC loss of data warnings in gzread.c, gzwrite.c
+- Note in zlib.h that gzerror() should be used to distinguish from EOF
+- Remove use of snprintf() from gzlib.c
+- Fix bug in gzseek()
+- Update contrib/vstudio, adding vc9 and vc10 [Kuno, Vollant]
+- Fix zconf.h generation in CMakeLists.txt [Lowman]
+- Improve comments in zconf.h where modified by configure
+
+Changes in 1.2.3.8 (13 Feb 2010)
+- Clean up text files (tabs, trailing whitespace, etc.) [Oberhumer]
+- Use z_off64_t in gz_zero() and gz_skip() to match state->skip
+- Avoid comparison problem when sizeof(int) == sizeof(z_off64_t)
+- Revert to Makefile.in from 1.2.3.6 (live with the clutter)
+- Fix missing error return in gzflush(), add zlib.h note
+- Add *64 functions to zlib.map [Levin]
+- Fix signed/unsigned comparison in gz_comp()
+- Use SFLAGS when testing shared linking in configure
+- Add --64 option to ./configure to use -m64 with gcc
+- Fix ./configure --help to correctly name options
+- Have make fail if a test fails [Levin]
+- Avoid buffer overrun in contrib/masmx64/gvmat64.asm [Simpson]
+- Remove assembler object files from contrib
+
+Changes in 1.2.3.7 (24 Jan 2010)
+- Always gzopen() with O_LARGEFILE if available
+- Fix gzdirect() to work immediately after gzopen() or gzdopen()
+- Make gzdirect() more precise when the state changes while reading
+- Improve zlib.h documentation in many places
+- Catch memory allocation failure in gz_open()
+- Complete close operation if seek forward in gzclose_w() fails
+- Return Z_ERRNO from gzclose_r() if close() fails
+- Return Z_STREAM_ERROR instead of EOF for gzclose() being passed NULL
+- Return zero for gzwrite() errors to match zlib.h description
+- Return -1 on gzputs() error to match zlib.h description
+- Add zconf.in.h to allow recovery from configure modification [Weigelt]
+- Fix static library permissions in Makefile.in [Weigelt]
+- Avoid warnings in configure tests that hide functionality [Weigelt]
+- Add *BSD and DragonFly to Linux case in configure [gentoo 123571]
+- Change libzdll.a to libz.dll.a in win32/Makefile.gcc [gentoo 288212]
+- Avoid access of uninitialized data for first inflateReset2 call [Gomes]
+- Keep object files in subdirectories to reduce the clutter somewhat
+- Remove default Makefile and zlibdefs.h, add dummy Makefile
+- Add new external functions to Z_PREFIX, remove duplicates, z_z_ -> z_
+- Remove zlibdefs.h completely -- modify zconf.h instead
+
+Changes in 1.2.3.6 (17 Jan 2010)
+- Avoid void * arithmetic in gzread.c and gzwrite.c
+- Make compilers happier with const char * for gz_error message
+- Avoid unused parameter warning in inflate.c
+- Avoid signed-unsigned comparison warning in inflate.c
+- Indent #pragma's for traditional C
+- Fix usage of strwinerror() in glib.c, change to gz_strwinerror()
+- Correct email address in configure for system options
+- Update make_vms.com and add make_vms.com to contrib/minizip [Zinser]
+- Update zlib.map [Brown]
+- Fix Makefile.in for Solaris 10 make of example64 and minizip64 [Torok]
+- Apply various fixes to CMakeLists.txt [Lowman]
+- Add checks on len in gzread() and gzwrite()
+- Add error message for no more room for gzungetc()
+- Remove zlib version check in gzwrite()
+- Defer compression of gzprintf() result until need to
+- Use snprintf() in gzdopen() if available
+- Remove USE_MMAP configuration determination (only used by minigzip)
+- Remove examples/pigz.c (available separately)
+- Update examples/gun.c to 1.6
+
+Changes in 1.2.3.5 (8 Jan 2010)
+- Add space after #if in zutil.h for some compilers
+- Fix relatively harmless bug in deflate_fast() [Exarevsky]
+- Fix same problem in deflate_slow()
+- Add $(SHAREDLIBV) to LIBS in Makefile.in [Brown]
+- Add deflate_rle() for faster Z_RLE strategy run-length encoding
+- Add deflate_huff() for faster Z_HUFFMAN_ONLY encoding
+- Change name of "write" variable in inffast.c to avoid library collisions
+- Fix premature EOF from gzread() in gzio.c [Brown]
+- Use zlib header window size if windowBits is 0 in inflateInit2()
+- Remove compressBound() call in deflate.c to avoid linking compress.o
+- Replace use of errno in gz* with functions, support WinCE [Alves]
+- Provide alternative to perror() in minigzip.c for WinCE [Alves]
+- Don't use _vsnprintf on later versions of MSVC [Lowman]
+- Add CMake build script and input file [Lowman]
+- Update contrib/minizip to 1.1 [Svensson, Vollant]
+- Moved nintendods directory from contrib to .
+- Replace gzio.c with a new set of routines with the same functionality
+- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above
+- Update contrib/minizip to 1.1b
+- Change gzeof() to return 0 on error instead of -1 to agree with zlib.h
+
+Changes in 1.2.3.4 (21 Dec 2009)
+- Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility
+- Update comments in configure and Makefile.in for default --shared
+- Fix test -z's in configure [Marquess]
+- Build examplesh and minigzipsh when not testing
+- Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h
+- Import LDFLAGS from the environment in configure
+- Fix configure to populate SFLAGS with discovered CFLAGS options
+- Adapt make_vms.com to the new Makefile.in [Zinser]
+- Add zlib2ansi script for C++ compilation [Marquess]
+- Add _FILE_OFFSET_BITS=64 test to make test (when applicable)
+- Add AMD64 assembler code for longest match to contrib [Teterin]
+- Include options from $SFLAGS when doing $LDSHARED
+- Simplify 64-bit file support by introducing z_off64_t type
+- Make shared object files in objs directory to work around old Sun cc
+- Use only three-part version number for Darwin shared compiles
+- Add rc option to ar in Makefile.in for when ./configure not run
+- Add -WI,-rpath,. to LDFLAGS for OSF 1 V4*
+- Set LD_LIBRARYN32_PATH for SGI IRIX shared compile
+- Protect against _FILE_OFFSET_BITS being defined when compiling zlib
+- Rename Makefile.in targets allstatic to static and allshared to shared
+- Fix static and shared Makefile.in targets to be independent
+- Correct error return bug in gz_open() by setting state [Brown]
+- Put spaces before ;;'s in configure for better sh compatibility
+- Add pigz.c (parallel implementation of gzip) to examples/
+- Correct constant in crc32.c to UL [Leventhal]
+- Reject negative lengths in crc32_combine()
+- Add inflateReset2() function to work like inflateEnd()/inflateInit2()
+- Include sys/types.h for _LARGEFILE64_SOURCE [Brown]
+- Correct typo in doc/algorithm.txt [Janik]
+- Fix bug in adler32_combine() [Zhu]
+- Catch missing-end-of-block-code error in all inflates and in puff
+    Assures that random input to inflate eventually results in an error
+- Added enough.c (calculation of ENOUGH for inftrees.h) to examples/
+- Update ENOUGH and its usage to reflect discovered bounds
+- Fix gzerror() error report on empty input file [Brown]
+- Add ush casts in trees.c to avoid pedantic runtime errors
+- Fix typo in zlib.h uncompress() description [Reiss]
+- Correct inflate() comments with regard to automatic header detection
+- Remove deprecation comment on Z_PARTIAL_FLUSH (it stays)
+- Put new version of gzlog (2.0) in examples with interruption recovery
+- Add puff compile option to permit invalid distance-too-far streams
+- Add puff TEST command options, ability to read piped input
+- Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but
+  _LARGEFILE64_SOURCE not defined
+- Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart
+- Fix deflateSetDictionary() to use all 32K for output consistency
+- Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h)
+- Clear bytes after deflate lookahead to avoid use of uninitialized data
+- Change a limit in inftrees.c to be more transparent to Coverity Prevent
+- Update win32/zlib.def with exported symbols from zlib.h
+- Correct spelling errors in zlib.h [Willem, Sobrado]
+- Allow Z_BLOCK for deflate() to force a new block
+- Allow negative bits in inflatePrime() to delete existing bit buffer
+- Add Z_TREES flush option to inflate() to return at end of trees
+- Add inflateMark() to return current state information for random access
+- Add Makefile for NintendoDS to contrib [Costa]
+- Add -w in configure compile tests to avoid spurious warnings [Beucler]
+- Fix typos in zlib.h comments for deflateSetDictionary()
+- Fix EOF detection in transparent gzread() [Maier]
+
+Changes in 1.2.3.3 (2 October 2006)
+- Make --shared the default for configure, add a --static option
+- Add compile option to permit invalid distance-too-far streams
+- Add inflateUndermine() function which is required to enable above
+- Remove use of "this" variable name for C++ compatibility [Marquess]
+- Add testing of shared library in make test, if shared library built
+- Use ftello() and fseeko() if available instead of ftell() and fseek()
+- Provide two versions of all functions that use the z_off_t type for
+  binary compatibility -- a normal version and a 64-bit offset version,
+  per the Large File Support Extension when _LARGEFILE64_SOURCE is
+  defined; use the 64-bit versions by default when _FILE_OFFSET_BITS
+  is defined to be 64
+- Add a --uname= option to configure to perhaps help with cross-compiling
+
+Changes in 1.2.3.2 (3 September 2006)
+- Turn off silly Borland warnings [Hay]
+- Use off64_t and define _LARGEFILE64_SOURCE when present
+- Fix missing dependency on inffixed.h in Makefile.in
+- Rig configure --shared to build both shared and static [Teredesai, Truta]
+- Remove zconf.in.h and instead create a new zlibdefs.h file
+- Fix contrib/minizip/unzip.c non-encrypted after encrypted [Vollant]
+- Add treebuild.xml (see http://treebuild.metux.de/) [Weigelt]
+
+Changes in 1.2.3.1 (16 August 2006)
+- Add watcom directory with OpenWatcom make files [Daniel]
+- Remove #undef of FAR in zconf.in.h for MVS [Fedtke]
+- Update make_vms.com [Zinser]
+- Use -fPIC for shared build in configure [Teredesai, Nicholson]
+- Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen]
+- Use fdopen() (not _fdopen()) for Interix in zutil.h [BŠck]
+- Add some FAQ entries about the contrib directory
+- Update the MVS question in the FAQ
+- Avoid extraneous reads after EOF in gzio.c [Brown]
+- Correct spelling of "successfully" in gzio.c [Randers-Pehrson]
+- Add comments to zlib.h about gzerror() usage [Brown]
+- Set extra flags in gzip header in gzopen() like deflate() does
+- Make configure options more compatible with double-dash conventions
+  [Weigelt]
+- Clean up compilation under Solaris SunStudio cc [Rowe, Reinholdtsen]
+- Fix uninstall target in Makefile.in [Truta]
+- Add pkgconfig support [Weigelt]
+- Use $(DESTDIR) macro in Makefile.in [Reinholdtsen, Weigelt]
+- Replace set_data_type() with a more accurate detect_data_type() in
+  trees.c, according to the txtvsbin.txt document [Truta]
+- Swap the order of #include <stdio.h> and #include "zlib.h" in
+  gzio.c, example.c and minigzip.c [Truta]
+- Shut up annoying VS2005 warnings about standard C deprecation [Rowe,
+  Truta] (where?)
+- Fix target "clean" from win32/Makefile.bor [Truta]
+- Create .pdb and .manifest files in win32/makefile.msc [Ziegler, Rowe]
+- Update zlib www home address in win32/DLL_FAQ.txt [Truta]
+- Update contrib/masmx86/inffas32.asm for VS2005 [Vollant, Van Wassenhove]
+- Enable browse info in the "Debug" and "ASM Debug" configurations in
+  the Visual C++ 6 project, and set (non-ASM) "Debug" as default [Truta]
+- Add pkgconfig support [Weigelt]
+- Add ZLIB_VER_MAJOR, ZLIB_VER_MINOR and ZLIB_VER_REVISION in zlib.h,
+  for use in win32/zlib1.rc [Polushin, Rowe, Truta]
+- Add a document that explains the new text detection scheme to
+  doc/txtvsbin.txt [Truta]
+- Add rfc1950.txt, rfc1951.txt and rfc1952.txt to doc/ [Truta]
+- Move algorithm.txt into doc/ [Truta]
+- Synchronize FAQ with website
+- Fix compressBound(), was low for some pathological cases [Fearnley]
+- Take into account wrapper variations in deflateBound()
+- Set examples/zpipe.c input and output to binary mode for Windows
+- Update examples/zlib_how.html with new zpipe.c (also web site)
+- Fix some warnings in examples/gzlog.c and examples/zran.c (it seems
+  that gcc became pickier in 4.0)
+- Add zlib.map for Linux: "All symbols from zlib-1.1.4 remain
+  un-versioned, the patch adds versioning only for symbols introduced in
+  zlib-1.2.0 or later.  It also declares as local those symbols which are
+  not designed to be exported." [Levin]
+- Update Z_PREFIX list in zconf.in.h, add --zprefix option to configure
+- Do not initialize global static by default in trees.c, add a response
+  NO_INIT_GLOBAL_POINTERS to initialize them if needed [Marquess]
+- Don't use strerror() in gzio.c under WinCE [Yakimov]
+- Don't use errno.h in zutil.h under WinCE [Yakimov]
+- Move arguments for AR to its usage to allow replacing ar [Marot]
+- Add HAVE_VISIBILITY_PRAGMA in zconf.in.h for Mozilla [Randers-Pehrson]
+- Improve inflateInit() and inflateInit2() documentation
+- Fix structure size comment in inflate.h
+- Change configure help option from --h* to --help [Santos]
+
 Changes in 1.2.3 (18 July 2005)
 - Apply security vulnerability fixes to contrib/infback9 as well
 - Clean up some text files (carriage returns, trailing space)
@@ -13,7 +630,7 @@ Changes in 1.2.2.4 (11 July 2005)
   compile
 - Fix some spelling errors in comments [Betts]
 - Correct inflateInit2() error return documentation in zlib.h
-- Added zran.c example of compressed data random access to examples
+- Add zran.c example of compressed data random access to examples
   directory, shows use of inflatePrime()
 - Fix cast for assignments to strm->state in inflate.c and infback.c
 - Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer]
diff --git a/third_party/zlib/FAQ b/third_party/zlib/FAQ
index 441d910..99b7cf9 100644
--- a/third_party/zlib/FAQ
+++ b/third_party/zlib/FAQ
@@ -3,8 +3,8 @@
 
 
 If your question is not there, please check the zlib home page
-http://www.zlib.org which may have more recent information.
-The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
+http://zlib.net/ which may have more recent information.
+The lastest zlib FAQ is at http://zlib.net/zlib_faq.html
 
 
  1. Is zlib Y2K-compliant?
@@ -13,54 +13,51 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
 
  2. Where can I get a Windows DLL version?
 
-    The zlib sources can be compiled without change to produce a DLL.
-    See the file win32/DLL_FAQ.txt in the zlib distribution.
-    Pointers to the precompiled DLL are found in the zlib web site at
-    http://www.zlib.org.
+    The zlib sources can be compiled without change to produce a DLL.  See the
+    file win32/DLL_FAQ.txt in the zlib distribution.  Pointers to the
+    precompiled DLL are found in the zlib web site at http://zlib.net/ .
 
  3. Where can I get a Visual Basic interface to zlib?
 
     See
-        * http://www.dogma.net/markn/articles/zlibtool/zlibtool.htm
-        * contrib/visual-basic.txt in the zlib distribution
+        * http://marknelson.us/1997/01/01/zlib-engine/
         * win32/DLL_FAQ.txt in the zlib distribution
 
  4. compress() returns Z_BUF_ERROR.
 
-    Make sure that before the call of compress, the length of the compressed
-    buffer is equal to the total size of the compressed buffer and not
-    zero. For Visual Basic, check that this parameter is passed by reference
+    Make sure that before the call of compress(), the length of the compressed
+    buffer is equal to the available size of the compressed buffer and not
+    zero.  For Visual Basic, check that this parameter is passed by reference
     ("as any"), not by value ("as long").
 
  5. deflate() or inflate() returns Z_BUF_ERROR.
 
-    Before making the call, make sure that avail_in and avail_out are not
-    zero. When setting the parameter flush equal to Z_FINISH, also make sure
-    that avail_out is big enough to allow processing all pending input.
-    Note that a Z_BUF_ERROR is not fatal--another call to deflate() or
-    inflate() can be made with more input or output space. A Z_BUF_ERROR
-    may in fact be unavoidable depending on how the functions are used, since
-    it is not possible to tell whether or not there is more output pending
-    when strm.avail_out returns with zero.
+    Before making the call, make sure that avail_in and avail_out are not zero.
+    When setting the parameter flush equal to Z_FINISH, also make sure that
+    avail_out is big enough to allow processing all pending input.  Note that a
+    Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be
+    made with more input or output space.  A Z_BUF_ERROR may in fact be
+    unavoidable depending on how the functions are used, since it is not
+    possible to tell whether or not there is more output pending when
+    strm.avail_out returns with zero.  See http://zlib.net/zlib_how.html for a
+    heavily annotated example.
 
  6. Where's the zlib documentation (man pages, etc.)?
 
-    It's in zlib.h for the moment, and Francis S. Lin has converted it to a
-    web page zlib.html. Volunteers to transform this to Unix-style man pages,
-    please contact us (zlib at gzip.org). Examples of zlib usage are in the files
-    example.c and minigzip.c.
+    It's in zlib.h .  Examples of zlib usage are in the files test/example.c
+    and test/minigzip.c, with more in examples/ .
 
  7. Why don't you use GNU autoconf or libtool or ...?
 
-    Because we would like to keep zlib as a very small and simple
-    package. zlib is rather portable and doesn't need much configuration.
+    Because we would like to keep zlib as a very small and simple package.
+    zlib is rather portable and doesn't need much configuration.
 
  8. I found a bug in zlib.
 
-    Most of the time, such problems are due to an incorrect usage of
-    zlib. Please try to reproduce the problem with a small program and send
-    the corresponding source to us at zlib at gzip.org . Do not send
-    multi-megabyte data files without prior agreement.
+    Most of the time, such problems are due to an incorrect usage of zlib.
+    Please try to reproduce the problem with a small program and send the
+    corresponding source to us at zlib at gzip.org .  Do not send multi-megabyte
+    data files without prior agreement.
 
  9. Why do I get "undefined reference to gzputc"?
 
@@ -82,13 +79,15 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
 
 12. Can zlib handle .Z files?
 
-    No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt
+    No, sorry.  You have to spawn an uncompress or gunzip subprocess, or adapt
     the code of uncompress on your own.
 
 13. How can I make a Unix shared library?
 
-    make clean
-    ./configure -s
+    By default a shared (and a static) library is built for Unix.  So:
+
+    make distclean
+    ./configure
     make
 
 14. How do I install a shared zlib library on Unix?
@@ -99,8 +98,10 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
 
     However, many flavors of Unix come with a shared zlib already installed.
     Before going to the trouble of compiling a shared version of zlib and
-    trying to install it, you may want to check if it's already there! If you
-    can #include <zlib.h>, it's there. The -lz option will probably link to it.
+    trying to install it, you may want to check if it's already there!  If you
+    can #include <zlib.h>, it's there.  The -lz option will probably link to
+    it.  You can check the version at the top of zlib.h or with the
+    ZLIB_VERSION symbol defined in zlib.h .
 
 15. I have a question about OttoPDF.
 
@@ -109,8 +110,8 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
 
 16. Can zlib decode Flate data in an Adobe PDF file?
 
-    Yes. See http://www.fastio.com/ (ClibPDF), or http://www.pdflib.com/ .
-    To modify PDF forms, see http://sourceforge.net/projects/acroformtool/ .
+    Yes. See http://www.pdflib.com/ . To modify PDF forms, see
+    http://sourceforge.net/projects/acroformtool/ .
 
 17. Why am I getting this "register_frame_info not found" error on Solaris?
 
@@ -121,67 +122,67 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
         symbol __register_frame_info: referenced symbol not found
 
     The symbol __register_frame_info is not part of zlib, it is generated by
-    the C compiler (cc or gcc). You must recompile applications using zlib
-    which have this problem. This problem is specific to Solaris. See
+    the C compiler (cc or gcc).  You must recompile applications using zlib
+    which have this problem.  This problem is specific to Solaris.  See
     http://www.sunfreeware.com for Solaris versions of zlib and applications
     using zlib.
 
 18. Why does gzip give an error on a file I make with compress/deflate?
 
     The compress and deflate functions produce data in the zlib format, which
-    is different and incompatible with the gzip format. The gz* functions in
-    zlib on the other hand use the gzip format. Both the zlib and gzip
-    formats use the same compressed data format internally, but have different
-    headers and trailers around the compressed data.
+    is different and incompatible with the gzip format.  The gz* functions in
+    zlib on the other hand use the gzip format.  Both the zlib and gzip formats
+    use the same compressed data format internally, but have different headers
+    and trailers around the compressed data.
 
 19. Ok, so why are there two different formats?
 
-    The gzip format was designed to retain the directory information about
-    a single file, such as the name and last modification date. The zlib
-    format on the other hand was designed for in-memory and communication
-    channel applications, and has a much more compact header and trailer and
-    uses a faster integrity check than gzip.
+    The gzip format was designed to retain the directory information about a
+    single file, such as the name and last modification date.  The zlib format
+    on the other hand was designed for in-memory and communication channel
+    applications, and has a much more compact header and trailer and uses a
+    faster integrity check than gzip.
 
 20. Well that's nice, but how do I make a gzip file in memory?
 
     You can request that deflate write the gzip format instead of the zlib
-    format using deflateInit2(). You can also request that inflate decode
-    the gzip format using inflateInit2(). Read zlib.h for more details.
+    format using deflateInit2().  You can also request that inflate decode the
+    gzip format using inflateInit2().  Read zlib.h for more details.
 
 21. Is zlib thread-safe?
 
-    Yes. However any library routines that zlib uses and any application-
-    provided memory allocation routines must also be thread-safe. zlib's gz*
+    Yes.  However any library routines that zlib uses and any application-
+    provided memory allocation routines must also be thread-safe.  zlib's gz*
     functions use stdio library routines, and most of zlib's functions use the
-    library memory allocation routines by default. zlib's Init functions allow
-    for the application to provide custom memory allocation routines.
+    library memory allocation routines by default.  zlib's *Init* functions
+    allow for the application to provide custom memory allocation routines.
 
     Of course, you should only operate on any given zlib or gzip stream from a
     single thread at a time.
 
 22. Can I use zlib in my commercial application?
 
-    Yes. Please read the license in zlib.h.
+    Yes.  Please read the license in zlib.h.
 
 23. Is zlib under the GNU license?
 
-    No. Please read the license in zlib.h.
+    No.  Please read the license in zlib.h.
 
 24. The license says that altered source versions must be "plainly marked". So
     what exactly do I need to do to meet that requirement?
 
-    You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In
+    You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h.  In
     particular, the final version number needs to be changed to "f", and an
-    identification string should be appended to ZLIB_VERSION. Version numbers
+    identification string should be appended to ZLIB_VERSION.  Version numbers
     x.x.x.f are reserved for modifications to zlib by others than the zlib
-    maintainers. For example, if the version of the base zlib you are altering
+    maintainers.  For example, if the version of the base zlib you are altering
     is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and
-    ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also
+    ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3".  You can also
     update the version strings in deflate.c and inftrees.c.
 
     For altered source distributions, you should also note the origin and
     nature of the changes in zlib.h, as well as in ChangeLog and README, along
-    with the dates of the alterations. The origin should include at least your
+    with the dates of the alterations.  The origin should include at least your
     name (or your company's name), and an email address to contact for help or
     issues with the library.
 
@@ -197,105 +198,112 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
 
 26. Will zlib work on a 64-bit machine?
 
-    It should. It has been tested on 64-bit machines, and has no dependence
-    on any data types being limited to 32-bits in length. If you have any
+    Yes.  It has been tested on 64-bit machines, and has no dependence on any
+    data types being limited to 32-bits in length.  If you have any
     difficulties, please provide a complete problem report to zlib at gzip.org
 
 27. Will zlib decompress data from the PKWare Data Compression Library?
 
-    No. The PKWare DCL uses a completely different compressed data format
-    than does PKZIP and zlib. However, you can look in zlib's contrib/blast
+    No.  The PKWare DCL uses a completely different compressed data format than
+    does PKZIP and zlib.  However, you can look in zlib's contrib/blast
     directory for a possible solution to your problem.
 
 28. Can I access data randomly in a compressed stream?
 
-    No, not without some preparation. If when compressing you periodically
-    use Z_FULL_FLUSH, carefully write all the pending data at those points,
-    and keep an index of those locations, then you can start decompression
-    at those points. You have to be careful to not use Z_FULL_FLUSH too
-    often, since it can significantly degrade compression.
+    No, not without some preparation.  If when compressing you periodically use
+    Z_FULL_FLUSH, carefully write all the pending data at those points, and
+    keep an index of those locations, then you can start decompression at those
+    points.  You have to be careful to not use Z_FULL_FLUSH too often, since it
+    can significantly degrade compression.  Alternatively, you can scan a
+    deflate stream once to generate an index, and then use that index for
+    random access.  See examples/zran.c .
 
 29. Does zlib work on MVS, OS/390, CICS, etc.?
 
-    We don't know for sure. We have heard occasional reports of success on
-    these systems. If you do use it on one of these, please provide us with
-    a report, instructions, and patches that we can reference when we get
-    these questions. Thanks.
+    It has in the past, but we have not heard of any recent evidence.  There
+    were working ports of zlib 1.1.4 to MVS, but those links no longer work.
+    If you know of recent, successful applications of zlib on these operating
+    systems, please let us know.  Thanks.
 
-30. Is there some simpler, easier to read version of inflate I can look at
-    to understand the deflate format?
+30. Is there some simpler, easier to read version of inflate I can look at to
+    understand the deflate format?
 
-    First off, you should read RFC 1951. Second, yes. Look in zlib's
+    First off, you should read RFC 1951.  Second, yes.  Look in zlib's
     contrib/puff directory.
 
 31. Does zlib infringe on any patents?
 
-    As far as we know, no. In fact, that was originally the whole point behind
-    zlib. Look here for some more information:
+    As far as we know, no.  In fact, that was originally the whole point behind
+    zlib.  Look here for some more information:
 
     http://www.gzip.org/#faq11
 
 32. Can zlib work with greater than 4 GB of data?
 
-    Yes. inflate() and deflate() will process any amount of data correctly.
+    Yes.  inflate() and deflate() will process any amount of data correctly.
     Each call of inflate() or deflate() is limited to input and output chunks
     of the maximum value that can be stored in the compiler's "unsigned int"
-    type, but there is no limit to the number of chunks. Note however that the
-    strm.total_in and strm_total_out counters may be limited to 4 GB. These
+    type, but there is no limit to the number of chunks.  Note however that the
+    strm.total_in and strm_total_out counters may be limited to 4 GB.  These
     counters are provided as a convenience and are not used internally by
-    inflate() or deflate(). The application can easily set up its own counters
+    inflate() or deflate().  The application can easily set up its own counters
     updated after each call of inflate() or deflate() to count beyond 4 GB.
     compress() and uncompress() may be limited to 4 GB, since they operate in a
-    single call. gzseek() and gztell() may be limited to 4 GB depending on how
-    zlib is compiled. See the zlibCompileFlags() function in zlib.h.
+    single call.  gzseek() and gztell() may be limited to 4 GB depending on how
+    zlib is compiled.  See the zlibCompileFlags() function in zlib.h.
 
-    The word "may" appears several times above since there is a 4 GB limit
-    only if the compiler's "long" type is 32 bits. If the compiler's "long"
-    type is 64 bits, then the limit is 16 exabytes.
+    The word "may" appears several times above since there is a 4 GB limit only
+    if the compiler's "long" type is 32 bits.  If the compiler's "long" type is
+    64 bits, then the limit is 16 exabytes.
 
 33. Does zlib have any security vulnerabilities?
 
-    The only one that we are aware of is potentially in gzprintf(). If zlib
-    is compiled to use sprintf() or vsprintf(), then there is no protection
-    against a buffer overflow of a 4K string space, other than the caller of
-    gzprintf() assuring that the output will not exceed 4K. On the other
-    hand, if zlib is compiled to use snprintf() or vsnprintf(), which should
-    normally be the case, then there is no vulnerability. The ./configure
-    script will display warnings if an insecure variation of sprintf() will
-    be used by gzprintf(). Also the zlibCompileFlags() function will return
-    information on what variant of sprintf() is used by gzprintf().
+    The only one that we are aware of is potentially in gzprintf().  If zlib is
+    compiled to use sprintf() or vsprintf(), then there is no protection
+    against a buffer overflow of an 8K string space (or other value as set by
+    gzbuffer()), other than the caller of gzprintf() assuring that the output
+    will not exceed 8K.  On the other hand, if zlib is compiled to use
+    snprintf() or vsnprintf(), which should normally be the case, then there is
+    no vulnerability.  The ./configure script will display warnings if an
+    insecure variation of sprintf() will be used by gzprintf().  Also the
+    zlibCompileFlags() function will return information on what variant of
+    sprintf() is used by gzprintf().
 
     If you don't have snprintf() or vsnprintf() and would like one, you can
     find a portable implementation here:
 
         http://www.ijs.si/software/snprintf/
 
-    Note that you should be using the most recent version of zlib. Versions
-    1.1.3 and before were subject to a double-free vulnerability.
+    Note that you should be using the most recent version of zlib.  Versions
+    1.1.3 and before were subject to a double-free vulnerability, and versions
+    1.2.1 and 1.2.2 were subject to an access exception when decompressing
+    invalid compressed data.
 
 34. Is there a Java version of zlib?
 
     Probably what you want is to use zlib in Java. zlib is already included
     as part of the Java SDK in the java.util.zip package. If you really want
     a version of zlib written in the Java language, look on the zlib home
-    page for links: http://www.zlib.org/
+    page for links: http://zlib.net/ .
 
 35. I get this or that compiler or source-code scanner warning when I crank it
     up to maximally-pedantic. Can't you guys write proper code?
 
     Many years ago, we gave up attempting to avoid warnings on every compiler
-    in the universe. It just got to be a waste of time, and some compilers
-    were downright silly. So now, we simply make sure that the code always
-    works.
+    in the universe.  It just got to be a waste of time, and some compilers
+    were downright silly as well as contradicted each other.  So now, we simply
+    make sure that the code always works.
 
 36. Valgrind (or some similar memory access checker) says that deflate is
     performing a conditional jump that depends on an uninitialized value.
     Isn't that a bug?
 
-    No.  That is intentional for performance reasons, and the output of
-    deflate is not affected.  This only started showing up recently since
-    zlib 1.2.x uses malloc() by default for allocations, whereas earlier
-    versions used calloc(), which zeros out the allocated memory.
+    No.  That is intentional for performance reasons, and the output of deflate
+    is not affected.  This only started showing up recently since zlib 1.2.x
+    uses malloc() by default for allocations, whereas earlier versions used
+    calloc(), which zeros out the allocated memory.  Even though the code was
+    correct, versions 1.2.4 and later was changed to not stimulate these
+    checkers.
 
 37. Will zlib read the (insert any ancient or arcane format here) compressed
     data format?
@@ -305,20 +313,21 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
 
 38. How can I encrypt/decrypt zip files with zlib?
 
-    zlib doesn't support encryption. The original PKZIP encryption is very weak
-    and can be broken with freely available programs. To get strong encryption,
-    use GnuPG, http://www.gnupg.org/ , which already includes zlib compression.
-    For PKZIP compatible "encryption", look at http://www.info-zip.org/
+    zlib doesn't support encryption.  The original PKZIP encryption is very
+    weak and can be broken with freely available programs.  To get strong
+    encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib
+    compression.  For PKZIP compatible "encryption", look at
+    http://www.info-zip.org/
 
 39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
 
-    "gzip" is the gzip format, and "deflate" is the zlib format. They should
-    probably have called the second one "zlib" instead to avoid confusion
-    with the raw deflate compressed data format. While the HTTP 1.1 RFC 2616
+    "gzip" is the gzip format, and "deflate" is the zlib format.  They should
+    probably have called the second one "zlib" instead to avoid confusion with
+    the raw deflate compressed data format.  While the HTTP 1.1 RFC 2616
     correctly points to the zlib specification in RFC 1950 for the "deflate"
     transfer encoding, there have been reports of servers and browsers that
     incorrectly produce or expect raw deflate data per the deflate
-    specficiation in RFC 1951, most notably Microsoft. So even though the
+    specification in RFC 1951, most notably Microsoft.  So even though the
     "deflate" transfer encoding using the zlib format would be the more
     efficient approach (and in fact exactly what the zlib format was designed
     for), using the "gzip" transfer encoding is probably more reliable due to
@@ -328,12 +337,32 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
 
 40. Does zlib support the new "Deflate64" format introduced by PKWare?
 
-    No. PKWare has apparently decided to keep that format proprietary, since
-    they have not documented it as they have previous compression formats.
-    In any case, the compression improvements are so modest compared to other
-    more modern approaches, that it's not worth the effort to implement.
+    No.  PKWare has apparently decided to keep that format proprietary, since
+    they have not documented it as they have previous compression formats.  In
+    any case, the compression improvements are so modest compared to other more
+    modern approaches, that it's not worth the effort to implement.
+
+41. I'm having a problem with the zip functions in zlib, can you help?
+
+    There are no zip functions in zlib.  You are probably using minizip by
+    Giles Vollant, which is found in the contrib directory of zlib.  It is not
+    part of zlib.  In fact none of the stuff in contrib is part of zlib.  The
+    files in there are not supported by the zlib authors.  You need to contact
+    the authors of the respective contribution for help.
+
+42. The match.asm code in contrib is under the GNU General Public License.
+    Since it's part of zlib, doesn't that mean that all of zlib falls under the
+    GNU GPL?
+
+    No.  The files in contrib are not part of zlib.  They were contributed by
+    other authors and are provided as a convenience to the user within the zlib
+    distribution.  Each item in contrib has its own license.
+
+43. Is zlib subject to export controls?  What is its ECCN?
+
+    zlib is not subject to export controls, and so is classified as EAR99.
 
-41. Can you please sign these lengthy legal documents and fax them back to us
+44. Can you please sign these lengthy legal documents and fax them back to us
     so that we can use your software in our product?
 
     No. Go away. Shoo.
diff --git a/third_party/zlib/INDEX b/third_party/zlib/INDEX
index 0587e59..2ba0641 100644
--- a/third_party/zlib/INDEX
+++ b/third_party/zlib/INDEX
@@ -1,23 +1,37 @@
+CMakeLists.txt  cmake build file
 ChangeLog       history of changes
 FAQ             Frequently Asked Questions about zlib
 INDEX           this file
-Makefile        makefile for Unix (generated by configure)
-Makefile.in     makefile for Unix (template for configure)
+Makefile        dummy Makefile that tells you to ./configure
+Makefile.in     template for Unix Makefile
 README          guess what
-algorithm.txt   description of the (de)compression algorithm
 configure       configure script for Unix
-zconf.in.h      template for zconf.h (used by configure)
+make_vms.com    makefile for VMS
+test/example.c  zlib usages examples for build testing
+test/minigzip.c minimal gzip-like functionality for build testing
+test/infcover.c inf*.c code coverage for build coverage testing
+treebuild.xml   XML description of source file dependencies
+zconf.h.cmakein zconf.h template for cmake
+zconf.h.in      zconf.h template for configure
+zlib.3          Man page for zlib
+zlib.3.pdf      Man page in PDF format
+zlib.map        Linux symbol information
+zlib.pc.in      Template for pkg-config descriptor
+zlib.pc.cmakein zlib.pc template for cmake
+zlib2ansi       perl script to convert source files for C++ compilation
 
 amiga/          makefiles for Amiga SAS C
-as400/          makefiles for IBM AS/400
+as400/          makefiles for AS/400
+doc/            documentation for formats and algorithms
 msdos/          makefiles for MSDOS
+nintendods/     makefile for Nintendo DS
 old/            makefiles for various architectures and zlib documentation
                 files that have not yet been updated for zlib 1.2.x
-projects/       projects for various Integrated Development Environments
 qnx/            makefiles for QNX
+watcom/         makefiles for OpenWatcom
 win32/          makefiles for Windows
 
-                zlib public header files (must be kept):
+                zlib public header files (required for library use):
 zconf.h
 zlib.h
 
@@ -28,7 +42,11 @@ crc32.c
 crc32.h
 deflate.c
 deflate.h
-gzio.c
+gzclose.c
+gzguts.h
+gzlib.c
+gzread.c
+gzwrite.c
 infback.c
 inffast.c
 inffast.h
@@ -43,9 +61,8 @@ uncompr.c
 zutil.c
 zutil.h
 
-                source files for sample programs:
-example.c
-minigzip.c
+                source files for sample programs
+See examples/README.examples
 
-                unsupported contribution by third parties
+                unsupported contributions by third parties
 See contrib/README.contrib
diff --git a/third_party/zlib/Makefile b/third_party/zlib/Makefile
index 2fd6e45..6bba86c 100644
--- a/third_party/zlib/Makefile
+++ b/third_party/zlib/Makefile
@@ -1,154 +1,5 @@
-# Makefile for zlib
-# Copyright (C) 1995-2005 Jean-loup Gailly.
-# For conditions of distribution and use, see copyright notice in zlib.h
+all:
+	- at echo "Please use ./configure first.  Thank you."
 
-# To compile and test, type:
-#    ./configure; make test
-# The call of configure is optional if you don't have special requirements
-# If you wish to build zlib as a shared library, use: ./configure -s
-
-# To use the asm code, type:
-#    cp contrib/asm?86/match.S ./match.S
-#    make LOC=-DASMV OBJA=match.o
-
-# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
-#    make install
-# To install in $HOME instead of /usr/local, use:
-#    make install prefix=$HOME
-
-CC=cc
-
-CFLAGS=-O
-#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
-#CFLAGS=-g -DDEBUG
-#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
-#           -Wstrict-prototypes -Wmissing-prototypes
-
-LDFLAGS=libz.a
-LDSHARED=$(CC)
-CPP=$(CC) -E
-
-LIBS=libz.a
-SHAREDLIB=libz.so
-SHAREDLIBV=libz.so.1.2.3
-SHAREDLIBM=libz.so.1
-
-AR=ar rc
-RANLIB=ranlib
-TAR=tar
-SHELL=/bin/sh
-EXE=
-
-prefix = /usr/local
-exec_prefix = ${prefix}
-libdir = ${exec_prefix}/lib
-includedir = ${prefix}/include
-mandir = ${prefix}/share/man
-man3dir = ${mandir}/man3
-
-OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
-       zutil.o inflate.o infback.o inftrees.o inffast.o
-
-OBJA =
-# to use the asm code: make OBJA=match.o
-
-TEST_OBJS = example.o minigzip.o
-
-all: example$(EXE) minigzip$(EXE)
-
-check: test
-test: all
-	@LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
-	echo hello world | ./minigzip | ./minigzip -d || \
-	  echo '		*** minigzip test FAILED ***' ; \
-	if ./example; then \
-	  echo '		*** zlib test OK ***'; \
-	else \
-	  echo '		*** zlib test FAILED ***'; \
-	fi
-
-libz.a: $(OBJS) $(OBJA)
-	$(AR) $@ $(OBJS) $(OBJA)
-	-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
-
-match.o: match.S
-	$(CPP) match.S > _match.s
-	$(CC) -c _match.s
-	mv _match.o match.o
-	rm -f _match.s
-
-$(SHAREDLIBV): $(OBJS)
-	$(LDSHARED) -o $@ $(OBJS)
-	rm -f $(SHAREDLIB) $(SHAREDLIBM)
-	ln -s $@ $(SHAREDLIB)
-	ln -s $@ $(SHAREDLIBM)
-
-example$(EXE): example.o $(LIBS)
-	$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
-
-minigzip$(EXE): minigzip.o $(LIBS)
-	$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
-
-install: $(LIBS)
-	- at if [ ! -d $(exec_prefix) ]; then mkdir -p $(exec_prefix); fi
-	- at if [ ! -d $(includedir)  ]; then mkdir -p $(includedir); fi
-	- at if [ ! -d $(libdir)      ]; then mkdir -p $(libdir); fi
-	- at if [ ! -d $(man3dir)     ]; then mkdir -p $(man3dir); fi
-	cp zlib.h zconf.h $(includedir)
-	chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
-	cp $(LIBS) $(libdir)
-	cd $(libdir); chmod 755 $(LIBS)
-	-@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
-	cd $(libdir); if test -f $(SHAREDLIBV); then \
-	  rm -f $(SHAREDLIB) $(SHAREDLIBM); \
-	  ln -s $(SHAREDLIBV) $(SHAREDLIB); \
-	  ln -s $(SHAREDLIBV) $(SHAREDLIBM); \
-	  (ldconfig || true)  >/dev/null 2>&1; \
-	fi
-	cp zlib.3 $(man3dir)
-	chmod 644 $(man3dir)/zlib.3
-# The ranlib in install is needed on NeXTSTEP which checks file times
-# ldconfig is for Linux
-
-uninstall:
-	cd $(includedir); \
-	cd $(libdir); rm -f libz.a; \
-	if test -f $(SHAREDLIBV); then \
-	  rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \
-	fi
-	cd $(man3dir); rm -f zlib.3
-
-mostlyclean: clean
-clean:
-	rm -f *.o *~ example$(EXE) minigzip$(EXE) \
-	   libz.* foo.gz so_locations \
-	   _match.s maketree contrib/infback9/*.o
-
-maintainer-clean: distclean
-distclean: clean
-	cp -p Makefile.in Makefile
-	cp -p zconf.in.h zconf.h
-	rm -f .DS_Store
-
-tags:
-	etags *.[ch]
-
-depend:
-	makedepend -- $(CFLAGS) -- *.[ch]
-
-# DO NOT DELETE THIS LINE -- make depend depends on it.
-
-adler32.o: zlib.h zconf.h
-compress.o: zlib.h zconf.h
-crc32.o: crc32.h zlib.h zconf.h
-deflate.o: deflate.h zutil.h zlib.h zconf.h
-example.o: zlib.h zconf.h
-gzio.o: zutil.h zlib.h zconf.h
-inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
-inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
-infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
-inftrees.o: zutil.h zlib.h zconf.h inftrees.h
-minigzip.o: zlib.h zconf.h
-trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
-uncompr.o: zlib.h zconf.h
-zutil.o: zutil.h zlib.h zconf.h
+distclean:
+	make -f Makefile.in distclean
diff --git a/third_party/zlib/Makefile.in b/third_party/zlib/Makefile.in
index 2fd6e45..c61aa30 100644
--- a/third_party/zlib/Makefile.in
+++ b/third_party/zlib/Makefile.in
@@ -1,11 +1,11 @@
 # Makefile for zlib
-# Copyright (C) 1995-2005 Jean-loup Gailly.
+# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler
 # For conditions of distribution and use, see copyright notice in zlib.h
 
 # To compile and test, type:
 #    ./configure; make test
-# The call of configure is optional if you don't have special requirements
-# If you wish to build zlib as a shared library, use: ./configure -s
+# Normally configure builds both a static and a shared library.
+# If you want to build just a static library, use: ./configure --static
 
 # To use the asm code, type:
 #    cp contrib/asm?86/match.S ./match.S
@@ -24,17 +24,23 @@ CFLAGS=-O
 #CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
 #           -Wstrict-prototypes -Wmissing-prototypes
 
-LDFLAGS=libz.a
+SFLAGS=-O
+LDFLAGS=
+TEST_LDFLAGS=-L. libz.a
 LDSHARED=$(CC)
 CPP=$(CC) -E
 
-LIBS=libz.a
+STATICLIB=libz.a
 SHAREDLIB=libz.so
-SHAREDLIBV=libz.so.1.2.3
+SHAREDLIBV=libz.so.1.2.8
 SHAREDLIBM=libz.so.1
+LIBS=$(STATICLIB) $(SHAREDLIBV)
 
-AR=ar rc
+AR=ar
+ARFLAGS=rc
 RANLIB=ranlib
+LDCONFIG=ldconfig
+LDSHAREDLIBC=-lc
 TAR=tar
 SHELL=/bin/sh
 EXE=
@@ -42,33 +48,84 @@ EXE=
 prefix = /usr/local
 exec_prefix = ${prefix}
 libdir = ${exec_prefix}/lib
+sharedlibdir = ${libdir}
 includedir = ${prefix}/include
 mandir = ${prefix}/share/man
 man3dir = ${mandir}/man3
+pkgconfigdir = ${libdir}/pkgconfig
 
-OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
-       zutil.o inflate.o infback.o inftrees.o inffast.o
+OBJZ = adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o
+OBJG = compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o
+OBJC = $(OBJZ) $(OBJG)
 
+PIC_OBJZ = adler32.lo crc32.lo deflate.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo zutil.lo
+PIC_OBJG = compress.lo uncompr.lo gzclose.lo gzlib.lo gzread.lo gzwrite.lo
+PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG)
+
+# to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo
 OBJA =
-# to use the asm code: make OBJA=match.o
+PIC_OBJA =
+
+OBJS = $(OBJC) $(OBJA)
+
+PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA)
+
+all: static shared
+
+static: example$(EXE) minigzip$(EXE)
 
-TEST_OBJS = example.o minigzip.o
+shared: examplesh$(EXE) minigzipsh$(EXE)
 
-all: example$(EXE) minigzip$(EXE)
+all64: example64$(EXE) minigzip64$(EXE)
 
 check: test
-test: all
-	@LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
-	echo hello world | ./minigzip | ./minigzip -d || \
-	  echo '		*** minigzip test FAILED ***' ; \
-	if ./example; then \
+
+test: all teststatic testshared
+
+teststatic: static
+	@TMPST=tmpst_$$; \
+	if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \
 	  echo '		*** zlib test OK ***'; \
 	else \
-	  echo '		*** zlib test FAILED ***'; \
-	fi
+	  echo '		*** zlib test FAILED ***'; false; \
+	fi; \
+	rm -f $$TMPST
+
+testshared: shared
+	@LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
+	LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \
+	DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \
+	SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \
+	TMPSH=tmpsh_$$; \
+	if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh $$TMPSH; then \
+	  echo '		*** zlib shared test OK ***'; \
+	else \
+	  echo '		*** zlib shared test FAILED ***'; false; \
+	fi; \
+	rm -f $$TMPSH
+
+test64: all64
+	@TMP64=tmp64_$$; \
+	if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \
+	  echo '		*** zlib 64-bit test OK ***'; \
+	else \
+	  echo '		*** zlib 64-bit test FAILED ***'; false; \
+	fi; \
+	rm -f $$TMP64
+
+infcover.o: test/infcover.c zlib.h zconf.h
+	$(CC) $(CFLAGS) -I. -c -o $@ test/infcover.c
+
+infcover: infcover.o libz.a
+	$(CC) $(CFLAGS) -o $@ infcover.o libz.a
 
-libz.a: $(OBJS) $(OBJA)
-	$(AR) $@ $(OBJS) $(OBJA)
+cover: infcover
+	rm -f *.gcda
+	./infcover
+	gcov inf*.c
+
+libz.a: $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
 	-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
 
 match.o: match.S
@@ -77,58 +134,130 @@ match.o: match.S
 	mv _match.o match.o
 	rm -f _match.s
 
-$(SHAREDLIBV): $(OBJS)
-	$(LDSHARED) -o $@ $(OBJS)
+match.lo: match.S
+	$(CPP) match.S > _match.s
+	$(CC) -c -fPIC _match.s
+	mv _match.o match.lo
+	rm -f _match.s
+
+example.o: test/example.c zlib.h zconf.h
+	$(CC) $(CFLAGS) -I. -c -o $@ test/example.c
+
+minigzip.o: test/minigzip.c zlib.h zconf.h
+	$(CC) $(CFLAGS) -I. -c -o $@ test/minigzip.c
+
+example64.o: test/example.c zlib.h zconf.h
+	$(CC) $(CFLAGS) -I. -D_FILE_OFFSET_BITS=64 -c -o $@ test/example.c
+
+minigzip64.o: test/minigzip.c zlib.h zconf.h
+	$(CC) $(CFLAGS) -I. -D_FILE_OFFSET_BITS=64 -c -o $@ test/minigzip.c
+
+.SUFFIXES: .lo
+
+.c.lo:
+	- at mkdir objs 2>/dev/null || test -d objs
+	$(CC) $(SFLAGS) -DPIC -c -o objs/$*.o $<
+	- at mv objs/$*.o $@
+
+placebo $(SHAREDLIBV): $(PIC_OBJS) libz.a
+	$(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) $(LDSHAREDLIBC) $(LDFLAGS)
 	rm -f $(SHAREDLIB) $(SHAREDLIBM)
 	ln -s $@ $(SHAREDLIB)
 	ln -s $@ $(SHAREDLIBM)
+	- at rmdir objs
+
+example$(EXE): example.o $(STATICLIB)
+	$(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS)
+
+minigzip$(EXE): minigzip.o $(STATICLIB)
+	$(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS)
+
+examplesh$(EXE): example.o $(SHAREDLIBV)
+	$(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV)
 
-example$(EXE): example.o $(LIBS)
-	$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
-
-minigzip$(EXE): minigzip.o $(LIBS)
-	$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
-
-install: $(LIBS)
-	- at if [ ! -d $(exec_prefix) ]; then mkdir -p $(exec_prefix); fi
-	- at if [ ! -d $(includedir)  ]; then mkdir -p $(includedir); fi
-	- at if [ ! -d $(libdir)      ]; then mkdir -p $(libdir); fi
-	- at if [ ! -d $(man3dir)     ]; then mkdir -p $(man3dir); fi
-	cp zlib.h zconf.h $(includedir)
-	chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
-	cp $(LIBS) $(libdir)
-	cd $(libdir); chmod 755 $(LIBS)
-	-@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
-	cd $(libdir); if test -f $(SHAREDLIBV); then \
-	  rm -f $(SHAREDLIB) $(SHAREDLIBM); \
-	  ln -s $(SHAREDLIBV) $(SHAREDLIB); \
-	  ln -s $(SHAREDLIBV) $(SHAREDLIBM); \
-	  (ldconfig || true)  >/dev/null 2>&1; \
+minigzipsh$(EXE): minigzip.o $(SHAREDLIBV)
+	$(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV)
+
+example64$(EXE): example64.o $(STATICLIB)
+	$(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS)
+
+minigzip64$(EXE): minigzip64.o $(STATICLIB)
+	$(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS)
+
+install-libs: $(LIBS)
+	- at if [ ! -d $(DESTDIR)$(exec_prefix)  ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi
+	- at if [ ! -d $(DESTDIR)$(libdir)       ]; then mkdir -p $(DESTDIR)$(libdir); fi
+	- at if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi
+	- at if [ ! -d $(DESTDIR)$(man3dir)      ]; then mkdir -p $(DESTDIR)$(man3dir); fi
+	- at if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi
+	cp $(STATICLIB) $(DESTDIR)$(libdir)
+	chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB)
+	-@($(RANLIB) $(DESTDIR)$(libdir)/libz.a || true) >/dev/null 2>&1
+	- at if test -n "$(SHAREDLIBV)"; then \
+	  cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir); \
+	  echo "cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)"; \
+	  chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \
+	  echo "chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV)"; \
+	  rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \
+	  ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB); \
+	  ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \
+	  ($(LDCONFIG) || true)  >/dev/null 2>&1; \
 	fi
-	cp zlib.3 $(man3dir)
-	chmod 644 $(man3dir)/zlib.3
+	cp zlib.3 $(DESTDIR)$(man3dir)
+	chmod 644 $(DESTDIR)$(man3dir)/zlib.3
+	cp zlib.pc $(DESTDIR)$(pkgconfigdir)
+	chmod 644 $(DESTDIR)$(pkgconfigdir)/zlib.pc
 # The ranlib in install is needed on NeXTSTEP which checks file times
 # ldconfig is for Linux
 
+install: install-libs
+	- at if [ ! -d $(DESTDIR)$(includedir)   ]; then mkdir -p $(DESTDIR)$(includedir); fi
+	cp zlib.h zconf.h $(DESTDIR)$(includedir)
+	chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h
+
 uninstall:
-	cd $(includedir); \
-	cd $(libdir); rm -f libz.a; \
-	if test -f $(SHAREDLIBV); then \
+	cd $(DESTDIR)$(includedir) && rm -f zlib.h zconf.h
+	cd $(DESTDIR)$(libdir) && rm -f libz.a; \
+	if test -n "$(SHAREDLIBV)" -a -f $(SHAREDLIBV); then \
 	  rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \
 	fi
-	cd $(man3dir); rm -f zlib.3
+	cd $(DESTDIR)$(man3dir) && rm -f zlib.3
+	cd $(DESTDIR)$(pkgconfigdir) && rm -f zlib.pc
+
+docs: zlib.3.pdf
+
+zlib.3.pdf: zlib.3
+	groff -mandoc -f H -T ps zlib.3 | ps2pdf - zlib.3.pdf
+
+zconf.h.cmakein: zconf.h.in
+	-@ TEMPFILE=zconfh_$$; \
+	echo "/#define ZCONF_H/ a\\\\\n#cmakedefine Z_PREFIX\\\\\n#cmakedefine Z_HAVE_UNISTD_H\n" >> $$TEMPFILE &&\
+	sed -f $$TEMPFILE zconf.h.in > zconf.h.cmakein &&\
+	touch -r zconf.h.in zconf.h.cmakein &&\
+	rm $$TEMPFILE
+
+zconf: zconf.h.in
+	cp -p zconf.h.in zconf.h
 
 mostlyclean: clean
 clean:
-	rm -f *.o *~ example$(EXE) minigzip$(EXE) \
+	rm -f *.o *.lo *~ \
+	   example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \
+	   example64$(EXE) minigzip64$(EXE) \
+	   infcover \
 	   libz.* foo.gz so_locations \
 	   _match.s maketree contrib/infback9/*.o
+	rm -rf objs
+	rm -f *.gcda *.gcno *.gcov
+	rm -f contrib/infback9/*.gcda contrib/infback9/*.gcno contrib/infback9/*.gcov
 
 maintainer-clean: distclean
-distclean: clean
-	cp -p Makefile.in Makefile
-	cp -p zconf.in.h zconf.h
-	rm -f .DS_Store
+distclean: clean zconf zconf.h.cmakein docs
+	rm -f Makefile zlib.pc configure.log
+	- at rm -f .DS_Store
+	- at printf 'all:\n\t- at echo "Please use ./configure first.  Thank you."\n' > Makefile
+	- at printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile
+	- at touch -r Makefile.in Makefile
 
 tags:
 	etags *.[ch]
@@ -138,17 +267,22 @@ depend:
 
 # DO NOT DELETE THIS LINE -- make depend depends on it.
 
-adler32.o: zlib.h zconf.h
-compress.o: zlib.h zconf.h
-crc32.o: crc32.h zlib.h zconf.h
+adler32.o zutil.o: zutil.h zlib.h zconf.h
+gzclose.o gzlib.o gzread.o gzwrite.o: zlib.h zconf.h gzguts.h
+compress.o example.o minigzip.o uncompr.o: zlib.h zconf.h
+crc32.o: zutil.h zlib.h zconf.h crc32.h
 deflate.o: deflate.h zutil.h zlib.h zconf.h
-example.o: zlib.h zconf.h
-gzio.o: zutil.h zlib.h zconf.h
+infback.o inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inffixed.h
 inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
-inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
-infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
 inftrees.o: zutil.h zlib.h zconf.h inftrees.h
-minigzip.o: zlib.h zconf.h
 trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
-uncompr.o: zlib.h zconf.h
-zutil.o: zutil.h zlib.h zconf.h
+
+adler32.lo zutil.lo: zutil.h zlib.h zconf.h
+gzclose.lo gzlib.lo gzread.lo gzwrite.lo: zlib.h zconf.h gzguts.h
+compress.lo example.lo minigzip.lo uncompr.lo: zlib.h zconf.h
+crc32.lo: zutil.h zlib.h zconf.h crc32.h
+deflate.lo: deflate.h zutil.h zlib.h zconf.h
+infback.lo inflate.lo: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inffixed.h
+inffast.lo: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inftrees.lo: zutil.h zlib.h zconf.h inftrees.h
+trees.lo: deflate.h zutil.h zlib.h zconf.h trees.h
diff --git a/third_party/zlib/README b/third_party/zlib/README
index 758cc50..5ca9d12 100644
--- a/third_party/zlib/README
+++ b/third_party/zlib/README
@@ -1,56 +1,52 @@
 ZLIB DATA COMPRESSION LIBRARY
 
-zlib 1.2.3 is a general purpose data compression library.  All the code is
+zlib 1.2.8 is a general purpose data compression library.  All the code is
 thread safe.  The data format used by the zlib library is described by RFCs
 (Request for Comments) 1950 to 1952 in the files
-http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
-and rfc1952.txt (gzip format). These documents are also available in other
-formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
+http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
+rfc1952 (gzip format).
 
 All functions of the compression library are documented in the file zlib.h
-(volunteer to write man pages welcome, contact zlib at gzip.org). A usage example
-of the library is given in the file example.c which also tests that the library
-is working correctly. Another example is given in the file minigzip.c. The
-compression library itself is composed of all source files except example.c and
-minigzip.c.
+(volunteer to write man pages welcome, contact zlib at gzip.org).  A usage example
+of the library is given in the file test/example.c which also tests that
+the library is working correctly.  Another example is given in the file
+test/minigzip.c.  The compression library itself is composed of all source
+files in the root directory.
 
 To compile all files and run the test program, follow the instructions given at
-the top of Makefile. In short "make test; make install" should work for most
-machines. For Unix: "./configure; make test; make install". For MSDOS, use one
-of the special makefiles such as Makefile.msc. For VMS, use make_vms.com.
+the top of Makefile.in.  In short "./configure; make test", and if that goes
+well, "make install" should work for most flavors of Unix.  For Windows, use
+one of the special makefiles in win32/ or contrib/vstudio/ .  For VMS, use
+make_vms.com.
 
 Questions about zlib should be sent to <zlib at gzip.org>, or to Gilles Vollant
-<info at winimage.com> for the Windows DLL version. The zlib home page is
-http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem,
-please check this site to verify that you have the latest version of zlib;
-otherwise get the latest version and check whether the problem still exists or
-not.
+<info at winimage.com> for the Windows DLL version.  The zlib home page is
+http://zlib.net/ .  Before reporting a problem, please check this site to
+verify that you have the latest version of zlib; otherwise get the latest
+version and check whether the problem still exists or not.
 
-PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking
-for help.
+PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help.
 
-Mark Nelson <markn at ieee.org> wrote an article about zlib for the Jan. 1997
-issue of  Dr. Dobb's Journal; a copy of the article is available in
-http://dogma.net/markn/articles/zlibtool/zlibtool.htm
+Mark Nelson <markn at ieee.org> wrote an article about zlib for the Jan.  1997
+issue of Dr.  Dobb's Journal; a copy of the article is available at
+http://marknelson.us/1997/01/01/zlib-engine/ .
 
-The changes made in version 1.2.3 are documented in the file ChangeLog.
+The changes made in version 1.2.8 are documented in the file ChangeLog.
 
-Unsupported third party contributions are provided in directory "contrib".
+Unsupported third party contributions are provided in directory contrib/ .
 
-A Java implementation of zlib is available in the Java Development Kit
-http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html
-See the zlib home page http://www.zlib.org for details.
+zlib is available in Java using the java.util.zip package, documented at
+http://java.sun.com/developer/technicalArticles/Programming/compression/ .
 
-A Perl interface to zlib written by Paul Marquess <pmqs at cpan.org> is in the
-CPAN (Comprehensive Perl Archive Network) sites
-http://www.cpan.org/modules/by-module/Compress/
+A Perl interface to zlib written by Paul Marquess <pmqs at cpan.org> is available
+at CPAN (Comprehensive Perl Archive Network) sites, including
+http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
 
 A Python interface to zlib written by A.M. Kuchling <amk at amk.ca> is
 available in Python 1.5 and later versions, see
-http://www.python.org/doc/lib/module-zlib.html
+http://docs.python.org/library/zlib.html .
 
-A zlib binding for TCL written by Andreas Kupries <a.kupries at westend.com> is
-availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html
+zlib is built into tcl: http://wiki.tcl.tk/4610 .
 
 An experimental package to read and write files in .zip format, written on top
 of zlib by Gilles Vollant <info at winimage.com>, is available in the
@@ -74,25 +70,21 @@ Notes for some targets:
 - zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
   other compilers. Use "make test" to check your compiler.
 
-- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
+- gzdopen is not supported on RISCOS or BEOS.
 
 - For PalmOs, see http://palmzlib.sourceforge.net/
 
-- When building a shared, i.e. dynamic library on Mac OS X, the library must be
-  installed before testing (do "make install" before "make test"), since the
-  library location is specified in the library.
-
 
 Acknowledgments:
 
-  The deflate format used by zlib was defined by Phil Katz. The deflate
-  and zlib specifications were written by L. Peter Deutsch. Thanks to all the
-  people who reported problems and suggested various improvements in zlib;
-  they are too numerous to cite here.
+  The deflate format used by zlib was defined by Phil Katz.  The deflate and
+  zlib specifications were written by L.  Peter Deutsch.  Thanks to all the
+  people who reported problems and suggested various improvements in zlib; they
+  are too numerous to cite here.
 
 Copyright notice:
 
- (C) 1995-2004 Jean-loup Gailly and Mark Adler
+ (C) 1995-2013 Jean-loup Gailly and Mark Adler
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -113,13 +105,11 @@ Copyright notice:
   Jean-loup Gailly        Mark Adler
   jloup at gzip.org          madler at alumni.caltech.edu
 
-If you use the zlib library in a product, we would appreciate *not*
-receiving lengthy legal documents to sign. The sources are provided
-for free but without warranty of any kind.  The library has been
-entirely written by Jean-loup Gailly and Mark Adler; it does not
-include third-party code.
+If you use the zlib library in a product, we would appreciate *not* receiving
+lengthy legal documents to sign.  The sources are provided for free but without
+warranty of any kind.  The library has been entirely written by Jean-loup
+Gailly and Mark Adler; it does not include third-party code.
 
-If you redistribute modified sources, we would appreciate that you include
-in the file ChangeLog history information documenting your changes. Please
-read the FAQ for more information on the distribution of modified source
-versions.
+If you redistribute modified sources, we would appreciate that you include in
+the file ChangeLog history information documenting your changes.  Please read
+the FAQ for more information on the distribution of modified source versions.
diff --git a/third_party/zlib/adler32.c b/third_party/zlib/adler32.c
index b5333d7..a868f07 100644
--- a/third_party/zlib/adler32.c
+++ b/third_party/zlib/adler32.c
@@ -1,5 +1,5 @@
 /* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995-2004 Mark Adler
+ * Copyright (C) 1995-2011 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -7,7 +7,11 @@
 
 #include "zutil.h"
 
-#define BASE 65521UL    /* largest prime smaller than 65536 */
+#define local static
+
+local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
+
+#define BASE 65521      /* largest prime smaller than 65536 */
 #define NMAX 5552
 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
 
@@ -17,39 +21,44 @@
 #define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
 #define DO16(buf)   DO8(buf,0); DO8(buf,8);
 
-/* use NO_DIVIDE if your processor does not do division in hardware */
+/* use NO_DIVIDE if your processor does not do division in hardware --
+   try it both ways to see which is faster */
 #ifdef NO_DIVIDE
-#  define MOD(a) \
+/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
+   (thank you to John Reiser for pointing this out) */
+#  define CHOP(a) \
     do { \
-        if (a >= (BASE << 16)) a -= (BASE << 16); \
-        if (a >= (BASE << 15)) a -= (BASE << 15); \
-        if (a >= (BASE << 14)) a -= (BASE << 14); \
-        if (a >= (BASE << 13)) a -= (BASE << 13); \
-        if (a >= (BASE << 12)) a -= (BASE << 12); \
-        if (a >= (BASE << 11)) a -= (BASE << 11); \
-        if (a >= (BASE << 10)) a -= (BASE << 10); \
-        if (a >= (BASE << 9)) a -= (BASE << 9); \
-        if (a >= (BASE << 8)) a -= (BASE << 8); \
-        if (a >= (BASE << 7)) a -= (BASE << 7); \
-        if (a >= (BASE << 6)) a -= (BASE << 6); \
-        if (a >= (BASE << 5)) a -= (BASE << 5); \
-        if (a >= (BASE << 4)) a -= (BASE << 4); \
-        if (a >= (BASE << 3)) a -= (BASE << 3); \
-        if (a >= (BASE << 2)) a -= (BASE << 2); \
-        if (a >= (BASE << 1)) a -= (BASE << 1); \
+        unsigned long tmp = a >> 16; \
+        a &= 0xffffUL; \
+        a += (tmp << 4) - tmp; \
+    } while (0)
+#  define MOD28(a) \
+    do { \
+        CHOP(a); \
         if (a >= BASE) a -= BASE; \
     } while (0)
-#  define MOD4(a) \
+#  define MOD(a) \
     do { \
-        if (a >= (BASE << 4)) a -= (BASE << 4); \
-        if (a >= (BASE << 3)) a -= (BASE << 3); \
-        if (a >= (BASE << 2)) a -= (BASE << 2); \
-        if (a >= (BASE << 1)) a -= (BASE << 1); \
+        CHOP(a); \
+        MOD28(a); \
+    } while (0)
+#  define MOD63(a) \
+    do { /* this assumes a is not negative */ \
+        z_off64_t tmp = a >> 32; \
+        a &= 0xffffffffL; \
+        a += (tmp << 8) - (tmp << 5) + tmp; \
+        tmp = a >> 16; \
+        a &= 0xffffL; \
+        a += (tmp << 4) - tmp; \
+        tmp = a >> 16; \
+        a &= 0xffffL; \
+        a += (tmp << 4) - tmp; \
         if (a >= BASE) a -= BASE; \
     } while (0)
 #else
 #  define MOD(a) a %= BASE
-#  define MOD4(a) a %= BASE
+#  define MOD28(a) a %= BASE
+#  define MOD63(a) a %= BASE
 #endif
 
 /* ========================================================================= */
@@ -88,7 +97,7 @@ uLong ZEXPORT adler32(adler, buf, len)
         }
         if (adler >= BASE)
             adler -= BASE;
-        MOD4(sum2);             /* only added so many BASE's */
+        MOD28(sum2);            /* only added so many BASE's */
         return adler | (sum2 << 16);
     }
 
@@ -124,25 +133,47 @@ uLong ZEXPORT adler32(adler, buf, len)
 }
 
 /* ========================================================================= */
-uLong ZEXPORT adler32_combine(adler1, adler2, len2)
+local uLong adler32_combine_(adler1, adler2, len2)
     uLong adler1;
     uLong adler2;
-    z_off_t len2;
+    z_off64_t len2;
 {
     unsigned long sum1;
     unsigned long sum2;
     unsigned rem;
 
+    /* for negative len, return invalid adler32 as a clue for debugging */
+    if (len2 < 0)
+        return 0xffffffffUL;
+
     /* the derivation of this formula is left as an exercise for the reader */
-    rem = (unsigned)(len2 % BASE);
+    MOD63(len2);                /* assumes len2 >= 0 */
+    rem = (unsigned)len2;
     sum1 = adler1 & 0xffff;
     sum2 = rem * sum1;
     MOD(sum2);
     sum1 += (adler2 & 0xffff) + BASE - 1;
     sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
-    if (sum1 > BASE) sum1 -= BASE;
-    if (sum1 > BASE) sum1 -= BASE;
-    if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
-    if (sum2 > BASE) sum2 -= BASE;
+    if (sum1 >= BASE) sum1 -= BASE;
+    if (sum1 >= BASE) sum1 -= BASE;
+    if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
+    if (sum2 >= BASE) sum2 -= BASE;
     return sum1 | (sum2 << 16);
 }
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(adler1, adler2, len2)
+    uLong adler1;
+    uLong adler2;
+    z_off_t len2;
+{
+    return adler32_combine_(adler1, adler2, len2);
+}
+
+uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
+    uLong adler1;
+    uLong adler2;
+    z_off64_t len2;
+{
+    return adler32_combine_(adler1, adler2, len2);
+}
diff --git a/third_party/zlib/algorithm.txt b/third_party/zlib/algorithm.txt
deleted file mode 100644
index b022dde..0000000
--- a/third_party/zlib/algorithm.txt
+++ /dev/null
@@ -1,209 +0,0 @@
-1. Compression algorithm (deflate)
-
-The deflation algorithm used by gzip (also zip and zlib) is a variation of
-LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
-the input data.  The second occurrence of a string is replaced by a
-pointer to the previous string, in the form of a pair (distance,
-length).  Distances are limited to 32K bytes, and lengths are limited
-to 258 bytes. When a string does not occur anywhere in the previous
-32K bytes, it is emitted as a sequence of literal bytes.  (In this
-description, `string' must be taken as an arbitrary sequence of bytes,
-and is not restricted to printable characters.)
-
-Literals or match lengths are compressed with one Huffman tree, and
-match distances are compressed with another tree. The trees are stored
-in a compact form at the start of each block. The blocks can have any
-size (except that the compressed data for one block must fit in
-available memory). A block is terminated when deflate() determines that
-it would be useful to start another block with fresh trees. (This is
-somewhat similar to the behavior of LZW-based _compress_.)
-
-Duplicated strings are found using a hash table. All input strings of
-length 3 are inserted in the hash table. A hash index is computed for
-the next 3 bytes. If the hash chain for this index is not empty, all
-strings in the chain are compared with the current input string, and
-the longest match is selected.
-
-The hash chains are searched starting with the most recent strings, to
-favor small distances and thus take advantage of the Huffman encoding.
-The hash chains are singly linked. There are no deletions from the
-hash chains, the algorithm simply discards matches that are too old.
-
-To avoid a worst-case situation, very long hash chains are arbitrarily
-truncated at a certain length, determined by a runtime option (level
-parameter of deflateInit). So deflate() does not always find the longest
-possible match but generally finds a match which is long enough.
-
-deflate() also defers the selection of matches with a lazy evaluation
-mechanism. After a match of length N has been found, deflate() searches for
-a longer match at the next input byte. If a longer match is found, the
-previous match is truncated to a length of one (thus producing a single
-literal byte) and the process of lazy evaluation begins again. Otherwise,
-the original match is kept, and the next match search is attempted only N
-steps later.
-
-The lazy match evaluation is also subject to a runtime parameter. If
-the current match is long enough, deflate() reduces the search for a longer
-match, thus speeding up the whole process. If compression ratio is more
-important than speed, deflate() attempts a complete second search even if
-the first match is already long enough.
-
-The lazy match evaluation is not performed for the fastest compression
-modes (level parameter 1 to 3). For these fast modes, new strings
-are inserted in the hash table only when no match was found, or
-when the match is not too long. This degrades the compression ratio
-but saves time since there are both fewer insertions and fewer searches.
-
-
-2. Decompression algorithm (inflate)
-
-2.1 Introduction
-
-The key question is how to represent a Huffman code (or any prefix code) so
-that you can decode fast.  The most important characteristic is that shorter
-codes are much more common than longer codes, so pay attention to decoding the
-short codes fast, and let the long codes take longer to decode.
-
-inflate() sets up a first level table that covers some number of bits of
-input less than the length of longest code.  It gets that many bits from the
-stream, and looks it up in the table.  The table will tell if the next
-code is that many bits or less and how many, and if it is, it will tell
-the value, else it will point to the next level table for which inflate()
-grabs more bits and tries to decode a longer code.
-
-How many bits to make the first lookup is a tradeoff between the time it
-takes to decode and the time it takes to build the table.  If building the
-table took no time (and if you had infinite memory), then there would only
-be a first level table to cover all the way to the longest code.  However,
-building the table ends up taking a lot longer for more bits since short
-codes are replicated many times in such a table.  What inflate() does is
-simply to make the number of bits in the first table a variable, and  then
-to set that variable for the maximum speed.
-
-For inflate, which has 286 possible codes for the literal/length tree, the size
-of the first table is nine bits.  Also the distance trees have 30 possible
-values, and the size of the first table is six bits.  Note that for each of
-those cases, the table ended up one bit longer than the ``average'' code
-length, i.e. the code length of an approximately flat code which would be a
-little more than eight bits for 286 symbols and a little less than five bits
-for 30 symbols.
-
-
-2.2 More details on the inflate table lookup
-
-Ok, you want to know what this cleverly obfuscated inflate tree actually
-looks like.  You are correct that it's not a Huffman tree.  It is simply a
-lookup table for the first, let's say, nine bits of a Huffman symbol.  The
-symbol could be as short as one bit or as long as 15 bits.  If a particular
-symbol is shorter than nine bits, then that symbol's translation is duplicated
-in all those entries that start with that symbol's bits.  For example, if the
-symbol is four bits, then it's duplicated 32 times in a nine-bit table.  If a
-symbol is nine bits long, it appears in the table once.
-
-If the symbol is longer than nine bits, then that entry in the table points
-to another similar table for the remaining bits.  Again, there are duplicated
-entries as needed.  The idea is that most of the time the symbol will be short
-and there will only be one table look up.  (That's whole idea behind data
-compression in the first place.)  For the less frequent long symbols, there
-will be two lookups.  If you had a compression method with really long
-symbols, you could have as many levels of lookups as is efficient.  For
-inflate, two is enough.
-
-So a table entry either points to another table (in which case nine bits in
-the above example are gobbled), or it contains the translation for the symbol
-and the number of bits to gobble.  Then you start again with the next
-ungobbled bit.
-
-You may wonder: why not just have one lookup table for how ever many bits the
-longest symbol is?  The reason is that if you do that, you end up spending
-more time filling in duplicate symbol entries than you do actually decoding.
-At least for deflate's output that generates new trees every several 10's of
-kbytes.  You can imagine that filling in a 2^15 entry table for a 15-bit code
-would take too long if you're only decoding several thousand symbols.  At the
-other extreme, you could make a new table for every bit in the code.  In fact,
-that's essentially a Huffman tree.  But then you spend two much time
-traversing the tree while decoding, even for short symbols.
-
-So the number of bits for the first lookup table is a trade of the time to
-fill out the table vs. the time spent looking at the second level and above of
-the table.
-
-Here is an example, scaled down:
-
-The code being decoded, with 10 symbols, from 1 to 6 bits long:
-
-A: 0
-B: 10
-C: 1100
-D: 11010
-E: 11011
-F: 11100
-G: 11101
-H: 11110
-I: 111110
-J: 111111
-
-Let's make the first table three bits long (eight entries):
-
-000: A,1
-001: A,1
-010: A,1
-011: A,1
-100: B,2
-101: B,2
-110: -> table X (gobble 3 bits)
-111: -> table Y (gobble 3 bits)
-
-Each entry is what the bits decode as and how many bits that is, i.e. how
-many bits to gobble.  Or the entry points to another table, with the number of
-bits to gobble implicit in the size of the table.
-
-Table X is two bits long since the longest code starting with 110 is five bits
-long:
-
-00: C,1
-01: C,1
-10: D,2
-11: E,2
-
-Table Y is three bits long since the longest code starting with 111 is six
-bits long:
-
-000: F,2
-001: F,2
-010: G,2
-011: G,2
-100: H,2
-101: H,2
-110: I,3
-111: J,3
-
-So what we have here are three tables with a total of 20 entries that had to
-be constructed.  That's compared to 64 entries for a single table.  Or
-compared to 16 entries for a Huffman tree (six two entry tables and one four
-entry table).  Assuming that the code ideally represents the probability of
-the symbols, it takes on the average 1.25 lookups per symbol.  That's compared
-to one lookup for the single table, or 1.66 lookups per symbol for the
-Huffman tree.
-
-There, I think that gives you a picture of what's going on.  For inflate, the
-meaning of a particular symbol is often more than just a letter.  It can be a
-byte (a "literal"), or it can be either a length or a distance which
-indicates a base value and a number of bits to fetch after the code that is
-added to the base value.  Or it might be the special end-of-block code.  The
-data structures created in inftrees.c try to encode all that information
-compactly in the tables.
-
-
-Jean-loup Gailly        Mark Adler
-jloup at gzip.org          madler at alumni.caltech.edu
-
-
-References:
-
-[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
-Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
-pp. 337-343.
-
-``DEFLATE Compressed Data Format Specification'' available in
-http://www.ietf.org/rfc/rfc1951.txt
diff --git a/third_party/zlib/amiga/Makefile.pup b/third_party/zlib/amiga/Makefile.pup
index 3f7e155..8940c12 100644
--- a/third_party/zlib/amiga/Makefile.pup
+++ b/third_party/zlib/amiga/Makefile.pup
@@ -14,8 +14,8 @@ LDFLAGS	= -o
 LDLIBS	= LIB:scppc.a LIB:end.o
 RM	= delete quiet
 
-OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
-       zutil.o inflate.o infback.o inftrees.o inffast.o
+OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \
+       uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
 
 TEST_OBJS = example.o minigzip.o
 
@@ -55,7 +55,10 @@ compress.o: zlib.h zconf.h
 crc32.o: crc32.h zlib.h zconf.h
 deflate.o: deflate.h zutil.h zlib.h zconf.h
 example.o: zlib.h zconf.h
-gzio.o: zutil.h zlib.h zconf.h
+gzclose.o: zlib.h zconf.h gzguts.h
+gzlib.o: zlib.h zconf.h gzguts.h
+gzread.o: zlib.h zconf.h gzguts.h
+gzwrite.o: zlib.h zconf.h gzguts.h
 inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
 inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
 infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
diff --git a/third_party/zlib/amiga/Makefile.sas b/third_party/zlib/amiga/Makefile.sas
index 296ef48..749e291 100644
--- a/third_party/zlib/amiga/Makefile.sas
+++ b/third_party/zlib/amiga/Makefile.sas
@@ -13,8 +13,8 @@ SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \
        NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX \
        DEF=POSTINC
 
-OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
-       zutil.o inflate.o infback.o inftrees.o inffast.o
+OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \
+       uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
 
 TEST_OBJS = example.o minigzip.o
 
@@ -54,7 +54,10 @@ compress.o: zlib.h zconf.h
 crc32.o: crc32.h zlib.h zconf.h
 deflate.o: deflate.h zutil.h zlib.h zconf.h
 example.o: zlib.h zconf.h
-gzio.o: zutil.h zlib.h zconf.h
+gzclose.o: zlib.h zconf.h gzguts.h
+gzlib.o: zlib.h zconf.h gzguts.h
+gzread.o: zlib.h zconf.h gzguts.h
+gzwrite.o: zlib.h zconf.h gzguts.h
 inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
 inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
 infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
diff --git a/third_party/zlib/as400/bndsrc b/third_party/zlib/as400/bndsrc
index 9cf94bb..98814fd 100644
--- a/third_party/zlib/as400/bndsrc
+++ b/third_party/zlib/as400/bndsrc
@@ -129,4 +129,87 @@ STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ZLIB')
 
   EXPORT SYMBOL("zlibCompileFlags")
 
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+/*   Version 1.2.5 additional entry points.                         */
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+/********************************************************************/
+/*   *MODULE      ADLER32      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("adler32_combine")
+  EXPORT SYMBOL("adler32_combine64")
+
+/********************************************************************/
+/*   *MODULE      CRC32        ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("crc32_combine")
+  EXPORT SYMBOL("crc32_combine64")
+
+/********************************************************************/
+/*   *MODULE      GZLIB        ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("gzbuffer")
+  EXPORT SYMBOL("gzoffset")
+  EXPORT SYMBOL("gzoffset64")
+  EXPORT SYMBOL("gzopen64")
+  EXPORT SYMBOL("gzseek64")
+  EXPORT SYMBOL("gztell64")
+
+/********************************************************************/
+/*   *MODULE      GZREAD       ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("gzclose_r")
+
+/********************************************************************/
+/*   *MODULE      GZWRITE      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("gzclose_w")
+
+/********************************************************************/
+/*   *MODULE      INFLATE      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("inflateMark")
+  EXPORT SYMBOL("inflatePrime")
+  EXPORT SYMBOL("inflateReset2")
+  EXPORT SYMBOL("inflateUndermine")
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+/*   Version 1.2.6 additional entry points.                         */
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+/********************************************************************/
+/*   *MODULE      DEFLATE      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("deflateResetKeep")
+  EXPORT SYMBOL("deflatePending")
+
+/********************************************************************/
+/*   *MODULE      GZWRITE      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("gzgetc_")
+
+/********************************************************************/
+/*   *MODULE      INFLATE      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("inflateResetKeep")
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+/*   Version 1.2.8 additional entry points.                         */
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+/********************************************************************/
+/*   *MODULE      INFLATE      ZLIB         01/02/01  00:15:09      */
+/********************************************************************/
+
+  EXPORT SYMBOL("inflateGetDictionary")
+
 ENDPGMEXP
diff --git a/third_party/zlib/as400/compile.clp b/third_party/zlib/as400/compile.clp
index 8554951..e3f47c6 100644
--- a/third_party/zlib/as400/compile.clp
+++ b/third_party/zlib/as400/compile.clp
@@ -26,85 +26,70 @@
              DCL        VAR(&CFLAGS) TYPE(*CHAR) +
                           VALUE('OPTIMIZE(40)')                 /* Compile options. */
 
+             DCL        VAR(&TGTRLS) TYPE(*CHAR) +
+                          VALUE('V5R3M0')                       /* Target release. */
+
 
 /*      Working storage.                                                      */
 
              DCL        VAR(&CMDLEN) TYPE(*DEC) LEN(15 5) VALUE(300)    /* Command length. */
              DCL        VAR(&CMD) TYPE(*CHAR) LEN(512)
+             DCL        VAR(&FIXDCMD) TYPE(*CHAR) LEN(512)
 
 
 /*      Compile sources into modules.                                         */
 
-             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
-                        '/ADLER32)               SRCFILE(' *TCAT               +
-                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
-                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CHGVAR     VAR(&FIXDCMD) VALUE('CRTCMOD' *BCAT &CFLAGS *BCAT      +
+                        'SYSIFCOPT(*IFS64IO)' *BCAT                            +
+                        'DEFINE(''_LARGEFILE64_SOURCE''' *BCAT                 +
+                        '''_LFS64_LARGEFILE=1'') TGTRLS(' *TCAT &TGTRLS *TCAT  +
+                        ') SRCFILE(' *TCAT &SRCLIB *TCAT '/' *TCAT             +
+                        &SRCFILE *TCAT ') MODULE(' *TCAT &MODLIB *TCAT '/')
+
+
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'ADLER32)')
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'COMPRESS)')
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'CRC32)')
+             CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
+
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'DEFLATE)')
              CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
 
-             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
-                        '/COMPRESS)              SRCFILE(' *TCAT               +
-                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
-                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'GZCLOSE)')
              CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
 
-             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
-                        '/CRC32)                 SRCFILE(' *TCAT               +
-                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
-                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'GZLIB)')
              CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
 
-             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
-                        '/DEFLATE)               SRCFILE(' *TCAT               +
-                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
-                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'GZREAD)')
              CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
 
-             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
-                        '/GZIO)                  SRCFILE(' *TCAT               +
-                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
-                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'GZWRITE)')
              CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
 
-             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
-                        '/INFBACK)               SRCFILE(' *TCAT               +
-                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
-                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'INFBACK)')
              CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
 
-             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
-                        '/INFFAST)               SRCFILE(' *TCAT               +
-                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
-                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'INFFAST)')
              CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
 
-             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
-                        '/INFLATE)               SRCFILE(' *TCAT               +
-                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
-                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'INFLATE)')
              CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
 
-             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
-                        '/INFTREES)              SRCFILE(' *TCAT               +
-                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
-                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'INFTREES)')
              CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
 
-             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
-                        '/TREES)                 SRCFILE(' *TCAT               +
-                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
-                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'TREES)')
              CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
 
-             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
-                        '/UNCOMPR)               SRCFILE(' *TCAT               +
-                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
-                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'UNCOMPR)')
              CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
 
-             CHGVAR     VAR(&CMD) VALUE('CRTCMOD MODULE(' *TCAT &MODLIB *TCAT  +
-                        '/ZUTIL)                 SRCFILE(' *TCAT               +
-                        &SRCLIB *TCAT '/' *TCAT &SRCFILE *TCAT                 +
-                        ') SYSIFCOPT(*IFSIO)' *BCAT &CFLAGS)
+             CHGVAR     VAR(&CMD) VALUE(&FIXDCMD *TCAT 'ZUTIL)')
              CALL       PGM(QCMDEXC) PARM(&CMD &CMDLEN)
 
 
@@ -113,11 +98,13 @@
              CRTSRVPGM  SRVPGM(&SRVLIB/ZLIB) +
                           MODULE(&MODLIB/ADLER32     &MODLIB/COMPRESS    +
                                  &MODLIB/CRC32       &MODLIB/DEFLATE     +
-                                 &MODLIB/GZIO        &MODLIB/INFBACK     +
-                                 &MODLIB/INFFAST     &MODLIB/INFLATE     +
-                                 &MODLIB/INFTREES    &MODLIB/TREES       +
-                                 &MODLIB/UNCOMPR     &MODLIB/ZUTIL)      +
-                          SRCFILE(&SRCLIB/&CTLFILE) SRCMBR(BNDSRC) +
-                          TEXT('ZLIB 1.2.3') TGTRLS(V4R4M0)
+                                 &MODLIB/GZCLOSE     &MODLIB/GZLIB       +
+                                 &MODLIB/GZREAD      &MODLIB/GZWRITE     +
+                                 &MODLIB/INFBACK     &MODLIB/INFFAST     +
+                                 &MODLIB/INFLATE     &MODLIB/INFTREES    +
+                                 &MODLIB/TREES       &MODLIB/UNCOMPR     +
+                                 &MODLIB/ZUTIL)                          +
+                          SRCFILE(&SRCLIB/&CTLFILE) SRCMBR(BNDSRC)       +
+                          TEXT('ZLIB 1.2.8') TGTRLS(&TGTRLS)
 
              ENDPGM
diff --git a/third_party/zlib/as400/readme.txt b/third_party/zlib/as400/readme.txt
index beae13f..7b5d93b 100644
--- a/third_party/zlib/as400/readme.txt
+++ b/third_party/zlib/as400/readme.txt
@@ -1,4 +1,4 @@
-        ZLIB version 1.2.3 for AS400 installation instructions
+        ZLIB version 1.2.8 for AS400 installation instructions
 
 I) From an AS400 *SAVF file:
 
@@ -8,7 +8,7 @@ On the AS400:
 
 _       Create the ZLIB AS400 library:
 
-        CRTLIB LIB(ZLIB) TYPE(PROD) TEXT('ZLIB compression API library')
+        CRTLIB LIB(ZLIB) TYPE(*PROD) TEXT('ZLIB compression API library')
 
 _       Create a work save file, for example:
 
@@ -52,7 +52,7 @@ II) From the original source distribution:
 
 1)      On the AS400, create the source library:
 
-        CRTLIB LIB(ZLIB) TYPE(PROD) TEXT('ZLIB compression API library')
+        CRTLIB LIB(ZLIB) TYPE(*PROD) TEXT('ZLIB compression API library')
 
 2)      Create the source files:
 
@@ -70,7 +70,10 @@ II) From the original source distribution:
     compress.c          COMPRESS C     ZLIB - Compress a memory buffer
     crc32.c             CRC32    C     ZLIB - Compute the CRC-32 of a data stream
     deflate.c           DEFLATE  C     ZLIB - Compress data using the deflation algorithm
-    gzio.c              GZIO     C     ZLIB - IO on .gz files
+    gzclose.c           GZCLOSE  C     ZLIB - Close .gz files
+    gzlib.c             GZLIB    C     ZLIB - Miscellaneous .gz files IO support
+    gzread.c            GZREAD   C     ZLIB - Read .gz files
+    gzwrite.c           GZWRITE  C     ZLIB - Write .gz files
     infback.c           INFBACK  C     ZLIB - Inflate using a callback interface
     inffast.c           INFFAST  C     ZLIB - Fast proc. literals & length/distance pairs
     inflate.c           INFLATE  C     ZLIB - Interface to inflate modules
@@ -81,6 +84,7 @@ II) From the original source distribution:
                 H                      Original ZLIB C and ILE/RPG include files
     crc32.h             CRC32    C     ZLIB - CRC32 tables
     deflate.h           DEFLATE  C     ZLIB - Internal compression state
+    gzguts.h            GZGUTS   C     ZLIB - Definitions for the gzclose module
     inffast.h           INFFAST  C     ZLIB - Header to use inffast.c
     inffixed.h          INFFIXED C     ZLIB - Table for decoding fixed codes
     inflate.h           INFLATE  C     ZLIB - Internal inflate state definitions
@@ -108,4 +112,4 @@ Notes:  For AS400 ILE RPG programmers, a /copy member defining the ZLIB
                 implementation does not handle conversion from/to ASCII, so
                 text data code conversions must be done explicitely.
 
-        Always open zipped files in binary mode.
+        Mainly for the reason above, always open zipped files in binary mode.
diff --git a/third_party/zlib/as400/zlib.inc b/third_party/zlib/as400/zlib.inc
index 7bbfb7e..7341a6d 100644
--- a/third_party/zlib/as400/zlib.inc
+++ b/third_party/zlib/as400/zlib.inc
@@ -1,7 +1,7 @@
       *  ZLIB.INC - Interface to the general purpose compression library
       *
       *  ILE RPG400 version by Patrick Monnerat, DATASPHERE.
-      *  Version 1.2.3
+      *  Version 1.2.8
       *
       *
       *  WARNING:
@@ -22,16 +22,25 @@
       *
       *  Versioning information.
       *
-     D ZLIB_VERSION    C                   '1.2.3'
-     D ZLIB_VERNUM     C                   X'1230'
+     D ZLIB_VERSION    C                   '1.2.8'
+     D ZLIB_VERNUM     C                   X'1280'
+     D ZLIB_VER_MAJOR  C                   1
+     D ZLIB_VER_MINOR  C                   2
+     D ZLIB_VER_REVISION...
+     D                 C                   8
+     D ZLIB_VER_SUBREVISION...
+     D                 C                   0
       *
       *  Other equates.
       *
      D Z_NO_FLUSH      C                   0
+     D Z_PARTIAL_FLUSH...
+     D                 C                   1
      D Z_SYNC_FLUSH    C                   2
      D Z_FULL_FLUSH    C                   3
      D Z_FINISH        C                   4
      D Z_BLOCK         C                   5
+     D Z_TREES         C                   6
       *
      D Z_OK            C                   0
      D Z_STREAM_END    C                   1
@@ -72,6 +81,7 @@
      D z_streamp       S               *                                        Stream struct ptr
      D gzFile          S               *                                        File pointer
      D z_off_t         S             10i 0                                      Stream offsets
+     D z_off64_t       S             20i 0                                      Stream offsets
       *
       **************************************************************************
       *                               Structures
@@ -101,15 +111,15 @@
       **************************************************************************
       *
      D compress        PR            10I 0 extproc('compress')
-     D  dest                      32767    options(*varsize)                    Destination buffer
+     D  dest                      65535    options(*varsize)                    Destination buffer
      D  destLen                      10U 0                                      Destination length
-     D  source                    32767    const options(*varsize)              Source buffer
+     D  source                    65535    const options(*varsize)              Source buffer
      D  sourceLen                    10u 0 value                                Source length
       *
      D compress2       PR            10I 0 extproc('compress2')
-     D  dest                      32767    options(*varsize)                    Destination buffer
+     D  dest                      65535    options(*varsize)                    Destination buffer
      D  destLen                      10U 0                                      Destination length
-     D  source                    32767    const options(*varsize)              Source buffer
+     D  source                    65535    const options(*varsize)              Source buffer
      D  sourceLen                    10U 0 value                                Source length
      D  level                        10I 0 value                                Compression level
       *
@@ -117,34 +127,50 @@
      D  sourceLen                    10U 0 value
       *
      D uncompress      PR            10I 0 extproc('uncompress')
-     D  dest                      32767    options(*varsize)                    Destination buffer
+     D  dest                      65535    options(*varsize)                    Destination buffer
      D  destLen                      10U 0                                      Destination length
-     D  source                    32767    const options(*varsize)              Source buffer
+     D  source                    65535    const options(*varsize)              Source buffer
      D  sourceLen                    10U 0 value                                Source length
       *
+      /if not defined(LARGE_FILES)
      D gzopen          PR                  extproc('gzopen')
      D                                     like(gzFile)
      D  path                           *   value options(*string)               File pathname
      D  mode                           *   value options(*string)               Open mode
+      /else
+     D gzopen          PR                  extproc('gzopen64')
+     D                                     like(gzFile)
+     D  path                           *   value options(*string)               File pathname
+     D  mode                           *   value options(*string)               Open mode
+      *
+     D gzopen64        PR                  extproc('gzopen64')
+     D                                     like(gzFile)
+     D  path                           *   value options(*string)               File pathname
+     D  mode                           *   value options(*string)               Open mode
+      /endif
       *
      D gzdopen         PR                  extproc('gzdopen')
      D                                     like(gzFile)
-     D  fd                           10i 0 value                                File descriptor
+     D  fd                           10I 0 value                                File descriptor
      D  mode                           *   value options(*string)               Open mode
       *
+     D gzbuffer        PR            10I 0 extproc('gzbuffer')
+     D  file                               value like(gzFile)                   File pointer
+     D  size                         10U 0 value
+      *
      D gzsetparams     PR            10I 0 extproc('gzsetparams')
      D  file                               value like(gzFile)                   File pointer
      D  level                        10I 0 value
-     D  strategy                     10i 0 value
+     D  strategy                     10I 0 value
       *
      D gzread          PR            10I 0 extproc('gzread')
      D  file                               value like(gzFile)                   File pointer
-     D  buf                       32767    options(*varsize)                    Buffer
+     D  buf                       65535    options(*varsize)                    Buffer
      D  len                          10u 0 value                                Buffer length
       *
      D gzwrite         PR            10I 0 extproc('gzwrite')
      D  file                               value like(gzFile)                   File pointer
-     D  buf                       32767    const options(*varsize)              Buffer
+     D  buf                       65535    const options(*varsize)              Buffer
      D  len                          10u 0 value                                Buffer length
       *
      D gzputs          PR            10I 0 extproc('gzputs')
@@ -153,29 +179,87 @@
       *
      D gzgets          PR              *   extproc('gzgets')
      D  file                               value like(gzFile)                   File pointer
-     D  buf                       32767    options(*varsize)                    Read buffer
+     D  buf                       65535    options(*varsize)                    Read buffer
      D  len                          10i 0 value                                Buffer length
       *
+     D gzputc          PR            10i 0 extproc('gzputc')
+     D  file                               value like(gzFile)                   File pointer
+     D  c                            10I 0 value                                Character to write
+      *
+     D gzgetc          PR            10i 0 extproc('gzgetc')
+     D  file                               value like(gzFile)                   File pointer
+      *
+     D gzgetc_         PR            10i 0 extproc('gzgetc_')
+     D  file                               value like(gzFile)                   File pointer
+      *
+     D gzungetc        PR            10i 0 extproc('gzungetc')
+     D  c                            10I 0 value                                Character to push
+     D  file                               value like(gzFile)                   File pointer
+      *
      D gzflush         PR            10i 0 extproc('gzflush')
      D  file                               value like(gzFile)                   File pointer
      D  flush                        10I 0 value                                Type of flush
       *
+      /if not defined(LARGE_FILES)
      D gzseek          PR                  extproc('gzseek')
      D                                     like(z_off_t)
      D  file                               value like(gzFile)                   File pointer
      D  offset                             value like(z_off_t)                  Offset
      D  whence                       10i 0 value                                Origin
+      /else
+     D gzseek          PR                  extproc('gzseek64')
+     D                                     like(z_off_t)
+     D  file                               value like(gzFile)                   File pointer
+     D  offset                             value like(z_off_t)                  Offset
+     D  whence                       10i 0 value                                Origin
+      *
+     D gzseek64        PR                  extproc('gzseek64')
+     D                                     like(z_off64_t)
+     D  file                               value like(gzFile)                   File pointer
+     D  offset                             value like(z_off64_t)                Offset
+     D  whence                       10i 0 value                                Origin
+      /endif
       *
      D gzrewind        PR            10i 0 extproc('gzrewind')
      D  file                               value like(gzFile)                   File pointer
       *
+      /if not defined(LARGE_FILES)
      D gztell          PR                  extproc('gztell')
      D                                     like(z_off_t)
      D  file                               value like(gzFile)                   File pointer
+      /else
+     D gztell          PR                  extproc('gztell64')
+     D                                     like(z_off_t)
+     D  file                               value like(gzFile)                   File pointer
+      *
+     D gztell64        PR                  extproc('gztell64')
+     D                                     like(z_off64_t)
+     D  file                               value like(gzFile)                   File pointer
+      /endif
+      *
+      /if not defined(LARGE_FILES)
+     D gzoffset        PR                  extproc('gzoffset')
+     D                                     like(z_off_t)
+     D  file                               value like(gzFile)                   File pointer
+      /else
+     D gzoffset        PR                  extproc('gzoffset64')
+     D                                     like(z_off_t)
+     D  file                               value like(gzFile)                   File pointer
+      *
+     D gzoffset64      PR                  extproc('gzoffset64')
+     D                                     like(z_off64_t)
+     D  file                               value like(gzFile)                   File pointer
+      /endif
       *
      D gzeof           PR            10i 0 extproc('gzeof')
      D  file                               value like(gzFile)                   File pointer
       *
+     D gzclose_r       PR            10i 0 extproc('gzclose_r')
+     D  file                               value like(gzFile)                   File pointer
+      *
+     D gzclose_w       PR            10i 0 extproc('gzclose_w')
+     D  file                               value like(gzFile)                   File pointer
+      *
      D gzclose         PR            10i 0 extproc('gzclose')
      D  file                               value like(gzFile)                   File pointer
       *
@@ -234,7 +318,7 @@
      D deflateSetDictionary...
      D                 PR            10I 0 extproc('deflateSetDictionary')      Init. dictionary
      D  strm                               like(z_stream)                       Compression stream
-     D  dictionary                32767    const options(*varsize)              Dictionary bytes
+     D  dictionary                65535    const options(*varsize)              Dictionary bytes
      D  dictLength                   10U 0 value                                Dictionary length
       *
      D deflateCopy     PR            10I 0 extproc('deflateCopy')               Compress strm 2 strm
@@ -253,9 +337,14 @@
      D  strm                               like(z_stream)                       Compression stream
      D  sourcelen                    10U 0 value                                Compression level
       *
+     D deflatePending  PR            10I 0 extproc('deflatePending')            Change level & strat
+     D  strm                               like(z_stream)                       Compression stream
+     D  pending                      10U 0                                      Pending bytes
+     D  bits                         10I 0                                      Pending bits
+      *
      D deflatePrime    PR            10I 0 extproc('deflatePrime')              Change level & strat
      D  strm                               like(z_stream)                       Compression stream
-     D  bits                         10I 0 value                                Number of bits to insert
+     D  bits                         10I 0 value                                # of bits to insert
      D  value                        10I 0 value                                Bits to insert
       *
      D inflateInit2    PR            10I 0 extproc('inflateInit2_')             Init. expansion
@@ -267,9 +356,15 @@
      D inflateSetDictionary...
      D                 PR            10I 0 extproc('inflateSetDictionary')      Init. dictionary
      D  strm                               like(z_stream)                       Expansion stream
-     D  dictionary                32767    const options(*varsize)              Dictionary bytes
+     D  dictionary                65535    const options(*varsize)              Dictionary bytes
      D  dictLength                   10U 0 value                                Dictionary length
       *
+     D inflateGetDictionary...
+     D                 PR            10I 0 extproc('inflateGetDictionary')      Get dictionary
+     D  strm                               like(z_stream)                       Expansion stream
+     D  dictionary                65535    options(*varsize)                    Dictionary bytes
+     D  dictLength                   10U 0                                      Dictionary length
+      *
      D inflateSync     PR            10I 0 extproc('inflateSync')               Sync. expansion
      D  strm                               like(z_stream)                       Expansion stream
       *
@@ -280,11 +375,23 @@
      D inflateReset    PR            10I 0 extproc('inflateReset')              End and init. stream
      D  strm                               like(z_stream)                       Expansion stream
       *
+     D inflateReset2   PR            10I 0 extproc('inflateReset2')             End and init. stream
+     D  strm                               like(z_stream)                       Expansion stream
+     D  windowBits                   10I 0 value                                Log2(buffer size)
+      *
+     D inflatePrime    PR            10I 0 extproc('inflatePrime')              Insert bits
+     D  strm                               like(z_stream)                       Expansion stream
+     D  bits                         10I 0 value                                Bit count
+     D  value                        10I 0 value                                Bits to insert
+      *
+     D inflateMark     PR            10I 0 extproc('inflateMark')               Get inflate info
+     D  strm                               like(z_stream)                       Expansion stream
+      *
      D inflateBackInit...
      D                 PR            10I 0 extproc('inflateBackInit_')
      D  strm                               like(z_stream)                       Expansion stream
      D  windowBits                   10I 0 value                                Log2(buffer size)
-     D  window                    32767    options(*varsize)                    Buffer
+     D  window                    65535    options(*varsize)                    Buffer
      D  version                        *   value options(*string)               Version string
      D  stream_size                  10i 0 value                                Stream struct. size
       *
@@ -307,12 +414,12 @@
       *
      D adler32         PR            10U 0 extproc('adler32')                   New checksum
      D  adler                        10U 0 value                                Old checksum
-     D  buf                       32767    const options(*varsize)              Bytes to accumulate
+     D  buf                       65535    const options(*varsize)              Bytes to accumulate
      D  len                          10U 0 value                                Buffer length
       *
      D crc32           PR            10U 0 extproc('crc32')                     New checksum
      D  crc                          10U 0 value                                Old checksum
-     D  buf                       32767    const options(*varsize)              Bytes to accumulate
+     D  buf                       65535    const options(*varsize)              Bytes to accumulate
      D  len                          10U 0 value                                Buffer length
       *
       **************************************************************************
@@ -328,4 +435,17 @@
       *
      D get_crc_table   PR              *   extproc('get_crc_table')             Ptr to ulongs
       *
+     D inflateUndermine...
+     D                 PR            10I 0 extproc('inflateUndermine')
+     D  strm                               like(z_stream)                       Expansion stream
+     D  arg                          10I 0 value                                Error code
+      *
+     D inflateResetKeep...
+     D                 PR            10I 0 extproc('inflateResetKeep')          End and init. stream
+     D  strm                               like(z_stream)                       Expansion stream
+      *
+     D deflateResetKeep...
+     D                 PR            10I 0 extproc('deflateResetKeep')          End and init. stream
+     D  strm                               like(z_stream)                       Expansion stream
+      *
       /endif
diff --git a/third_party/zlib/compress.c b/third_party/zlib/compress.c
index 40a53cd..6e97626 100644
--- a/third_party/zlib/compress.c
+++ b/third_party/zlib/compress.c
@@ -1,11 +1,12 @@
 /* compress.c -- compress a memory buffer
- * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 /* @(#) $Id$ */
 
-#include "zutil.h"
+#define ZLIB_INTERNAL
+#include "zlib.h"
 
 /* ===========================================================================
      Compresses the source buffer into the destination buffer. The level
@@ -28,7 +29,7 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
     z_stream stream;
     int err;
 
-    stream.next_in = source;
+    stream.next_in = (z_const Bytef *)source;
     stream.avail_in = (uInt)sourceLen;
 #ifdef MAXSEG_64K
     /* Check for source > 64K on 16-bit machine: */
@@ -74,5 +75,6 @@ int ZEXPORT compress (dest, destLen, source, sourceLen)
 uLong ZEXPORT compressBound (sourceLen)
     uLong sourceLen;
 {
-    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
+    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+           (sourceLen >> 25) + 13;
 }
diff --git a/third_party/zlib/contrib/README.contrib b/third_party/zlib/contrib/README.contrib
index 20afc62..c66349b 100644
--- a/third_party/zlib/contrib/README.contrib
+++ b/third_party/zlib/contrib/README.contrib
@@ -8,7 +8,10 @@ ada/        by Dmitriy Anisimkov <anisimkov at yahoo.com>
         Support for Ada
         See http://zlib-ada.sourceforge.net/
 
-asm586/
+amd64/      by Mikhail Teterin <mi at ALDAN.algebra.com>
+        asm code for AMD64
+        See patch at http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/96393
+
 asm686/     by Brian Raiter <breadbox at muppetlabs.com>
         asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax
         See http://www.muppetlabs.com/~breadbox/software/assembly.html
@@ -22,6 +25,10 @@ delphi/     by Cosmin Truta <cosmint at cs.ubbcluj.ro>
 dotzlib/    by Henrik Ravn <henrik at ravn.com>
         Support for Microsoft .Net and Visual C++ .Net
 
+gcc_gvmat64/by Gilles Vollant <info at winimage.com>
+        GCC Version of x86 64-bit (AMD64 and Intel EM64t) code for x64
+        assembler to replace longest_match() and inflate_fast()
+
 infback9/   by Mark Adler <madler at alumni.caltech.edu>
         Unsupported diffs to infback to decode the deflate64 format
 
@@ -38,20 +45,19 @@ iostream3/  by Ludwig Schwardt <schwardt at sun.ac.za>
             and Kevin Ruland <kevin at rodin.wustl.edu>
         Yet another C++ I/O streams interface
 
-masm686/    by Dan Higdon <hdan at kinesoft.com>
-            and Chuck Walbourn <chuckw at kinesoft.com>
-        asm code for Pentium Pro/PII, using the MASM syntax
-
 masmx64/    by Gilles Vollant <info at winimage.com>
-	x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to
-	replace longest_match() and inflate_fast()
+        x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to
+        replace longest_match() and inflate_fast(),  also masm x86
+        64-bits translation of Chris Anderson inflate_fast()
 
 masmx86/    by Gilles Vollant <info at winimage.com>
         x86 asm code to replace longest_match() and inflate_fast(),
-        for Visual C++ and MASM
+        for Visual C++ and MASM (32 bits).
+        Based on Brian Raiter (asm686) and Chris Anderson (inflate86)
 
 minizip/    by Gilles Vollant <info at winimage.com>
         Mini zip and unzip based on zlib
+        Includes Zip64 support by Mathias Svensson <mathias at result42.com>
         See http://www.winimage.com/zLibDll/unzip.html
 
 pascal/     by Bob Dellaca <bobdl at xtra.co.nz> et al.
@@ -69,3 +75,4 @@ untgz/      by Pedro A. Aranda Gutierrez <paag at tid.es>
 
 vstudio/    by Gilles Vollant <info at winimage.com>
         Building a minizip-enhanced zlib with Microsoft Visual Studio
+        Includes vc11 from kreuzerkrieg and vc12 from davispuh
diff --git a/third_party/zlib/contrib/ada/zlib-streams.ads b/third_party/zlib/contrib/ada/zlib-streams.ads
index f3352d3..f0193c6 100644
--- a/third_party/zlib/contrib/ada/zlib-streams.ads
+++ b/third_party/zlib/contrib/ada/zlib-streams.ads
@@ -31,7 +31,7 @@ package ZLib.Streams is
       Mode   : in     Flush_Mode := Sync_Flush);
    --  Flush the written data to the back stream,
    --  all data placed to the compressor is flushing to the Back stream.
-   --  Should not be used untill necessary, because it is decreasing
+   --  Should not be used untill necessary, becouse it is decreasing
    --  compression.
 
    function Read_Total_In (Stream : in Stream_Type) return Count;
@@ -97,13 +97,13 @@ private
       Rest_Last  : Stream_Element_Offset;
       --  Buffer for Read operation.
       --  We need to have this buffer in the record
-      --  because not all read data from back stream
+      --  becouse not all read data from back stream
       --  could be processed during the read operation.
 
       Buffer_Size : Stream_Element_Offset;
       --  Buffer size for write operation.
       --  We do not need to have this buffer
-      --  in the record because all data could be
+      --  in the record becouse all data could be
       --  processed in the write operation.
 
       Back       : Stream_Access;
diff --git a/third_party/zlib/contrib/ada/zlib-thin.ads b/third_party/zlib/contrib/ada/zlib-thin.ads
index 810173c..d4407eb 100644
--- a/third_party/zlib/contrib/ada/zlib-thin.ads
+++ b/third_party/zlib/contrib/ada/zlib-thin.ads
@@ -436,7 +436,7 @@ private
 
    pragma Import (C, inflateBackInit, "inflateBackInit_");
 
-   --  I stopped binding the inflateBack routines, because realize that
+   --  I stopped binding the inflateBack routines, becouse realize that
    --  it does not support zlib and gzip headers for now, and have no
    --  symmetric deflateBack routines.
    --  ZLib-Ada is symmetric regarding deflate/inflate data transformation
diff --git a/third_party/zlib/contrib/asm586/README.586 b/third_party/zlib/contrib/asm586/README.586
deleted file mode 100644
index 6bb78f3..0000000
--- a/third_party/zlib/contrib/asm586/README.586
+++ /dev/null
@@ -1,43 +0,0 @@
-This is a patched version of zlib modified to use
-Pentium-optimized assembly code in the deflation algorithm. The files
-changed/added by this patch are:
-
-README.586
-match.S
-
-The effectiveness of these modifications is a bit marginal, as the the
-program's bottleneck seems to be mostly L1-cache contention, for which
-there is no real way to work around without rewriting the basic
-algorithm. The speedup on average is around 5-10% (which is generally
-less than the amount of variance between subsequent executions).
-However, when used at level 9 compression, the cache contention can
-drop enough for the assembly version to achieve 10-20% speedup (and
-sometimes more, depending on the amount of overall redundancy in the
-files). Even here, though, cache contention can still be the limiting
-factor, depending on the nature of the program using the zlib library.
-This may also mean that better improvements will be seen on a Pentium
-with MMX, which suffers much less from L1-cache contention, but I have
-not yet verified this.
-
-Note that this code has been tailored for the Pentium in particular,
-and will not perform well on the Pentium Pro (due to the use of a
-partial register in the inner loop).
-
-If you are using an assembler other than GNU as, you will have to
-translate match.S to use your assembler's syntax. (Have fun.)
-
-Brian Raiter
-breadbox at muppetlabs.com
-April, 1998
-
-
-Added for zlib 1.1.3:
-
-The patches come from
-http://www.muppetlabs.com/~breadbox/software/assembly.html
-
-To compile zlib with this asm file, copy match.S to the zlib directory
-then do:
-
-CFLAGS="-O3 -DASMV" ./configure
-make OBJA=match.o
diff --git a/third_party/zlib/contrib/asm586/match.S b/third_party/zlib/contrib/asm586/match.S
deleted file mode 100644
index 0368b35..0000000
--- a/third_party/zlib/contrib/asm586/match.S
+++ /dev/null
@@ -1,364 +0,0 @@
-/* match.s -- Pentium-optimized version of longest_match()
- * Written for zlib 1.1.2
- * Copyright (C) 1998 Brian Raiter <breadbox at muppetlabs.com>
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License.
- */
-
-#ifndef NO_UNDERLINE
-#define	match_init	_match_init
-#define	longest_match	_longest_match
-#endif
-
-#define	MAX_MATCH	(258)
-#define	MIN_MATCH	(3)
-#define	MIN_LOOKAHEAD	(MAX_MATCH + MIN_MATCH + 1)
-#define	MAX_MATCH_8	((MAX_MATCH + 7) & ~7)
-
-/* stack frame offsets */
-
-#define	wmask			0	/* local copy of s->wmask	*/
-#define	window			4	/* local copy of s->window	*/
-#define	windowbestlen		8	/* s->window + bestlen		*/
-#define	chainlenscanend		12	/* high word: current chain len	*/
-					/* low word: last bytes sought	*/
-#define	scanstart		16	/* first two bytes of string	*/
-#define	scanalign		20	/* dword-misalignment of string	*/
-#define	nicematch		24	/* a good enough match size	*/
-#define	bestlen			28	/* size of best match so far	*/
-#define	scan			32	/* ptr to string wanting match	*/
-
-#define	LocalVarsSize		(36)
-/*	saved ebx		36 */
-/*	saved edi		40 */
-/*	saved esi		44 */
-/*	saved ebp		48 */
-/*	return address		52 */
-#define	deflatestate		56	/* the function arguments	*/
-#define	curmatch		60
-
-/* Offsets for fields in the deflate_state structure. These numbers
- * are calculated from the definition of deflate_state, with the
- * assumption that the compiler will dword-align the fields. (Thus,
- * changing the definition of deflate_state could easily cause this
- * program to crash horribly, without so much as a warning at
- * compile time. Sigh.)
- */
-
-/* All the +zlib1222add offsets are due to the addition of fields
- *  in zlib in the deflate_state structure since the asm code was first written
- * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
- * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
- * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
- */
-
-#define zlib1222add		(8)
-
-#define	dsWSize			(36+zlib1222add)
-#define	dsWMask			(44+zlib1222add)
-#define	dsWindow		(48+zlib1222add)
-#define	dsPrev			(56+zlib1222add)
-#define	dsMatchLen		(88+zlib1222add)
-#define	dsPrevMatch		(92+zlib1222add)
-#define	dsStrStart		(100+zlib1222add)
-#define	dsMatchStart		(104+zlib1222add)
-#define	dsLookahead		(108+zlib1222add)
-#define	dsPrevLen		(112+zlib1222add)
-#define	dsMaxChainLen		(116+zlib1222add)
-#define	dsGoodMatch		(132+zlib1222add)
-#define	dsNiceMatch		(136+zlib1222add)
-
-
-.file "match.S"
-
-.globl	match_init, longest_match
-
-.text
-
-/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
-
-longest_match:
-
-/* Save registers that the compiler may be using, and adjust %esp to	*/
-/* make room for our stack frame.					*/
-
-		pushl	%ebp
-		pushl	%edi
-		pushl	%esi
-		pushl	%ebx
-		subl	$LocalVarsSize, %esp
-
-/* Retrieve the function arguments. %ecx will hold cur_match		*/
-/* throughout the entire function. %edx will hold the pointer to the	*/
-/* deflate_state structure during the function's setup (before		*/
-/* entering the main loop).						*/
-
-		movl	deflatestate(%esp), %edx
-		movl	curmatch(%esp), %ecx
-
-/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;	*/
-
-		movl	dsNiceMatch(%edx), %eax
-		movl	dsLookahead(%edx), %ebx
-		cmpl	%eax, %ebx
-		jl	LookaheadLess
-		movl	%eax, %ebx
-LookaheadLess:	movl	%ebx, nicematch(%esp)
-
-/* register Bytef *scan = s->window + s->strstart;			*/
-
-		movl	dsWindow(%edx), %esi
-		movl	%esi, window(%esp)
-		movl	dsStrStart(%edx), %ebp
-		lea	(%esi,%ebp), %edi
-		movl	%edi, scan(%esp)
-
-/* Determine how many bytes the scan ptr is off from being		*/
-/* dword-aligned.							*/
-
-		movl	%edi, %eax
-		negl	%eax
-		andl	$3, %eax
-		movl	%eax, scanalign(%esp)
-
-/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?			*/
-/*     s->strstart - (IPos)MAX_DIST(s) : NIL;				*/
-
-		movl	dsWSize(%edx), %eax
-		subl	$MIN_LOOKAHEAD, %eax
-		subl	%eax, %ebp
-		jg	LimitPositive
-		xorl	%ebp, %ebp
-LimitPositive:
-
-/* unsigned chain_length = s->max_chain_length;				*/
-/* if (s->prev_length >= s->good_match) {				*/
-/*     chain_length >>= 2;						*/
-/* }									*/
-
-		movl	dsPrevLen(%edx), %eax
-		movl	dsGoodMatch(%edx), %ebx
-		cmpl	%ebx, %eax
-		movl	dsMaxChainLen(%edx), %ebx
-		jl	LastMatchGood
-		shrl	$2, %ebx
-LastMatchGood:
-
-/* chainlen is decremented once beforehand so that the function can	*/
-/* use the sign flag instead of the zero flag for the exit test.	*/
-/* It is then shifted into the high word, to make room for the scanend	*/
-/* scanend value, which it will always accompany.			*/
-
-		decl	%ebx
-		shll	$16, %ebx
-
-/* int best_len = s->prev_length;					*/
-
-		movl	dsPrevLen(%edx), %eax
-		movl	%eax, bestlen(%esp)
-
-/* Store the sum of s->window + best_len in %esi locally, and in %esi.	*/
-
-		addl	%eax, %esi
-		movl	%esi, windowbestlen(%esp)
-
-/* register ush scan_start = *(ushf*)scan;				*/
-/* register ush scan_end   = *(ushf*)(scan+best_len-1);			*/
-
-		movw	(%edi), %bx
-		movw	%bx, scanstart(%esp)
-		movw	-1(%edi,%eax), %bx
-		movl	%ebx, chainlenscanend(%esp)
-
-/* Posf *prev = s->prev;						*/
-/* uInt wmask = s->w_mask;						*/
-
-		movl	dsPrev(%edx), %edi
-		movl	dsWMask(%edx), %edx
-		mov	%edx, wmask(%esp)
-
-/* Jump into the main loop.						*/
-
-		jmp	LoopEntry
-
-.balign 16
-
-/* do {
- *     match = s->window + cur_match;
- *     if (*(ushf*)(match+best_len-1) != scan_end ||
- *         *(ushf*)match != scan_start) continue;
- *     [...]
- * } while ((cur_match = prev[cur_match & wmask]) > limit
- *          && --chain_length != 0);
- *
- * Here is the inner loop of the function. The function will spend the
- * majority of its time in this loop, and majority of that time will
- * be spent in the first ten instructions.
- *
- * Within this loop:
- * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend)
- * %ecx = curmatch
- * %edx = curmatch & wmask
- * %esi = windowbestlen - i.e., (window + bestlen)
- * %edi = prev
- * %ebp = limit
- *
- * Two optimization notes on the choice of instructions:
- *
- * The first instruction uses a 16-bit address, which costs an extra,
- * unpairable cycle. This is cheaper than doing a 32-bit access and
- * zeroing the high word, due to the 3-cycle misalignment penalty which
- * would occur half the time. This also turns out to be cheaper than
- * doing two separate 8-bit accesses, as the memory is so rarely in the
- * L1 cache.
- *
- * The window buffer, however, apparently spends a lot of time in the
- * cache, and so it is faster to retrieve the word at the end of the
- * match string with two 8-bit loads. The instructions that test the
- * word at the beginning of the match string, however, are executed
- * much less frequently, and there it was cheaper to use 16-bit
- * instructions, which avoided the necessity of saving off and
- * subsequently reloading one of the other registers.
- */
-LookupLoop:
-							/* 1 U & V  */
-		movw	(%edi,%edx,2), %cx		/* 2 U pipe */
-		movl	wmask(%esp), %edx		/* 2 V pipe */
-		cmpl	%ebp, %ecx			/* 3 U pipe */
-		jbe	LeaveNow			/* 3 V pipe */
-		subl	$0x00010000, %ebx		/* 4 U pipe */
-		js	LeaveNow			/* 4 V pipe */
-LoopEntry:	movb	-1(%esi,%ecx), %al		/* 5 U pipe */
-		andl	%ecx, %edx			/* 5 V pipe */
-		cmpb	%bl, %al			/* 6 U pipe */
-		jnz	LookupLoop			/* 6 V pipe */
-		movb	(%esi,%ecx), %ah
-		cmpb	%bh, %ah
-		jnz	LookupLoop
-		movl	window(%esp), %eax
-		movw	(%eax,%ecx), %ax
-		cmpw	scanstart(%esp), %ax
-		jnz	LookupLoop
-
-/* Store the current value of chainlen.					*/
-
-		movl	%ebx, chainlenscanend(%esp)
-
-/* Point %edi to the string under scrutiny, and %esi to the string we	*/
-/* are hoping to match it up with. In actuality, %esi and %edi are	*/
-/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is	*/
-/* initialized to -(MAX_MATCH_8 - scanalign).				*/
-
-		movl	window(%esp), %esi
-		movl	scan(%esp), %edi
-		addl	%ecx, %esi
-		movl	scanalign(%esp), %eax
-		movl	$(-MAX_MATCH_8), %edx
-		lea	MAX_MATCH_8(%edi,%eax), %edi
-		lea	MAX_MATCH_8(%esi,%eax), %esi
-
-/* Test the strings for equality, 8 bytes at a time. At the end,
- * adjust %edx so that it is offset to the exact byte that mismatched.
- *
- * We already know at this point that the first three bytes of the
- * strings match each other, and they can be safely passed over before
- * starting the compare loop. So what this code does is skip over 0-3
- * bytes, as much as necessary in order to dword-align the %edi
- * pointer. (%esi will still be misaligned three times out of four.)
- *
- * It should be confessed that this loop usually does not represent
- * much of the total running time. Replacing it with a more
- * straightforward "rep cmpsb" would not drastically degrade
- * performance.
- */
-LoopCmps:
-		movl	(%esi,%edx), %eax
-		movl	(%edi,%edx), %ebx
-		xorl	%ebx, %eax
-		jnz	LeaveLoopCmps
-		movl	4(%esi,%edx), %eax
-		movl	4(%edi,%edx), %ebx
-		xorl	%ebx, %eax
-		jnz	LeaveLoopCmps4
-		addl	$8, %edx
-		jnz	LoopCmps
-		jmp	LenMaximum
-LeaveLoopCmps4:	addl	$4, %edx
-LeaveLoopCmps:	testl	$0x0000FFFF, %eax
-		jnz	LenLower
-		addl	$2, %edx
-		shrl	$16, %eax
-LenLower:	subb	$1, %al
-		adcl	$0, %edx
-
-/* Calculate the length of the match. If it is longer than MAX_MATCH,	*/
-/* then automatically accept it as the best possible match and leave.	*/
-
-		lea	(%edi,%edx), %eax
-		movl	scan(%esp), %edi
-		subl	%edi, %eax
-		cmpl	$MAX_MATCH, %eax
-		jge	LenMaximum
-
-/* If the length of the match is not longer than the best match we	*/
-/* have so far, then forget it and return to the lookup loop.		*/
-
-		movl	deflatestate(%esp), %edx
-		movl	bestlen(%esp), %ebx
-		cmpl	%ebx, %eax
-		jg	LongerMatch
-		movl	chainlenscanend(%esp), %ebx
-		movl	windowbestlen(%esp), %esi
-		movl	dsPrev(%edx), %edi
-		movl	wmask(%esp), %edx
-		andl	%ecx, %edx
-		jmp	LookupLoop
-
-/*         s->match_start = cur_match;					*/
-/*         best_len = len;						*/
-/*         if (len >= nice_match) break;				*/
-/*         scan_end = *(ushf*)(scan+best_len-1);			*/
-
-LongerMatch:	movl	nicematch(%esp), %ebx
-		movl	%eax, bestlen(%esp)
-		movl	%ecx, dsMatchStart(%edx)
-		cmpl	%ebx, %eax
-		jge	LeaveNow
-		movl	window(%esp), %esi
-		addl	%eax, %esi
-		movl	%esi, windowbestlen(%esp)
-		movl	chainlenscanend(%esp), %ebx
-		movw	-1(%edi,%eax), %bx
-		movl	dsPrev(%edx), %edi
-		movl	%ebx, chainlenscanend(%esp)
-		movl	wmask(%esp), %edx
-		andl	%ecx, %edx
-		jmp	LookupLoop
-
-/* Accept the current string, with the maximum possible length.		*/
-
-LenMaximum:	movl	deflatestate(%esp), %edx
-		movl	$MAX_MATCH, bestlen(%esp)
-		movl	%ecx, dsMatchStart(%edx)
-
-/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;		*/
-/* return s->lookahead;							*/
-
-LeaveNow:
-		movl	deflatestate(%esp), %edx
-		movl	bestlen(%esp), %ebx
-		movl	dsLookahead(%edx), %eax
-		cmpl	%eax, %ebx
-		jg	LookaheadRet
-		movl	%ebx, %eax
-LookaheadRet:
-
-/* Restore the stack and return from whence we came.			*/
-
-		addl	$LocalVarsSize, %esp
-		popl	%ebx
-		popl	%esi
-		popl	%edi
-		popl	%ebp
-match_init:	ret
diff --git a/third_party/zlib/contrib/asm686/README.686 b/third_party/zlib/contrib/asm686/README.686
index a593f23..a0bf3be 100644
--- a/third_party/zlib/contrib/asm686/README.686
+++ b/third_party/zlib/contrib/asm686/README.686
@@ -32,3 +32,20 @@ then do:
 
 CFLAGS="-O3 -DASMV" ./configure
 make OBJA=match.o
+
+
+Update:
+
+I've been ignoring these assembly routines for years, believing that
+gcc's generated code had caught up with it sometime around gcc 2.95
+and the major rearchitecting of the Pentium 4. However, I recently
+learned that, despite what I believed, this code still has some life
+in it. On the Pentium 4 and AMD64 chips, it continues to run about 8%
+faster than the code produced by gcc 4.1.
+
+In acknowledgement of its continuing usefulness, I've altered the
+license to match that of the rest of zlib. Share and Enjoy!
+
+Brian Raiter
+breadbox at muppetlabs.com
+April, 2007
diff --git a/third_party/zlib/contrib/asm686/match.S b/third_party/zlib/contrib/asm686/match.S
index 5c3e9ee..fa42109 100644
--- a/third_party/zlib/contrib/asm686/match.S
+++ b/third_party/zlib/contrib/asm686/match.S
@@ -1,9 +1,23 @@
-/* match.s -- Pentium-Pro-optimized version of longest_match()
- * Written for zlib 1.1.2
- * Copyright (C) 1998 Brian Raiter <breadbox at muppetlabs.com>
+/* match.S -- x86 assembly version of the zlib longest_match() function.
+ * Optimized for the Intel 686 chips (PPro and later).
  *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License.
+ * Copyright (C) 1998, 2007 Brian Raiter <breadbox at muppetlabs.com>
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the author be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
  */
 
 #ifndef NO_UNDERLINE
@@ -69,17 +83,25 @@
 .text
 
 /* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
+.cfi_sections	.debug_frame
 
 longest_match:
 
+.cfi_startproc
 /* Save registers that the compiler may be using, and adjust %esp to	*/
 /* make room for our stack frame.					*/
 
 		pushl	%ebp
+		.cfi_def_cfa_offset 8
+		.cfi_offset ebp, -8
 		pushl	%edi
+		.cfi_def_cfa_offset 12
 		pushl	%esi
+		.cfi_def_cfa_offset 16
 		pushl	%ebx
+		.cfi_def_cfa_offset 20
 		subl	$LocalVarsSize, %esp
+		.cfi_def_cfa_offset LocalVarsSize+20
 
 /* Retrieve the function arguments. %ecx will hold cur_match		*/
 /* throughout the entire function. %edx will hold the pointer to the	*/
@@ -94,7 +116,7 @@ longest_match:
 /* if (s->prev_length >= s->good_match) {				*/
 /*     chain_length >>= 2;						*/
 /* }									*/
-
+ 
 		movl	dsPrevLen(%edx), %eax
 		movl	dsGoodMatch(%edx), %ebx
 		cmpl	%ebx, %eax
@@ -322,8 +344,14 @@ LookaheadRet:
 /* Restore the stack and return from whence we came.			*/
 
 		addl	$LocalVarsSize, %esp
+		.cfi_def_cfa_offset 20
 		popl	%ebx
+		.cfi_def_cfa_offset 16
 		popl	%esi
+		.cfi_def_cfa_offset 12
 		popl	%edi
+		.cfi_def_cfa_offset 8
 		popl	%ebp
+		.cfi_def_cfa_offset 4
+.cfi_endproc
 match_init:	ret
diff --git a/third_party/zlib/contrib/blast/blast.c b/third_party/zlib/contrib/blast/blast.c
index 4ce697a..69ef0fe 100644
--- a/third_party/zlib/contrib/blast/blast.c
+++ b/third_party/zlib/contrib/blast/blast.c
@@ -1,7 +1,7 @@
 /* blast.c
- * Copyright (C) 2003 Mark Adler
+ * Copyright (C) 2003, 2012 Mark Adler
  * For conditions of distribution and use, see copyright notice in blast.h
- * version 1.1, 16 Feb 2003
+ * version 1.2, 24 Oct 2012
  *
  * blast.c decompresses data compressed by the PKWare Compression Library.
  * This function provides functionality similar to the explode() function of
@@ -22,6 +22,8 @@
  *
  * 1.0  12 Feb 2003     - First version
  * 1.1  16 Feb 2003     - Fixed distance check for > 4 GB uncompressed data
+ * 1.2  24 Oct 2012     - Add note about using binary mode in stdio
+ *                      - Fix comparisons of differently signed integers
  */
 
 #include <setjmp.h>             /* for setjmp(), longjmp(), and jmp_buf */
@@ -279,7 +281,7 @@ local int decomp(struct state *s)
     int dict;           /* log2(dictionary size) - 6 */
     int symbol;         /* decoded symbol, extra bits for distance */
     int len;            /* length for copy */
-    int dist;           /* distance for copy */
+    unsigned dist;      /* distance for copy */
     int copy;           /* copy counter */
     unsigned char *from, *to;   /* copy pointers */
     static int virgin = 1;                              /* build tables once */
diff --git a/third_party/zlib/contrib/blast/blast.h b/third_party/zlib/contrib/blast/blast.h
index ce9e541..658cfd3 100644
--- a/third_party/zlib/contrib/blast/blast.h
+++ b/third_party/zlib/contrib/blast/blast.h
@@ -1,6 +1,6 @@
 /* blast.h -- interface for blast.c
-  Copyright (C) 2003 Mark Adler
-  version 1.1, 16 Feb 2003
+  Copyright (C) 2003, 2012 Mark Adler
+  version 1.2, 24 Oct 2012
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the author be held liable for any damages
@@ -28,6 +28,10 @@
  * that library.  (Note: PKWare overused the "implode" verb, and the format
  * used by their library implode() function is completely different and
  * incompatible with the implode compression method supported by PKZIP.)
+ *
+ * The binary mode for stdio functions should be used to assure that the
+ * compressed data is not corrupted when read or written.  For example:
+ * fopen(..., "rb") and fopen(..., "wb").
  */
 
 
diff --git a/third_party/zlib/contrib/delphi/ZLib.pas b/third_party/zlib/contrib/delphi/ZLib.pas
index 3f2b8b4..a579974 100644
--- a/third_party/zlib/contrib/delphi/ZLib.pas
+++ b/third_party/zlib/contrib/delphi/ZLib.pas
@@ -152,7 +152,7 @@ procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
   const OutBuf: Pointer; BufSize: Integer);
 
 const
-  zlib_version = '1.2.3';
+  zlib_version = '1.2.8';
 
 type
   EZlibError = class(Exception);
diff --git a/third_party/zlib/contrib/delphi/zlibd32.mak b/third_party/zlib/contrib/delphi/zlibd32.mak
index 88fafa0..9bb00b7 100644
--- a/third_party/zlib/contrib/delphi/zlibd32.mak
+++ b/third_party/zlib/contrib/delphi/zlibd32.mak
@@ -18,10 +18,10 @@ LDFLAGS =
 # variables
 ZLIB_LIB = zlib.lib
 
-OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
-OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
-OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
-OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj
+OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj
+OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
 
 
 # targets
@@ -38,7 +38,13 @@ crc32.obj: crc32.c zlib.h zconf.h crc32.h
 
 deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
 
-gzio.obj: gzio.c zutil.h zlib.h zconf.h
+gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h
+
+gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h
+
+gzread.obj: gzread.c zlib.h zconf.h gzguts.h
+
+gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h
 
 infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
  inffast.h inffixed.h
@@ -57,9 +63,9 @@ uncompr.obj: uncompr.c zlib.h zconf.h
 
 zutil.obj: zutil.c zutil.h zlib.h zconf.h
 
-example.obj: example.c zlib.h zconf.h
+example.obj: test/example.c zlib.h zconf.h
 
-minigzip.obj: minigzip.c zlib.h zconf.h
+minigzip.obj: test/minigzip.c zlib.h zconf.h
 
 
 # For the sake of the old Borland make,
diff --git a/third_party/zlib/contrib/dotzlib/DotZLib.build b/third_party/zlib/contrib/dotzlib/DotZLib.build
index ed19cc9..7f90d6b 100644
--- a/third_party/zlib/contrib/dotzlib/DotZLib.build
+++ b/third_party/zlib/contrib/dotzlib/DotZLib.build
@@ -4,7 +4,7 @@
 
 	<property name="nunit.location" value="c:/program files/NUnit V2.1/bin" />
 	<property name="build.root" value="bin" />
-	
+
 	<property name="debug" value="true" />
 	<property name="nunit" value="true" />
 
@@ -16,7 +16,7 @@
 	</target>
 
 	<target name="build" description="compiles the source code">
-		
+
 		<mkdir dir="${build.folder}" />
 		<csc target="library" output="${build.folder}DotZLib.dll" debug="${debug}">
 			<references basedir="${nunit.location}">
diff --git a/third_party/zlib/contrib/dotzlib/DotZLib.chm b/third_party/zlib/contrib/dotzlib/DotZLib.chm
index 0bc7df76e407dcc69094483a6e9507240fe257ab..f214a444aebb20950fb3e8499b36731e1f12be95 100644
GIT binary patch
delta 20
ccmbQSgJs$dmJRNyn>|vc=Wb77V%#DL09=R&1^@s6

delta 24
gcmbQXgJs4JmJRNyjGUX at Q>EuJa&AvzV%#DL0C9W>7XSbN

diff --git a/third_party/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs b/third_party/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs
index 6fc0fdc..0491bfc 100644
--- a/third_party/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs
+++ b/third_party/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs
@@ -2,7 +2,7 @@ using System.Reflection;
 using System.Runtime.CompilerServices;
 
 //
-// General Information about an assembly is controlled through the following 
+// General Information about an assembly is controlled through the following
 // set of attributes. Change these attribute values to modify the information
 // associated with an assembly.
 //
@@ -13,42 +13,42 @@ using System.Runtime.CompilerServices;
 [assembly: AssemblyProduct("")]
 [assembly: AssemblyCopyright("(c) 2004 by Henrik Ravn")]
 [assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]		
+[assembly: AssemblyCulture("")]
 
 //
 // Version information for an assembly consists of the following four values:
 //
 //      Major Version
-//      Minor Version 
+//      Minor Version
 //      Build Number
 //      Revision
 //
-// You can specify all the values or you can default the Revision and Build Numbers 
+// You can specify all the values or you can default the Revision and Build Numbers
 // by using the '*' as shown below:
 
 [assembly: AssemblyVersion("1.0.*")]
 
 //
-// In order to sign your assembly you must specify a key to use. Refer to the 
+// In order to sign your assembly you must specify a key to use. Refer to the
 // Microsoft .NET Framework documentation for more information on assembly signing.
 //
-// Use the attributes below to control which key is used for signing. 
+// Use the attributes below to control which key is used for signing.
 //
-// Notes: 
+// Notes:
 //   (*) If no key is specified, the assembly is not signed.
 //   (*) KeyName refers to a key that has been installed in the Crypto Service
 //       Provider (CSP) on your machine. KeyFile refers to a file which contains
 //       a key.
-//   (*) If the KeyFile and the KeyName values are both specified, the 
+//   (*) If the KeyFile and the KeyName values are both specified, the
 //       following processing occurs:
 //       (1) If the KeyName can be found in the CSP, that key is used.
-//       (2) If the KeyName does not exist and the KeyFile does exist, the key 
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key
 //           in the KeyFile is installed into the CSP and used.
 //   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
 //       When specifying the KeyFile, the location of the KeyFile should be
 //       relative to the project output directory which is
 //       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
-//       located in the project directory, you would specify the AssemblyKeyFile 
+//       located in the project directory, you would specify the AssemblyKeyFile
 //       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
 //   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
 //       documentation for more information on this.
diff --git a/third_party/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs b/third_party/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs
index dfe7e90..788b2fc 100644
--- a/third_party/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs
+++ b/third_party/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs
@@ -1,7 +1,7 @@
 //
 // © Copyright Henrik Ravn 2004
 //
-// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
@@ -25,7 +25,7 @@ namespace DotZLib
         protected uint _current;
 
         /// <summary>
-        /// Initializes a new instance of the checksum generator base - the current checksum is 
+        /// Initializes a new instance of the checksum generator base - the current checksum is
         /// set to zero
         /// </summary>
         public ChecksumGeneratorBase()
@@ -61,7 +61,7 @@ namespace DotZLib
         /// <exception cref="ArgumentException">The sum of offset and count is larger than the length of <c>data</c></exception>
         /// <exception cref="NullReferenceException"><c>data</c> is a null reference</exception>
         /// <exception cref="ArgumentOutOfRangeException">Offset or count is negative.</exception>
-        /// <remarks>All the other <c>Update</c> methods are implmeneted in terms of this one. 
+        /// <remarks>All the other <c>Update</c> methods are implmeneted in terms of this one.
         /// This is therefore the only method a derived class has to implement</remarks>
         public abstract void Update(byte[] data, int offset, int count);
 
@@ -101,7 +101,7 @@ namespace DotZLib
     /// <summary>
     /// Implements a CRC32 checksum generator
     /// </summary>
-    public sealed class CRC32Checksum : ChecksumGeneratorBase    
+    public sealed class CRC32Checksum : ChecksumGeneratorBase
     {
         #region DLL imports
 
@@ -152,7 +152,7 @@ namespace DotZLib
     /// <summary>
     /// Implements a checksum generator that computes the Adler checksum on data
     /// </summary>
-    public sealed class AdlerChecksum : ChecksumGeneratorBase    
+    public sealed class AdlerChecksum : ChecksumGeneratorBase
     {
         #region DLL imports
 
diff --git a/third_party/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs b/third_party/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs
index 16997e9..c1cab3a 100644
--- a/third_party/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs
+++ b/third_party/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs
@@ -1,7 +1,7 @@
 //
 // © Copyright Henrik Ravn 2004
 //
-// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
@@ -25,7 +25,7 @@ namespace DotZLib
         #endregion
 
         public CircularBuffer(int capacity)
-        {    
+        {
             Debug.Assert( capacity > 0 );
             _buffer = new byte[capacity];
             _capacity = capacity;
diff --git a/third_party/zlib/contrib/dotzlib/DotZLib/CodecBase.cs b/third_party/zlib/contrib/dotzlib/DotZLib/CodecBase.cs
index 954db7d..42e6da3 100644
--- a/third_party/zlib/contrib/dotzlib/DotZLib/CodecBase.cs
+++ b/third_party/zlib/contrib/dotzlib/DotZLib/CodecBase.cs
@@ -1,7 +1,7 @@
 //
 // © Copyright Henrik Ravn 2004
 //
-// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
@@ -19,7 +19,7 @@ namespace DotZLib
         #region Data members
 
         /// <summary>
-        /// Instance of the internal zlib buffer structure that is 
+        /// Instance of the internal zlib buffer structure that is
         /// passed to all functions in the zlib dll
         /// </summary>
         internal ZStream _ztream = new ZStream();
@@ -45,7 +45,7 @@ namespace DotZLib
         #endregion
 
         /// <summary>
-        /// Initializes a new instance of the <c>CodeBase</c> class. 
+        /// Initializes a new instance of the <c>CodeBase</c> class.
         /// </summary>
 		public CodecBase()
 		{
@@ -77,7 +77,7 @@ namespace DotZLib
             if (_ztream.total_out > 0)
             {
                 if (DataAvailable != null)
-                    DataAvailable( _outBuffer, 0, (int)_ztream.total_out); 
+                    DataAvailable( _outBuffer, 0, (int)_ztream.total_out);
                 resetOutput();
             }
         }
diff --git a/third_party/zlib/contrib/dotzlib/DotZLib/Deflater.cs b/third_party/zlib/contrib/dotzlib/DotZLib/Deflater.cs
index d7b8dcc..c247792 100644
--- a/third_party/zlib/contrib/dotzlib/DotZLib/Deflater.cs
+++ b/third_party/zlib/contrib/dotzlib/DotZLib/Deflater.cs
@@ -1,7 +1,7 @@
 //
 // © Copyright Henrik Ravn 2004
 //
-// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
@@ -56,7 +56,7 @@ namespace DotZLib
             if (data == null) throw new ArgumentNullException();
             if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
             if ((offset+count) > data.Length) throw new ArgumentException();
-            
+
             int total = count;
             int inputIndex = offset;
             int err = 0;
@@ -86,7 +86,7 @@ namespace DotZLib
         public override void Finish()
         {
             int err;
-            do 
+            do
             {
                 err = deflate(ref _ztream, (int)FlushTypes.Finish);
                 OnDataAvailable();
diff --git a/third_party/zlib/contrib/dotzlib/DotZLib/DotZLib.cs b/third_party/zlib/contrib/dotzlib/DotZLib/DotZLib.cs
index 410deb0..be184b4 100644
--- a/third_party/zlib/contrib/dotzlib/DotZLib/DotZLib.cs
+++ b/third_party/zlib/contrib/dotzlib/DotZLib/DotZLib.cs
@@ -1,7 +1,7 @@
 //
 // © Copyright Henrik Ravn 2004
 //
-// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
@@ -19,7 +19,7 @@ namespace DotZLib
     /// <summary>
     /// Defines constants for the various flush types used with zlib
     /// </summary>
-    internal enum FlushTypes 
+    internal enum FlushTypes
     {
         None,  Partial,  Sync,  Full,  Finish,  Block
     }
@@ -38,7 +38,7 @@ namespace DotZLib
         public uint total_out;
 
         [MarshalAs(UnmanagedType.LPStr)]
-        string msg; 
+        string msg;
         uint state;
 
         uint zalloc;
@@ -51,7 +51,7 @@ namespace DotZLib
     }
 
     #endregion
-    
+
     #endregion
 
     #region Public enums
@@ -63,7 +63,7 @@ namespace DotZLib
         /// <summary>
         /// The default compression level with a reasonable compromise between compression and speed
         /// </summary>
-        Default = -1,   
+        Default = -1,
         /// <summary>
         /// No compression at all. The data are passed straight through.
         /// </summary>
@@ -71,7 +71,7 @@ namespace DotZLib
         /// <summary>
         /// The maximum compression rate available.
         /// </summary>
-        Best = 9,   
+        Best = 9,
         /// <summary>
         /// The fastest available compression level.
         /// </summary>
@@ -86,7 +86,7 @@ namespace DotZLib
     public class ZLibException : ApplicationException
     {
         /// <summary>
-        /// Initializes a new instance of the <see cref="ZLibException"/> class with a specified 
+        /// Initializes a new instance of the <see cref="ZLibException"/> class with a specified
         /// error message and error code
         /// </summary>
         /// <param name="errorCode">The zlib error code that caused the exception</param>
@@ -96,7 +96,7 @@ namespace DotZLib
         }
 
         /// <summary>
-        /// Initializes a new instance of the <see cref="ZLibException"/> class with a specified 
+        /// Initializes a new instance of the <see cref="ZLibException"/> class with a specified
         /// error code
         /// </summary>
         /// <param name="errorCode">The zlib error code that caused the exception</param>
@@ -109,7 +109,7 @@ namespace DotZLib
     #region Interfaces
 
     /// <summary>
-    /// Declares methods and properties that enables a running checksum to be calculated 
+    /// Declares methods and properties that enables a running checksum to be calculated
     /// </summary>
     public interface ChecksumGenerator
     {
@@ -163,7 +163,7 @@ namespace DotZLib
     /// <paramref name="data">The byte array containing the processed data</paramref>
     /// <paramref name="startIndex">The index of the first processed byte in <c>data</c></paramref>
     /// <paramref name="count">The number of processed bytes available</paramref>
-    /// <remarks>On return from this method, the data may be overwritten, so grab it while you can. 
+    /// <remarks>On return from this method, the data may be overwritten, so grab it while you can.
     /// You cannot assume that startIndex will be zero.
     /// </remarks>
     public delegate void DataAvailableHandler(byte[] data, int startIndex, int count);
diff --git a/third_party/zlib/contrib/dotzlib/DotZLib/GZipStream.cs b/third_party/zlib/contrib/dotzlib/DotZLib/GZipStream.cs
index f861675..b161300 100644
--- a/third_party/zlib/contrib/dotzlib/DotZLib/GZipStream.cs
+++ b/third_party/zlib/contrib/dotzlib/DotZLib/GZipStream.cs
@@ -1,7 +1,7 @@
 //
 // © Copyright Henrik Ravn 2004
 //
-// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
@@ -84,7 +84,7 @@ namespace DotZLib
                 return !_isWriting;
             }
         }
-    
+
 
         /// <summary>
         /// Returns false.
@@ -96,7 +96,7 @@ namespace DotZLib
                 return false;
             }
         }
-    
+
         /// <summary>
         /// Returns true if this tsream is writeable, false otherwise
         /// </summary>
@@ -108,7 +108,7 @@ namespace DotZLib
             }
         }
         #endregion
-    
+
         #region Destructor & IDispose stuff
 
         /// <summary>
@@ -137,7 +137,7 @@ namespace DotZLib
             }
         }
         #endregion
-    
+
         #region Basic reading and writing
         /// <summary>
         /// Attempts to read a number of bytes from the stream.
@@ -244,7 +244,7 @@ namespace DotZLib
         {
             throw new NotSupportedException();
         }
-    
+
         /// <summary>
         ///  Not suppported.
         /// </summary>
@@ -256,7 +256,7 @@ namespace DotZLib
         {
             throw new NotSupportedException();
         }
-    
+
         /// <summary>
         /// Flushes the <c>GZipStream</c>.
         /// </summary>
@@ -266,7 +266,7 @@ namespace DotZLib
         {
             // left empty on purpose
         }
-    
+
         /// <summary>
         /// Gets/sets the current position in the <c>GZipStream</c>. Not suppported.
         /// </summary>
@@ -283,7 +283,7 @@ namespace DotZLib
                 throw new NotSupportedException();
             }
         }
-    
+
         /// <summary>
         /// Gets the size of the stream. Not suppported.
         /// </summary>
diff --git a/third_party/zlib/contrib/dotzlib/DotZLib/Inflater.cs b/third_party/zlib/contrib/dotzlib/DotZLib/Inflater.cs
index 4e60cda..8ed5451 100644
--- a/third_party/zlib/contrib/dotzlib/DotZLib/Inflater.cs
+++ b/third_party/zlib/contrib/dotzlib/DotZLib/Inflater.cs
@@ -1,7 +1,7 @@
 //
 // © Copyright Henrik Ravn 2004
 //
-// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
@@ -11,7 +11,7 @@ using System.Runtime.InteropServices;
 
 namespace DotZLib
 {
-    
+
     /// <summary>
     /// Implements a data decompressor, using the inflate algorithm in the ZLib dll
     /// </summary>
@@ -84,7 +84,7 @@ namespace DotZLib
         public override void Finish()
         {
             int err;
-            do 
+            do
             {
                 err = inflate(ref _ztream, (int)FlushTypes.Finish);
                 OnDataAvailable();
diff --git a/third_party/zlib/contrib/dotzlib/DotZLib/UnitTests.cs b/third_party/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
index 8dc00db..b273d54 100644
--- a/third_party/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
+++ b/third_party/zlib/contrib/dotzlib/DotZLib/UnitTests.cs
@@ -1,7 +1,7 @@
 //
-// © Copyright Henrik Ravn 2004
+// © Copyright Henrik Ravn 2004
 //
-// Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+// Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
@@ -156,7 +156,7 @@ namespace DotZLibTests
         public void Info_Version()
         {
             Info info = new Info();
-            Assert.AreEqual("1.2.3", Info.Version);
+            Assert.AreEqual("1.2.8", Info.Version);
             Assert.AreEqual(32, info.SizeOfUInt);
             Assert.AreEqual(32, info.SizeOfULong);
             Assert.AreEqual(32, info.SizeOfPointer);
@@ -225,7 +225,7 @@ namespace DotZLibTests
 
         [Test]
         public void Inflate_Expand()
-        { 
+        {
             uncompressedData.Clear();
 
             using (Inflater inf = new Inflater())
@@ -271,4 +271,4 @@ namespace DotZLibTests
 	}
 }
 
-#endif
\ No newline at end of file
+#endif
diff --git a/third_party/zlib/contrib/dotzlib/readme.txt b/third_party/zlib/contrib/dotzlib/readme.txt
index 210f4b0..b239572 100644
--- a/third_party/zlib/contrib/dotzlib/readme.txt
+++ b/third_party/zlib/contrib/dotzlib/readme.txt
@@ -1,6 +1,6 @@
 This directory contains a .Net wrapper class library for the ZLib1.dll
 
-The wrapper includes support for inflating/deflating memory buffers, 
+The wrapper includes support for inflating/deflating memory buffers,
 .Net streaming wrappers for the gz streams part of zlib, and wrappers
 for the checksum parts of zlib. See DotZLib/UnitTests.cs for examples.
 
@@ -26,11 +26,11 @@ Build instructions:
 
 1. Using Visual Studio.Net 2003:
    Open DotZLib.sln in VS.Net and build from there. Output file (DotZLib.dll)
-   will be found ./DotZLib/bin/release or ./DotZLib/bin/debug, depending on 
-   you are building the release or debug version of the library. Check 
+   will be found ./DotZLib/bin/release or ./DotZLib/bin/debug, depending on
+   you are building the release or debug version of the library. Check
    DotZLib/UnitTests.cs for instructions on how to include unit tests in the
    build.
-   
+
 2. Using NAnt:
    Open a command prompt with access to the build environment and run nant
    in the same directory as the DotZLib.build file.
@@ -38,15 +38,15 @@ Build instructions:
    debug={true|false} to toggle between release/debug builds (default=true).
    nunit={true|false} to include or esclude unit tests (default=true).
    Also the target clean will remove binaries.
-   Output file (DotZLib.dll) will be found in either ./DotZLib/bin/release 
-   or ./DotZLib/bin/debug, depending on whether you are building the release 
+   Output file (DotZLib.dll) will be found in either ./DotZLib/bin/release
+   or ./DotZLib/bin/debug, depending on whether you are building the release
    or debug version of the library.
 
-   Examples: 
+   Examples:
      nant -D:debug=false -D:nunit=false
        will build a release mode version of the library without unit tests.
      nant
-       will build a debug version of the library with unit tests 
+       will build a debug version of the library with unit tests
      nant clean
        will remove all previously built files.
 
@@ -54,5 +54,5 @@ Build instructions:
 ---------------------------------
 Copyright (c) Henrik Ravn 2004
 
-Use, modification and distribution are subject to the Boost Software License, Version 1.0. 
+Use, modification and distribution are subject to the Boost Software License, Version 1.0.
 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
diff --git a/third_party/zlib/contrib/infback9/infback9.c b/third_party/zlib/contrib/infback9/infback9.c
index f5ddde6..05fb3e3 100644
--- a/third_party/zlib/contrib/infback9/infback9.c
+++ b/third_party/zlib/contrib/infback9/infback9.c
@@ -1,5 +1,5 @@
 /* infback9.c -- inflate deflate64 data using a call-back interface
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2008 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -222,14 +222,13 @@ out_func out;
 void FAR *out_desc;
 {
     struct inflate_state FAR *state;
-    unsigned char FAR *next;    /* next input */
+    z_const unsigned char FAR *next;    /* next input */
     unsigned char FAR *put;     /* next output */
     unsigned have;              /* available input */
     unsigned long left;         /* available output */
     inflate_mode mode;          /* current inflate mode */
     int lastblock;              /* true if processing last block */
     int wrap;                   /* true if the window has wrapped */
-    unsigned long write;        /* window write index */
     unsigned char FAR *window;  /* allocated sliding window, if needed */
     unsigned long hold;         /* bit buffer */
     unsigned bits;              /* bits in bit buffer */
@@ -242,7 +241,7 @@ void FAR *out_desc;
     code const FAR *distcode;   /* starting table for distance codes */
     unsigned lenbits;           /* index bits for lencode */
     unsigned distbits;          /* index bits for distcode */
-    code this;                  /* current decoding table entry */
+    code here;                  /* current decoding table entry */
     code last;                  /* parent table entry */
     unsigned len;               /* length to copy for repeats, bits to drop */
     int ret;                    /* return code */
@@ -259,7 +258,6 @@ void FAR *out_desc;
     strm->msg = Z_NULL;
     mode = TYPE;
     lastblock = 0;
-    write = 0;
     wrap = 0;
     window = state->window;
     next = strm->next_in;
@@ -384,19 +382,19 @@ void FAR *out_desc;
             state->have = 0;
             while (state->have < state->nlen + state->ndist) {
                 for (;;) {
-                    this = lencode[BITS(lenbits)];
-                    if ((unsigned)(this.bits) <= bits) break;
+                    here = lencode[BITS(lenbits)];
+                    if ((unsigned)(here.bits) <= bits) break;
                     PULLBYTE();
                 }
-                if (this.val < 16) {
-                    NEEDBITS(this.bits);
-                    DROPBITS(this.bits);
-                    state->lens[state->have++] = this.val;
+                if (here.val < 16) {
+                    NEEDBITS(here.bits);
+                    DROPBITS(here.bits);
+                    state->lens[state->have++] = here.val;
                 }
                 else {
-                    if (this.val == 16) {
-                        NEEDBITS(this.bits + 2);
-                        DROPBITS(this.bits);
+                    if (here.val == 16) {
+                        NEEDBITS(here.bits + 2);
+                        DROPBITS(here.bits);
                         if (state->have == 0) {
                             strm->msg = (char *)"invalid bit length repeat";
                             mode = BAD;
@@ -406,16 +404,16 @@ void FAR *out_desc;
                         copy = 3 + BITS(2);
                         DROPBITS(2);
                     }
-                    else if (this.val == 17) {
-                        NEEDBITS(this.bits + 3);
-                        DROPBITS(this.bits);
+                    else if (here.val == 17) {
+                        NEEDBITS(here.bits + 3);
+                        DROPBITS(here.bits);
                         len = 0;
                         copy = 3 + BITS(3);
                         DROPBITS(3);
                     }
                     else {
-                        NEEDBITS(this.bits + 7);
-                        DROPBITS(this.bits);
+                        NEEDBITS(here.bits + 7);
+                        DROPBITS(here.bits);
                         len = 0;
                         copy = 11 + BITS(7);
                         DROPBITS(7);
@@ -433,7 +431,16 @@ void FAR *out_desc;
             /* handle error breaks in while */
             if (mode == BAD) break;
 
-            /* build code tables */
+            /* check for end-of-block code (better have one) */
+            if (state->lens[256] == 0) {
+                strm->msg = (char *)"invalid code -- missing end-of-block";
+                mode = BAD;
+                break;
+            }
+
+            /* build code tables -- note: do not change the lenbits or distbits
+               values here (9 and 6) without reading the comments in inftree9.h
+               concerning the ENOUGH constants, which depend on those values */
             state->next = state->codes;
             lencode = (code const FAR *)(state->next);
             lenbits = 9;
@@ -460,28 +467,28 @@ void FAR *out_desc;
         case LEN:
             /* get a literal, length, or end-of-block code */
             for (;;) {
-                this = lencode[BITS(lenbits)];
-                if ((unsigned)(this.bits) <= bits) break;
+                here = lencode[BITS(lenbits)];
+                if ((unsigned)(here.bits) <= bits) break;
                 PULLBYTE();
             }
-            if (this.op && (this.op & 0xf0) == 0) {
-                last = this;
+            if (here.op && (here.op & 0xf0) == 0) {
+                last = here;
                 for (;;) {
-                    this = lencode[last.val +
+                    here = lencode[last.val +
                             (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
                     PULLBYTE();
                 }
                 DROPBITS(last.bits);
             }
-            DROPBITS(this.bits);
-            length = (unsigned)this.val;
+            DROPBITS(here.bits);
+            length = (unsigned)here.val;
 
             /* process literal */
-            if (this.op == 0) {
-                Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+            if (here.op == 0) {
+                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
                         "inflate:         literal '%c'\n" :
-                        "inflate:         literal 0x%02x\n", this.val));
+                        "inflate:         literal 0x%02x\n", here.val));
                 ROOM();
                 *put++ = (unsigned char)(length);
                 left--;
@@ -490,21 +497,21 @@ void FAR *out_desc;
             }
 
             /* process end of block */
-            if (this.op & 32) {
+            if (here.op & 32) {
                 Tracevv((stderr, "inflate:         end of block\n"));
                 mode = TYPE;
                 break;
             }
 
             /* invalid code */
-            if (this.op & 64) {
+            if (here.op & 64) {
                 strm->msg = (char *)"invalid literal/length code";
                 mode = BAD;
                 break;
             }
 
             /* length code -- get extra bits, if any */
-            extra = (unsigned)(this.op) & 31;
+            extra = (unsigned)(here.op) & 31;
             if (extra != 0) {
                 NEEDBITS(extra);
                 length += BITS(extra);
@@ -514,30 +521,30 @@ void FAR *out_desc;
 
             /* get distance code */
             for (;;) {
-                this = distcode[BITS(distbits)];
-                if ((unsigned)(this.bits) <= bits) break;
+                here = distcode[BITS(distbits)];
+                if ((unsigned)(here.bits) <= bits) break;
                 PULLBYTE();
             }
-            if ((this.op & 0xf0) == 0) {
-                last = this;
+            if ((here.op & 0xf0) == 0) {
+                last = here;
                 for (;;) {
-                    this = distcode[last.val +
+                    here = distcode[last.val +
                             (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
                     PULLBYTE();
                 }
                 DROPBITS(last.bits);
             }
-            DROPBITS(this.bits);
-            if (this.op & 64) {
+            DROPBITS(here.bits);
+            if (here.op & 64) {
                 strm->msg = (char *)"invalid distance code";
                 mode = BAD;
                 break;
             }
-            offset = (unsigned)this.val;
+            offset = (unsigned)here.val;
 
             /* get distance extra bits, if any */
-            extra = (unsigned)(this.op) & 15;
+            extra = (unsigned)(here.op) & 15;
             if (extra != 0) {
                 NEEDBITS(extra);
                 offset += BITS(extra);
diff --git a/third_party/zlib/contrib/infback9/inftree9.c b/third_party/zlib/contrib/infback9/inftree9.c
index 0993f75..4a73ad2 100644
--- a/third_party/zlib/contrib/infback9/inftree9.c
+++ b/third_party/zlib/contrib/infback9/inftree9.c
@@ -1,5 +1,5 @@
 /* inftree9.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2005 Mark Adler
+ * Copyright (C) 1995-2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -9,7 +9,7 @@
 #define MAXBITS 15
 
 const char inflate9_copyright[] =
-   " inflate9 1.2.3 Copyright 1995-2005 Mark Adler ";
+   " inflate9 1.2.8 Copyright 1995-2013 Mark Adler ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -64,7 +64,7 @@ unsigned short FAR *work;
     static const unsigned short lext[31] = { /* Length codes 257..285 extra */
         128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129,
         130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132,
-        133, 133, 133, 133, 144, 201, 196};
+        133, 133, 133, 133, 144, 72, 78};
     static const unsigned short dbase[32] = { /* Distance codes 0..31 base */
         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49,
         65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,
@@ -160,11 +160,10 @@ unsigned short FAR *work;
        entered in the tables.
 
        used keeps track of how many table entries have been allocated from the
-       provided *table space.  It is checked when a LENS table is being made
-       against the space in *table, ENOUGH, minus the maximum space needed by
-       the worst case distance code, MAXD.  This should never happen, but the
-       sufficiency of ENOUGH has not been proven exhaustively, hence the check.
-       This assumes that when type == LENS, bits == 9.
+       provided *table space.  It is checked for LENS and DIST tables against
+       the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+       the initial root table size constants.  See the comments in inftree9.h
+       for more information.
 
        sym increments through all symbols, and the loop terminates when
        all codes of length max, i.e. all codes, have been processed.  This
@@ -203,7 +202,8 @@ unsigned short FAR *work;
     mask = used - 1;            /* mask for comparing low */
 
     /* check available table space */
-    if (type == LENS && used >= ENOUGH - MAXD)
+    if ((type == LENS && used >= ENOUGH_LENS) ||
+        (type == DISTS && used >= ENOUGH_DISTS))
         return 1;
 
     /* process all codes and make table entries */
@@ -270,7 +270,8 @@ unsigned short FAR *work;
 
             /* check for enough space */
             used += 1U << curr;
-            if (type == LENS && used >= ENOUGH - MAXD)
+            if ((type == LENS && used >= ENOUGH_LENS) ||
+                (type == DISTS && used >= ENOUGH_DISTS))
                 return 1;
 
             /* point entry in root table to sub-table */
diff --git a/third_party/zlib/contrib/infback9/inftree9.h b/third_party/zlib/contrib/infback9/inftree9.h
index a268084..5ab21f0 100644
--- a/third_party/zlib/contrib/infback9/inftree9.h
+++ b/third_party/zlib/contrib/infback9/inftree9.h
@@ -1,5 +1,5 @@
 /* inftree9.h -- header to use inftree9.c
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2008 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -35,15 +35,21 @@ typedef struct {
     01000000 - invalid code
  */
 
-/* Maximum size of dynamic tree.  The maximum found in a long but non-
-   exhaustive search was 1444 code structures (852 for length/literals
-   and 592 for distances, the latter actually the result of an
-   exhaustive search).  The true maximum is not known, but the value
-   below is more than safe. */
-#define ENOUGH 2048
-#define MAXD 592
+/* Maximum size of the dynamic table.  The maximum number of code structures is
+   1446, which is the sum of 852 for literal/length codes and 594 for distance
+   codes.  These values were found by exhaustive searches using the program
+   examples/enough.c found in the zlib distribtution.  The arguments to that
+   program are the number of symbols, the initial root table size, and the
+   maximum bit length of a code.  "enough 286 9 15" for literal/length codes
+   returns returns 852, and "enough 32 6 15" for distance codes returns 594.
+   The initial root table size (9 or 6) is found in the fifth argument of the
+   inflate_table() calls in infback9.c.  If the root table size is changed,
+   then these maximum sizes would be need to be recalculated and updated. */
+#define ENOUGH_LENS 852
+#define ENOUGH_DISTS 594
+#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
 
-/* Type of code to build for inftable() */
+/* Type of code to build for inflate_table9() */
 typedef enum {
     CODES,
     LENS,
diff --git a/third_party/zlib/contrib/inflate86/inffas86.c b/third_party/zlib/contrib/inflate86/inffas86.c
index 6da7635..7292f67 100644
--- a/third_party/zlib/contrib/inflate86/inffas86.c
+++ b/third_party/zlib/contrib/inflate86/inffas86.c
@@ -113,7 +113,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
     ar.beg = ar.out - (start - strm->avail_out);
     ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT);
     ar.wsize = state->wsize;
-    ar.write = state->write;
+    ar.write = state->wnext;
     ar.window = state->window;
     ar.hold = state->hold;
     ar.bits = state->bits;
diff --git a/third_party/zlib/contrib/masm686/match.asm b/third_party/zlib/contrib/masm686/match.asm
deleted file mode 100644
index 4b03a71..0000000
--- a/third_party/zlib/contrib/masm686/match.asm
+++ /dev/null
@@ -1,413 +0,0 @@
-
-; match.asm -- Pentium-Pro optimized version of longest_match()
-;
-; Updated for zlib 1.1.3 and converted to MASM 6.1x
-; Copyright (C) 2000 Dan Higdon <hdan at kinesoft.com>
-;                    and Chuck Walbourn <chuckw at kinesoft.com>
-; Corrections by Cosmin Truta <cosmint at cs.ubbcluj.ro>
-;
-; This is free software; you can redistribute it and/or modify it
-; under the terms of the GNU General Public License.
-
-; Based on match.S
-; Written for zlib 1.1.2
-; Copyright (C) 1998 Brian Raiter <breadbox at muppetlabs.com>
-;
-; Modified by Gilles Vollant (2005) for add gzhead and gzindex
-
-	.686P
-	.MODEL	FLAT
-
-;===========================================================================
-; EQUATES
-;===========================================================================
-
-MAX_MATCH	EQU 258
-MIN_MATCH	EQU 3
-MIN_LOOKAHEAD	EQU (MAX_MATCH + MIN_MATCH + 1)
-MAX_MATCH_8	EQU ((MAX_MATCH + 7) AND (NOT 7))
-
-;===========================================================================
-; STRUCTURES
-;===========================================================================
-
-; This STRUCT assumes a 4-byte alignment
-
-DEFLATE_STATE	STRUCT
-ds_strm			dd ?
-ds_status		dd ?
-ds_pending_buf		dd ?
-ds_pending_buf_size	dd ?
-ds_pending_out		dd ?
-ds_pending		dd ?
-ds_wrap			dd ?
-; gzhead and gzindex are added in zlib 1.2.2.2 (see deflate.h)
-ds_gzhead               dd ?
-ds_gzindex              dd ?
-ds_data_type		db ?
-ds_method		db ?
-			db ?	; padding
-			db ?	; padding
-ds_last_flush		dd ?
-ds_w_size		dd ?	; used
-ds_w_bits		dd ?
-ds_w_mask		dd ?	; used
-ds_window		dd ?	; used
-ds_window_size		dd ?
-ds_prev			dd ?	; used
-ds_head			dd ?
-ds_ins_h		dd ?
-ds_hash_size		dd ?
-ds_hash_bits		dd ?
-ds_hash_mask		dd ?
-ds_hash_shift		dd ?
-ds_block_start		dd ?
-ds_match_length		dd ?	; used
-ds_prev_match		dd ?	; used
-ds_match_available	dd ?
-ds_strstart		dd ?	; used
-ds_match_start		dd ?	; used
-ds_lookahead		dd ?	; used
-ds_prev_length		dd ?	; used
-ds_max_chain_length	dd ?	; used
-ds_max_laxy_match	dd ?
-ds_level		dd ?
-ds_strategy		dd ?
-ds_good_match		dd ?	; used
-ds_nice_match		dd ?	; used
-
-; Don't need anymore of the struct for match
-DEFLATE_STATE	ENDS
-
-;===========================================================================
-; CODE
-;===========================================================================
-_TEXT	SEGMENT
-
-;---------------------------------------------------------------------------
-; match_init
-;---------------------------------------------------------------------------
-	ALIGN	4
-PUBLIC	_match_init
-_match_init	PROC
-	; no initialization needed
-	ret
-_match_init	ENDP
-
-;---------------------------------------------------------------------------
-; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
-;---------------------------------------------------------------------------
-	ALIGN	4
-
-PUBLIC	_longest_match
-_longest_match	PROC
-
-; Since this code uses EBP for a scratch register, the stack frame must
-; be manually constructed and referenced relative to the ESP register.
-
-; Stack image
-; Variables
-chainlenwmask	=  0	; high word: current chain len
-			; low word: s->wmask
-window		=  4	; local copy of s->window
-windowbestlen	=  8	; s->window + bestlen
-scanend		= 12	; last two bytes of string
-scanstart	= 16	; first two bytes of string
-scanalign	= 20	; dword-misalignment of string
-nicematch	= 24	; a good enough match size
-bestlen		= 28	; size of best match so far
-scan		= 32	; ptr to string wanting match
-varsize		= 36	; number of bytes (also offset to last saved register)
-
-; Saved Registers (actually pushed into place)
-ebx_save	= 36
-edi_save	= 40
-esi_save	= 44
-ebp_save	= 48
-
-; Parameters
-retaddr		= 52
-deflatestate	= 56
-curmatch	= 60
-
-; Save registers that the compiler may be using
-	push	ebp
-	push	edi
-	push	esi
-	push	ebx
-
-; Allocate local variable space
-	sub	esp,varsize
-
-; Retrieve the function arguments. ecx will hold cur_match
-; throughout the entire function. edx will hold the pointer to the
-; deflate_state structure during the function's setup (before
-; entering the main loop).
-
-	mov	edx, [esp+deflatestate]
-ASSUME	edx:PTR DEFLATE_STATE
-
-	mov	ecx, [esp+curmatch]
-
-; uInt wmask = s->w_mask;
-; unsigned chain_length = s->max_chain_length;
-; if (s->prev_length >= s->good_match) {
-;     chain_length >>= 2;
-; }
-
-	mov	eax, [edx].ds_prev_length
-	mov	ebx, [edx].ds_good_match
-	cmp	eax, ebx
-	mov	eax, [edx].ds_w_mask
-	mov	ebx, [edx].ds_max_chain_length
-	jl	SHORT LastMatchGood
-	shr	ebx, 2
-LastMatchGood:
-
-; chainlen is decremented once beforehand so that the function can
-; use the sign flag instead of the zero flag for the exit test.
-; It is then shifted into the high word, to make room for the wmask
-; value, which it will always accompany.
-
-	dec	ebx
-	shl	ebx, 16
-	or	ebx, eax
-	mov	[esp+chainlenwmask], ebx
-
-; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-
-	mov	eax, [edx].ds_nice_match
-	mov	ebx, [edx].ds_lookahead
-	cmp	ebx, eax
-	jl	SHORT LookaheadLess
-	mov	ebx, eax
-LookaheadLess:
-	mov	[esp+nicematch], ebx
-
-;/* register Bytef *scan = s->window + s->strstart;                     */
-
-	mov	esi, [edx].ds_window
-	mov	[esp+window], esi
-	mov	ebp, [edx].ds_strstart
-	lea	edi, [esi+ebp]
-	mov	[esp+scan],edi
-
-;/* Determine how many bytes the scan ptr is off from being             */
-;/* dword-aligned.                                                      */
-
-	mov	eax, edi
-	neg	eax
-	and	eax, 3
-	mov	[esp+scanalign], eax
-
-;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                      */
-;/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                          */
-
-	mov	eax, [edx].ds_w_size
-	sub	eax, MIN_LOOKAHEAD
-	sub	ebp, eax
-	jg	SHORT LimitPositive
-	xor	ebp, ebp
-LimitPositive:
-
-;/* int best_len = s->prev_length;                                      */
-
-	mov	eax, [edx].ds_prev_length
-	mov	[esp+bestlen], eax
-
-;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
-
-	add	esi, eax
-	mov	[esp+windowbestlen], esi
-
-;/* register ush scan_start = *(ushf*)scan;                             */
-;/* register ush scan_end   = *(ushf*)(scan+best_len-1);                */
-;/* Posf *prev = s->prev;                                               */
-
-	movzx	ebx, WORD PTR[edi]
-	mov	[esp+scanstart], ebx
-	movzx	ebx, WORD PTR[eax+edi-1]
-	mov	[esp+scanend], ebx
-	mov	edi, [edx].ds_prev
-
-;/* Jump into the main loop.                                            */
-
-	mov	edx, [esp+chainlenwmask]
-	jmp	SHORT LoopEntry
-
-;/* do {
-; *     match = s->window + cur_match;
-; *     if (*(ushf*)(match+best_len-1) != scan_end ||
-; *         *(ushf*)match != scan_start) continue;
-; *     [...]
-; * } while ((cur_match = prev[cur_match & wmask]) > limit
-; *          && --chain_length != 0);
-; *
-; * Here is the inner loop of the function. The function will spend the
-; * majority of its time in this loop, and majority of that time will
-; * be spent in the first ten instructions.
-; *
-; * Within this loop:
-; * %ebx = scanend
-; * %ecx = curmatch
-; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
-; * %esi = windowbestlen - i.e., (window + bestlen)
-; * %edi = prev
-; * %ebp = limit
-; */
-
-	ALIGN	4
-LookupLoop:
-	and	ecx, edx
-	movzx	ecx, WORD PTR[edi+ecx*2]
-	cmp	ecx, ebp
-	jbe	LeaveNow
-	sub	edx, 000010000H
-	js	LeaveNow
-
-LoopEntry:
-	movzx	eax, WORD PTR[esi+ecx-1]
-	cmp	eax, ebx
-	jnz	SHORT LookupLoop
-
-	mov	eax, [esp+window]
-	movzx	eax, WORD PTR[eax+ecx]
-	cmp	eax, [esp+scanstart]
-	jnz	SHORT LookupLoop
-
-;/* Store the current value of chainlen.                                */
-
-	mov	[esp+chainlenwmask], edx
-
-;/* Point %edi to the string under scrutiny, and %esi to the string we  */
-;/* are hoping to match it up with. In actuality, %esi and %edi are     */
-;/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is     */
-;/* initialized to -(MAX_MATCH_8 - scanalign).                          */
-
-	mov	esi, [esp+window]
-	mov	edi, [esp+scan]
-	add	esi, ecx
-	mov	eax, [esp+scanalign]
-	mov	edx, -MAX_MATCH_8
-	lea	edi, [edi+eax+MAX_MATCH_8]
-	lea	esi, [esi+eax+MAX_MATCH_8]
-
-;/* Test the strings for equality, 8 bytes at a time. At the end,
-; * adjust %edx so that it is offset to the exact byte that mismatched.
-; *
-; * We already know at this point that the first three bytes of the
-; * strings match each other, and they can be safely passed over before
-; * starting the compare loop. So what this code does is skip over 0-3
-; * bytes, as much as necessary in order to dword-align the %edi
-; * pointer. (%esi will still be misaligned three times out of four.)
-; *
-; * It should be confessed that this loop usually does not represent
-; * much of the total running time. Replacing it with a more
-; * straightforward "rep cmpsb" would not drastically degrade
-; * performance.
-; */
-
-LoopCmps:
-	mov	eax, DWORD PTR[esi+edx]
-	xor	eax, DWORD PTR[edi+edx]
-	jnz	SHORT LeaveLoopCmps
-
-	mov	eax, DWORD PTR[esi+edx+4]
-	xor	eax, DWORD PTR[edi+edx+4]
-	jnz	SHORT LeaveLoopCmps4
-
-	add	edx, 8
-	jnz	SHORT LoopCmps
-	jmp	LenMaximum
-	ALIGN	4
-
-LeaveLoopCmps4:
-	add	edx, 4
-
-LeaveLoopCmps:
-	test	eax, 00000FFFFH
-	jnz	SHORT LenLower
-
-	add	edx, 2
-	shr	eax, 16
-
-LenLower:
-	sub	al, 1
-	adc	edx, 0
-
-;/* Calculate the length of the match. If it is longer than MAX_MATCH,  */
-;/* then automatically accept it as the best possible match and leave.  */
-
-	lea	eax, [edi+edx]
-	mov	edi, [esp+scan]
-	sub	eax, edi
-	cmp	eax, MAX_MATCH
-	jge	SHORT LenMaximum
-
-;/* If the length of the match is not longer than the best match we     */
-;/* have so far, then forget it and return to the lookup loop.          */
-
-	mov	edx, [esp+deflatestate]
-	mov	ebx, [esp+bestlen]
-	cmp	eax, ebx
-	jg	SHORT LongerMatch
-	mov	esi, [esp+windowbestlen]
-	mov	edi, [edx].ds_prev
-	mov	ebx, [esp+scanend]
-	mov	edx, [esp+chainlenwmask]
-	jmp	LookupLoop
-	ALIGN	4
-
-;/*         s->match_start = cur_match;                                 */
-;/*         best_len = len;                                             */
-;/*         if (len >= nice_match) break;                               */
-;/*         scan_end = *(ushf*)(scan+best_len-1);                       */
-
-LongerMatch:
-	mov	ebx, [esp+nicematch]
-	mov	[esp+bestlen], eax
-	mov	[edx].ds_match_start, ecx
-	cmp	eax, ebx
-	jge	SHORT LeaveNow
-	mov	esi, [esp+window]
-	add	esi, eax
-	mov	[esp+windowbestlen], esi
-	movzx	ebx, WORD PTR[edi+eax-1]
-	mov	edi, [edx].ds_prev
-	mov	[esp+scanend], ebx
-	mov	edx, [esp+chainlenwmask]
-	jmp	LookupLoop
-	ALIGN	4
-
-;/* Accept the current string, with the maximum possible length.        */
-
-LenMaximum:
-	mov	edx, [esp+deflatestate]
-	mov	DWORD PTR[esp+bestlen], MAX_MATCH
-	mov	[edx].ds_match_start, ecx
-
-;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;          */
-;/* return s->lookahead;                                                */
-
-LeaveNow:
-	mov	edx, [esp+deflatestate]
-	mov	ebx, [esp+bestlen]
-	mov	eax, [edx].ds_lookahead
-	cmp	ebx, eax
-	jg	SHORT LookaheadRet
-	mov	eax, ebx
-LookaheadRet:
-
-; Restore the stack and return from whence we came.
-
-	add	esp, varsize
-	pop	ebx
-	pop	esi
-	pop	edi
-	pop	ebp
-	ret
-
-_longest_match	ENDP
-
-_TEXT	ENDS
-END
diff --git a/third_party/zlib/contrib/masmx64/gvmat64.asm b/third_party/zlib/contrib/masmx64/gvmat64.asm
index 790d655..9879c28 100644
--- a/third_party/zlib/contrib/masmx64/gvmat64.asm
+++ b/third_party/zlib/contrib/masmx64/gvmat64.asm
@@ -2,8 +2,10 @@
 ;    deflate_state *s,
 ;    IPos cur_match);                             /* current match */
 
-; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86
-; Copyright (C) 1995-2005 Jean-loup Gailly, Brian Raiter and Gilles Vollant.
+; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86_64
+;  (AMD64 on Athlon 64, Opteron, Phenom
+;     and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7)
+; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant.
 ;
 ; File written by Gilles Vollant, by converting to assembly the longest_match
 ;  from Jean-loup Gailly in deflate.c of zLib and infoZip zip.
@@ -11,6 +13,24 @@
 ;  and by taking inspiration on asm686 with masm, optimised assembly code
 ;        from Brian Raiter, written 1998
 ;
+;  This software is provided 'as-is', without any express or implied
+;  warranty.  In no event will the authors be held liable for any damages
+;  arising from the use of this software.
+;
+;  Permission is granted to anyone to use this software for any purpose,
+;  including commercial applications, and to alter it and redistribute it
+;  freely, subject to the following restrictions:
+;
+;  1. The origin of this software must not be misrepresented; you must not
+;     claim that you wrote the original software. If you use this software
+;     in a product, an acknowledgment in the product documentation would be
+;     appreciated but is not required.
+;  2. Altered source versions must be plainly marked as such, and must not be
+;     misrepresented as being the original software
+;  3. This notice may not be removed or altered from any source distribution.
+;
+;
+;
 ;         http://www.zlib.net
 ;         http://www.winimage.com/zLibDll
 ;         http://www.muppetlabs.com/~breadbox/software/assembly.html
@@ -26,10 +46,10 @@
 ;
 ; This file compile with Microsoft Macro Assembler (x64) for AMD64
 ;
-;   ml64.exe is given with Visual Studio 2005 and Windows 2003 server DDK
+;   ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK
 ;
-;   (you can get Windows 2003 server DDK with ml64 and cl for AMD64 from
-;      http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
+;   (you can get Windows WDK with ml64 for AMD64 from
+;      http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price)
 ;
 
 
@@ -71,6 +91,25 @@ save_r13        equ  rsp + 64 - LocalVarsSize
 ;save_r15        equ  rsp + 80 - LocalVarsSize
 
 
+; summary of register usage
+; scanend     ebx
+; scanendw    bx
+; chainlenwmask   edx
+; curmatch    rsi
+; curmatchd   esi
+; windowbestlen   r8
+; scanalign   r9
+; scanalignd  r9d
+; window      r10
+; bestlen     r11
+; bestlend    r11d
+; scanstart   r12d
+; scanstartw  r12w
+; scan        r13
+; nicematch   r14d
+; limit       r15
+; limitd      r15d
+; prev        rcx
 
 ;  all the +4 offsets are due to the addition of pending_buf_size (in zlib
 ;  in the deflate_state structure since the asm code was first written
@@ -406,7 +445,8 @@ LoopCmps:
 
         add rdx,8+8+8
 
-        jmp short LoopCmps
+        jnz short LoopCmps
+        jmp short LenMaximum
 LeaveLoopCmps16: add rdx,8
 LeaveLoopCmps8: add rdx,8
 LeaveLoopCmps:
diff --git a/third_party/zlib/contrib/masmx64/inffas8664.c b/third_party/zlib/contrib/masmx64/inffas8664.c
index 3af764d..e8af06f 100644
--- a/third_party/zlib/contrib/masmx64/inffas8664.c
+++ b/third_party/zlib/contrib/masmx64/inffas8664.c
@@ -111,11 +111,11 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
     type_ar ar;
     void inffas8664fnc(struct inffast_ar * par);
 
-    
+
 
 #if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64))
 #define PAD_AVAIL_IN 6
-#define PAD_AVAIL_OUT 258    
+#define PAD_AVAIL_OUT 258
 #else
 #define PAD_AVAIL_IN 5
 #define PAD_AVAIL_OUT 257
@@ -130,7 +130,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
     ar.beg = ar.out - (start - strm->avail_out);
     ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT);
     ar.wsize = state->wsize;
-    ar.write = state->write;
+    ar.write = state->wnext;
     ar.window = state->window;
     ar.hold = state->hold;
     ar.bits = state->bits;
diff --git a/third_party/zlib/contrib/masmx64/inffasx64.asm b/third_party/zlib/contrib/masmx64/inffasx64.asm
index b5d93a2..60a8d89 100644
--- a/third_party/zlib/contrib/masmx64/inffasx64.asm
+++ b/third_party/zlib/contrib/masmx64/inffasx64.asm
@@ -9,12 +9,16 @@
 ;   ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
 ;   with Microsoft Macro Assembler (x64) for AMD64
 ;
-;   ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK
+
+; This file compile with Microsoft Macro Assembler (x64) for AMD64
+;
+;   ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK
 ;
-;   (you can get Windows 2003 server DDK with ml64 and cl.exe for AMD64 from 
-;      http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
+;   (you can get Windows WDK with ml64 for AMD64 from
+;      http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price)
 ;
 
+
 .code
 inffas8664fnc PROC
 
@@ -379,7 +383,7 @@ L_break_loop_with_status:
 	mov r14,[rsp-40]
 	mov r15,[rsp-48]
 	mov rbx,[rsp-56]
-	
+
     ret 0
 ;          :
 ;          : "m" (ar)
diff --git a/third_party/zlib/contrib/masmx64/readme.txt b/third_party/zlib/contrib/masmx64/readme.txt
index ee03115..2da6733 100644
--- a/third_party/zlib/contrib/masmx64/readme.txt
+++ b/third_party/zlib/contrib/masmx64/readme.txt
@@ -12,7 +12,10 @@ inffasx64.asm and inffas8664.c were written by Chris Anderson, by optimizing
 
 Use instructions
 ----------------
-Copy these files into the zlib source directory.
+Assemble the .asm files using MASM and put the object files into the zlib source
+directory.  You can also get object files here:
+
+     http://www.winimage.com/zLibDll/zlib124_masm_obj.zip
 
 define ASMV and ASMINF in your project. Include inffas8664.c in your source tree,
 and inffasx64.obj and gvmat64.obj as object to link.
@@ -24,5 +27,5 @@ run bld_64.bat with Microsoft Macro Assembler (x64) for AMD64 (ml64.exe)
 
 ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK
 
-You can get Windows 2003 server DDK with ml64 and cl for AMD64 from 
+You can get Windows 2003 server DDK with ml64 and cl for AMD64 from
   http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
diff --git a/third_party/zlib/contrib/masmx86/bld_ml32.bat b/third_party/zlib/contrib/masmx86/bld_ml32.bat
index 99144d0..e1b86bf 100644
--- a/third_party/zlib/contrib/masmx86/bld_ml32.bat
+++ b/third_party/zlib/contrib/masmx86/bld_ml32.bat
@@ -1,2 +1,2 @@
-ml /coff /Zi /c /Flgvmat32.lst  gvmat32.asm 
-ml /coff /Zi /c /Flinffas32.lst inffas32.asm 
+ml /coff /Zi /c /Flmatch686.lst match686.asm
+ml /coff /Zi /c /Flinffas32.lst inffas32.asm
diff --git a/third_party/zlib/contrib/masmx86/gvmat32.asm b/third_party/zlib/contrib/masmx86/gvmat32.asm
deleted file mode 100644
index 874bb2d..0000000
--- a/third_party/zlib/contrib/masmx86/gvmat32.asm
+++ /dev/null
@@ -1,972 +0,0 @@
-; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86
-; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
-; File written by Gilles Vollant, by modifiying the longest_match
-;  from Jean-loup Gailly in deflate.c
-;
-;         http://www.zlib.net
-;         http://www.winimage.com/zLibDll
-;         http://www.muppetlabs.com/~breadbox/software/assembly.html
-;
-; For Visual C++ 4.x and higher and ML 6.x and higher
-;   ml.exe is in directory \MASM611C of Win95 DDK
-;   ml.exe is also distributed in http://www.masm32.com/masmdl.htm
-;    and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/
-;
-; this file contain two implementation of longest_match
-;
-;  longest_match_7fff : written 1996 by Gilles Vollant optimized for 
-;            first Pentium. Assume s->w_mask == 0x7fff
-;  longest_match_686 : written by Brian raiter (1998), optimized for Pentium Pro
-;
-;  for using an seembly version of longest_match, you need define ASMV in project
-;  There is two way in using gvmat32.asm
-;
-;  A) Suggested method
-;    if you want include both longest_match_7fff and longest_match_686
-;    compile the asm file running
-;           ml /coff /Zi /Flgvmat32.lst /c gvmat32.asm
-;    and include gvmat32c.c in your project
-;    if you have an old cpu (386,486 or first Pentium) and s->w_mask==0x7fff,
-;        longest_match_7fff will be used
-;    if you have a more modern CPU (Pentium Pro, II and higher)
-;        longest_match_686 will be used
-;    on old cpu with s->w_mask!=0x7fff, longest_match_686 will be used,
-;        but this is not a sitation you'll find often
-;
-;  B) Alternative
-;    if you are not interresed in old cpu performance and want the smaller
-;       binaries possible
-;
-;    compile the asm file running
-;           ml /coff /Zi /c /Flgvmat32.lst /DNOOLDPENTIUMCODE gvmat32.asm
-;    and do not include gvmat32c.c in your project (ou define also 
-;              NOOLDPENTIUMCODE)
-;
-; note : as I known, longest_match_686 is very faster than longest_match_7fff
-;        on pentium Pro/II/III, faster (but less) in P4, but it seem
-;        longest_match_7fff can be faster (very very litte) on AMD Athlon64/K8
-;
-; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2
-
-;uInt longest_match_7fff(s, cur_match)
-;    deflate_state *s;
-;    IPos cur_match;                             /* current match */
-
-    NbStack         equ     76
-    cur_match       equ     dword ptr[esp+NbStack-0]
-    str_s           equ     dword ptr[esp+NbStack-4]
-; 5 dword on top (ret,ebp,esi,edi,ebx)
-    adrret          equ     dword ptr[esp+NbStack-8]
-    pushebp         equ     dword ptr[esp+NbStack-12]
-    pushedi         equ     dword ptr[esp+NbStack-16]
-    pushesi         equ     dword ptr[esp+NbStack-20]
-    pushebx         equ     dword ptr[esp+NbStack-24]
-
-    chain_length    equ     dword ptr [esp+NbStack-28]
-    limit           equ     dword ptr [esp+NbStack-32]
-    best_len        equ     dword ptr [esp+NbStack-36]
-    window          equ     dword ptr [esp+NbStack-40]
-    prev            equ     dword ptr [esp+NbStack-44]
-    scan_start      equ      word ptr [esp+NbStack-48]
-    wmask           equ     dword ptr [esp+NbStack-52]
-    match_start_ptr equ     dword ptr [esp+NbStack-56]
-    nice_match      equ     dword ptr [esp+NbStack-60]
-    scan            equ     dword ptr [esp+NbStack-64]
-
-    windowlen       equ     dword ptr [esp+NbStack-68]
-    match_start     equ     dword ptr [esp+NbStack-72]
-    strend          equ     dword ptr [esp+NbStack-76]
-    NbStackAdd      equ     (NbStack-24)
-
-    .386p
-
-    name    gvmatch
-    .MODEL  FLAT
-
-
-
-;  all the +zlib1222add offsets are due to the addition of fields
-;  in zlib in the deflate_state structure since the asm code was first written
-;  (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
-;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
-;  if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
-
-    zlib1222add         equ     8
-
-;  Note : these value are good with a 8 bytes boundary pack structure
-    dep_chain_length    equ     74h+zlib1222add
-    dep_window          equ     30h+zlib1222add
-    dep_strstart        equ     64h+zlib1222add
-    dep_prev_length     equ     70h+zlib1222add
-    dep_nice_match      equ     88h+zlib1222add
-    dep_w_size          equ     24h+zlib1222add
-    dep_prev            equ     38h+zlib1222add
-    dep_w_mask          equ     2ch+zlib1222add
-    dep_good_match      equ     84h+zlib1222add
-    dep_match_start     equ     68h+zlib1222add
-    dep_lookahead       equ     6ch+zlib1222add
-
-
-_TEXT                   segment
-
-IFDEF NOUNDERLINE
-   IFDEF NOOLDPENTIUMCODE
-            public  longest_match
-            public  match_init
-   ELSE            
-            public  longest_match_7fff
-            public  cpudetect32
-            public  longest_match_686
-   ENDIF
-ELSE
-   IFDEF NOOLDPENTIUMCODE
-            public  _longest_match
-            public  _match_init
-   ELSE
-            public  _longest_match_7fff
-            public  _cpudetect32
-            public  _longest_match_686
-   ENDIF
-ENDIF
-
-    MAX_MATCH           equ     258
-    MIN_MATCH           equ     3
-    MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)
-
-
-
-IFNDEF NOOLDPENTIUMCODE
-IFDEF NOUNDERLINE
-longest_match_7fff   proc near
-ELSE
-_longest_match_7fff  proc near
-ENDIF
-
-    mov     edx,[esp+4]
-
-
-
-    push    ebp
-    push    edi
-    push    esi
-    push    ebx
-
-    sub     esp,NbStackAdd
-
-; initialize or check the variables used in match.asm.
-    mov     ebp,edx
-
-; chain_length = s->max_chain_length
-; if (prev_length>=good_match) chain_length >>= 2
-    mov     edx,[ebp+dep_chain_length]
-    mov     ebx,[ebp+dep_prev_length]
-    cmp     [ebp+dep_good_match],ebx
-    ja      noshr
-    shr     edx,2
-noshr:
-; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop
-    inc     edx
-    mov     edi,[ebp+dep_nice_match]
-    mov     chain_length,edx
-    mov     eax,[ebp+dep_lookahead]
-    cmp     eax,edi
-; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-    jae     nolookaheadnicematch
-    mov     edi,eax
-nolookaheadnicematch:
-; best_len = s->prev_length
-    mov     best_len,ebx
-
-; window = s->window
-    mov     esi,[ebp+dep_window]
-    mov     ecx,[ebp+dep_strstart]
-    mov     window,esi
-
-    mov     nice_match,edi
-; scan = window + strstart
-    add     esi,ecx
-    mov     scan,esi
-; dx = *window
-    mov     dx,word ptr [esi]
-; bx = *(window+best_len-1)
-    mov     bx,word ptr [esi+ebx-1]
-    add     esi,MAX_MATCH-1
-; scan_start = *scan
-    mov     scan_start,dx
-; strend = scan + MAX_MATCH-1
-    mov     strend,esi
-; bx = scan_end = *(window+best_len-1)
-
-;    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
-;        s->strstart - (IPos)MAX_DIST(s) : NIL;
-
-    mov     esi,[ebp+dep_w_size]
-    sub     esi,MIN_LOOKAHEAD
-; here esi = MAX_DIST(s)
-    sub     ecx,esi
-    ja      nodist
-    xor     ecx,ecx
-nodist:
-    mov     limit,ecx
-
-; prev = s->prev
-    mov     edx,[ebp+dep_prev]
-    mov     prev,edx
-
-;
-    mov     edx,dword ptr [ebp+dep_match_start]
-    mov     bp,scan_start
-    mov     eax,cur_match
-    mov     match_start,edx
-
-    mov     edx,window
-    mov     edi,edx
-    add     edi,best_len
-    mov     esi,prev
-    dec     edi
-; windowlen = window + best_len -1
-    mov     windowlen,edi
-
-    jmp     beginloop2
-    align   4
-
-; here, in the loop
-;       eax = ax = cur_match
-;       ecx = limit
-;        bx = scan_end
-;        bp = scan_start
-;       edi = windowlen (window + best_len -1)
-;       esi = prev
-
-
-;// here; chain_length <=16
-normalbeg0add16:
-    add     chain_length,16
-    jz      exitloop
-normalbeg0:
-    cmp     word ptr[edi+eax],bx
-    je      normalbeg2noroll
-rcontlabnoroll:
-; cur_match = prev[cur_match & wmask]
-    and     eax,7fffh
-    mov     ax,word ptr[esi+eax*2]
-; if cur_match > limit, go to exitloop
-    cmp     ecx,eax
-    jnb     exitloop
-; if --chain_length != 0, go to exitloop
-    dec     chain_length
-    jnz     normalbeg0
-    jmp     exitloop
-
-normalbeg2noroll:
-; if (scan_start==*(cur_match+window)) goto normalbeg2
-    cmp     bp,word ptr[edx+eax]
-    jne     rcontlabnoroll
-    jmp     normalbeg2
-
-contloop3:
-    mov     edi,windowlen
-
-; cur_match = prev[cur_match & wmask]
-    and     eax,7fffh
-    mov     ax,word ptr[esi+eax*2]
-; if cur_match > limit, go to exitloop
-    cmp     ecx,eax
-jnbexitloopshort1:
-    jnb     exitloop
-; if --chain_length != 0, go to exitloop
-
-
-; begin the main loop
-beginloop2:
-    sub     chain_length,16+1
-; if chain_length <=16, don't use the unrolled loop
-    jna     normalbeg0add16
-
-do16:
-    cmp     word ptr[edi+eax],bx
-    je      normalbeg2dc0
-
-maccn   MACRO   lab
-    and     eax,7fffh
-    mov     ax,word ptr[esi+eax*2]
-    cmp     ecx,eax
-    jnb     exitloop
-    cmp     word ptr[edi+eax],bx
-    je      lab
-    ENDM
-
-rcontloop0:
-    maccn   normalbeg2dc1
-
-rcontloop1:
-    maccn   normalbeg2dc2
-
-rcontloop2:
-    maccn   normalbeg2dc3
-
-rcontloop3:
-    maccn   normalbeg2dc4
-
-rcontloop4:
-    maccn   normalbeg2dc5
-
-rcontloop5:
-    maccn   normalbeg2dc6
-
-rcontloop6:
-    maccn   normalbeg2dc7
-
-rcontloop7:
-    maccn   normalbeg2dc8
-
-rcontloop8:
-    maccn   normalbeg2dc9
-
-rcontloop9:
-    maccn   normalbeg2dc10
-
-rcontloop10:
-    maccn   short normalbeg2dc11
-
-rcontloop11:
-    maccn   short normalbeg2dc12
-
-rcontloop12:
-    maccn   short normalbeg2dc13
-
-rcontloop13:
-    maccn   short normalbeg2dc14
-
-rcontloop14:
-    maccn   short normalbeg2dc15
-
-rcontloop15:
-    and     eax,7fffh
-    mov     ax,word ptr[esi+eax*2]
-    cmp     ecx,eax
-    jnb     exitloop
-
-    sub     chain_length,16
-    ja      do16
-    jmp     normalbeg0add16
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-normbeg MACRO   rcontlab,valsub
-; if we are here, we know that *(match+best_len-1) == scan_end
-    cmp     bp,word ptr[edx+eax]
-; if (match != scan_start) goto rcontlab
-    jne     rcontlab
-; calculate the good chain_length, and we'll compare scan and match string
-    add     chain_length,16-valsub
-    jmp     iseq
-    ENDM
-
-
-normalbeg2dc11:
-    normbeg rcontloop11,11
-
-normalbeg2dc12:
-    normbeg short rcontloop12,12
-
-normalbeg2dc13:
-    normbeg short rcontloop13,13
-
-normalbeg2dc14:
-    normbeg short rcontloop14,14
-
-normalbeg2dc15:
-    normbeg short rcontloop15,15
-
-normalbeg2dc10:
-    normbeg rcontloop10,10
-
-normalbeg2dc9:
-    normbeg rcontloop9,9
-
-normalbeg2dc8:
-    normbeg rcontloop8,8
-
-normalbeg2dc7:
-    normbeg rcontloop7,7
-
-normalbeg2dc6:
-    normbeg rcontloop6,6
-
-normalbeg2dc5:
-    normbeg rcontloop5,5
-
-normalbeg2dc4:
-    normbeg rcontloop4,4
-
-normalbeg2dc3:
-    normbeg rcontloop3,3
-
-normalbeg2dc2:
-    normbeg rcontloop2,2
-
-normalbeg2dc1:
-    normbeg rcontloop1,1
-
-normalbeg2dc0:
-    normbeg rcontloop0,0
-
-
-; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end
-
-normalbeg2:
-    mov     edi,window
-
-    cmp     bp,word ptr[edi+eax]
-    jne     contloop3                   ; if *(ushf*)match != scan_start, continue
-
-iseq:
-; if we are here, we know that *(match+best_len-1) == scan_end
-; and (match == scan_start)
-
-    mov     edi,edx
-    mov     esi,scan                    ; esi = scan
-    add     edi,eax                     ; edi = window + cur_match = match
-
-    mov     edx,[esi+3]                 ; compare manually dword at match+3
-    xor     edx,[edi+3]                 ; and scan +3
-
-    jz      begincompare                ; if equal, go to long compare
-
-; we will determine the unmatch byte and calculate len (in esi)
-    or      dl,dl
-    je      eq1rr
-    mov     esi,3
-    jmp     trfinval
-eq1rr:
-    or      dx,dx
-    je      eq1
-
-    mov     esi,4
-    jmp     trfinval
-eq1:
-    and     edx,0ffffffh
-    jz      eq11
-    mov     esi,5
-    jmp     trfinval
-eq11:
-    mov     esi,6
-    jmp     trfinval
-
-begincompare:
-    ; here we now scan and match begin same
-    add     edi,6
-    add     esi,6
-    mov     ecx,(MAX_MATCH-(2+4))/4     ; scan for at most MAX_MATCH bytes
-    repe    cmpsd                       ; loop until mismatch
-
-    je      trfin                       ; go to trfin if not unmatch
-; we determine the unmatch byte
-    sub     esi,4
-    mov     edx,[edi-4]
-    xor     edx,[esi]
-
-    or      dl,dl
-    jnz     trfin
-    inc     esi
-
-    or      dx,dx
-    jnz     trfin
-    inc     esi
-
-    and     edx,0ffffffh
-    jnz     trfin
-    inc     esi
-
-trfin:
-    sub     esi,scan          ; esi = len
-trfinval:
-; here we have finised compare, and esi contain len of equal string
-    cmp     esi,best_len        ; if len > best_len, go newbestlen
-    ja      short newbestlen
-; now we restore edx, ecx and esi, for the big loop
-    mov     esi,prev
-    mov     ecx,limit
-    mov     edx,window
-    jmp     contloop3
-
-newbestlen:
-    mov     best_len,esi        ; len become best_len
-
-    mov     match_start,eax     ; save new position as match_start
-    cmp     esi,nice_match      ; if best_len >= nice_match, exit
-    jae     exitloop
-    mov     ecx,scan
-    mov     edx,window          ; restore edx=window
-    add     ecx,esi
-    add     esi,edx
-
-    dec     esi
-    mov     windowlen,esi       ; windowlen = window + best_len-1
-    mov     bx,[ecx-1]          ; bx = *(scan+best_len-1) = scan_end
-
-; now we restore ecx and esi, for the big loop :
-    mov     esi,prev
-    mov     ecx,limit
-    jmp     contloop3
-
-exitloop:
-; exit : s->match_start=match_start
-    mov     ebx,match_start
-    mov     ebp,str_s
-    mov     ecx,best_len
-    mov     dword ptr [ebp+dep_match_start],ebx
-    mov     eax,dword ptr [ebp+dep_lookahead]
-    cmp     ecx,eax
-    ja      minexlo
-    mov     eax,ecx
-minexlo:
-; return min(best_len,s->lookahead)
-
-; restore stack and register ebx,esi,edi,ebp
-    add     esp,NbStackAdd
-
-    pop     ebx
-    pop     esi
-    pop     edi
-    pop     ebp
-    ret
-InfoAuthor:
-; please don't remove this string !
-; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!
-    db     0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah
-
-
-
-IFDEF NOUNDERLINE
-longest_match_7fff   endp
-ELSE
-_longest_match_7fff  endp
-ENDIF
-
-
-IFDEF NOUNDERLINE
-cpudetect32     proc near
-ELSE
-_cpudetect32    proc near
-ENDIF
-
-    push    ebx
-
-    pushfd                  ; push original EFLAGS
-    pop     eax             ; get original EFLAGS
-    mov     ecx, eax        ; save original EFLAGS
-    xor     eax, 40000h     ; flip AC bit in EFLAGS
-    push    eax             ; save new EFLAGS value on stack
-    popfd                   ; replace current EFLAGS value
-    pushfd                  ; get new EFLAGS
-    pop     eax             ; store new EFLAGS in EAX
-    xor     eax, ecx        ; can’t toggle AC bit, processor=80386
-    jz      end_cpu_is_386  ; jump if 80386 processor
-    push    ecx
-    popfd                   ; restore AC bit in EFLAGS first
-
-    pushfd
-    pushfd
-    pop     ecx
-
-    mov     eax, ecx        ; get original EFLAGS
-    xor     eax, 200000h    ; flip ID bit in EFLAGS
-    push    eax             ; save new EFLAGS value on stack
-    popfd                   ; replace current EFLAGS value
-    pushfd                  ; get new EFLAGS
-    pop     eax             ; store new EFLAGS in EAX
-    popfd                   ; restore original EFLAGS
-    xor     eax, ecx        ; can’t toggle ID bit,
-    je      is_old_486      ; processor=old
-
-    mov     eax,1
-    db      0fh,0a2h        ;CPUID
-
-exitcpudetect:
-    pop ebx
-    ret
-
-end_cpu_is_386:
-    mov     eax,0300h
-    jmp     exitcpudetect
-
-is_old_486:
-    mov     eax,0400h
-    jmp     exitcpudetect
-
-IFDEF NOUNDERLINE
-cpudetect32     endp
-ELSE
-_cpudetect32    endp
-ENDIF
-ENDIF
-
-MAX_MATCH       equ     258
-MIN_MATCH       equ     3
-MIN_LOOKAHEAD   equ     (MAX_MATCH + MIN_MATCH + 1)
-MAX_MATCH_8_     equ     ((MAX_MATCH + 7) AND 0FFF0h)
-
-
-;;; stack frame offsets
-
-chainlenwmask   equ  esp + 0    ; high word: current chain len
-                    ; low word: s->wmask
-window      equ  esp + 4    ; local copy of s->window
-windowbestlen   equ  esp + 8    ; s->window + bestlen
-scanstart   equ  esp + 16   ; first two bytes of string
-scanend     equ  esp + 12   ; last two bytes of string
-scanalign   equ  esp + 20   ; dword-misalignment of string
-nicematch   equ  esp + 24   ; a good enough match size
-bestlen     equ  esp + 28   ; size of best match so far
-scan        equ  esp + 32   ; ptr to string wanting match
-
-LocalVarsSize   equ 36
-;   saved ebx   byte esp + 36
-;   saved edi   byte esp + 40
-;   saved esi   byte esp + 44
-;   saved ebp   byte esp + 48
-;   return address  byte esp + 52
-deflatestate    equ  esp + 56   ; the function arguments
-curmatch    equ  esp + 60
-
-;;; Offsets for fields in the deflate_state structure. These numbers
-;;; are calculated from the definition of deflate_state, with the
-;;; assumption that the compiler will dword-align the fields. (Thus,
-;;; changing the definition of deflate_state could easily cause this
-;;; program to crash horribly, without so much as a warning at
-;;; compile time. Sigh.)
-
-dsWSize     equ 36+zlib1222add
-dsWMask     equ 44+zlib1222add
-dsWindow    equ 48+zlib1222add
-dsPrev      equ 56+zlib1222add
-dsMatchLen  equ 88+zlib1222add
-dsPrevMatch equ 92+zlib1222add
-dsStrStart  equ 100+zlib1222add
-dsMatchStart    equ 104+zlib1222add
-dsLookahead equ 108+zlib1222add
-dsPrevLen   equ 112+zlib1222add
-dsMaxChainLen   equ 116+zlib1222add
-dsGoodMatch equ 132+zlib1222add
-dsNiceMatch equ 136+zlib1222add
-
-
-;;; match.asm -- Pentium-Pro-optimized version of longest_match()
-;;; Written for zlib 1.1.2
-;;; Copyright (C) 1998 Brian Raiter <breadbox at muppetlabs.com>
-;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html
-;;;
-;;; This is free software; you can redistribute it and/or modify it
-;;; under the terms of the GNU General Public License.
-
-;GLOBAL _longest_match, _match_init
-
-
-;SECTION    .text
-
-;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
-
-;_longest_match:
-IFDEF NOOLDPENTIUMCODE
-    IFDEF NOUNDERLINE
-    longest_match       proc near
-    ELSE
-    _longest_match      proc near
-    ENDIF
-ELSE
-    IFDEF NOUNDERLINE
-    longest_match_686   proc near
-    ELSE
-    _longest_match_686  proc near
-    ENDIF
-ENDIF
-
-;;; Save registers that the compiler may be using, and adjust esp to
-;;; make room for our stack frame.
-
-        push    ebp
-        push    edi
-        push    esi
-        push    ebx
-        sub esp, LocalVarsSize
-
-;;; Retrieve the function arguments. ecx will hold cur_match
-;;; throughout the entire function. edx will hold the pointer to the
-;;; deflate_state structure during the function's setup (before
-;;; entering the main loop.
-
-        mov edx, [deflatestate]
-        mov ecx, [curmatch]
-
-;;; uInt wmask = s->w_mask;
-;;; unsigned chain_length = s->max_chain_length;
-;;; if (s->prev_length >= s->good_match) {
-;;;     chain_length >>= 2;
-;;; }
-
-        mov eax, [edx + dsPrevLen]
-        mov ebx, [edx + dsGoodMatch]
-        cmp eax, ebx
-        mov eax, [edx + dsWMask]
-        mov ebx, [edx + dsMaxChainLen]
-        jl  LastMatchGood
-        shr ebx, 2
-LastMatchGood:
-
-;;; chainlen is decremented once beforehand so that the function can
-;;; use the sign flag instead of the zero flag for the exit test.
-;;; It is then shifted into the high word, to make room for the wmask
-;;; value, which it will always accompany.
-
-        dec ebx
-        shl ebx, 16
-        or  ebx, eax
-        mov [chainlenwmask], ebx
-
-;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-
-        mov eax, [edx + dsNiceMatch]
-        mov ebx, [edx + dsLookahead]
-        cmp ebx, eax
-        jl  LookaheadLess
-        mov ebx, eax
-LookaheadLess:  mov [nicematch], ebx
-
-;;; register Bytef *scan = s->window + s->strstart;
-
-        mov esi, [edx + dsWindow]
-        mov [window], esi
-        mov ebp, [edx + dsStrStart]
-        lea edi, [esi + ebp]
-        mov [scan], edi
-
-;;; Determine how many bytes the scan ptr is off from being
-;;; dword-aligned.
-
-        mov eax, edi
-        neg eax
-        and eax, 3
-        mov [scanalign], eax
-
-;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
-;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;
-
-        mov eax, [edx + dsWSize]
-        sub eax, MIN_LOOKAHEAD
-        sub ebp, eax
-        jg  LimitPositive
-        xor ebp, ebp
-LimitPositive:
-
-;;; int best_len = s->prev_length;
-
-        mov eax, [edx + dsPrevLen]
-        mov [bestlen], eax
-
-;;; Store the sum of s->window + best_len in esi locally, and in esi.
-
-        add esi, eax
-        mov [windowbestlen], esi
-
-;;; register ush scan_start = *(ushf*)scan;
-;;; register ush scan_end   = *(ushf*)(scan+best_len-1);
-;;; Posf *prev = s->prev;
-
-        movzx   ebx, word ptr [edi]
-        mov [scanstart], ebx
-        movzx   ebx, word ptr [edi + eax - 1]
-        mov [scanend], ebx
-        mov edi, [edx + dsPrev]
-
-;;; Jump into the main loop.
-
-        mov edx, [chainlenwmask]
-        jmp short LoopEntry
-
-align 4
-
-;;; do {
-;;;     match = s->window + cur_match;
-;;;     if (*(ushf*)(match+best_len-1) != scan_end ||
-;;;         *(ushf*)match != scan_start) continue;
-;;;     [...]
-;;; } while ((cur_match = prev[cur_match & wmask]) > limit
-;;;          && --chain_length != 0);
-;;;
-;;; Here is the inner loop of the function. The function will spend the
-;;; majority of its time in this loop, and majority of that time will
-;;; be spent in the first ten instructions.
-;;;
-;;; Within this loop:
-;;; ebx = scanend
-;;; ecx = curmatch
-;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
-;;; esi = windowbestlen - i.e., (window + bestlen)
-;;; edi = prev
-;;; ebp = limit
-
-LookupLoop:
-        and ecx, edx
-        movzx   ecx, word ptr [edi + ecx*2]
-        cmp ecx, ebp
-        jbe LeaveNow
-        sub edx, 00010000h
-        js  LeaveNow
-LoopEntry:  movzx   eax, word ptr [esi + ecx - 1]
-        cmp eax, ebx
-        jnz LookupLoop
-        mov eax, [window]
-        movzx   eax, word ptr [eax + ecx]
-        cmp eax, [scanstart]
-        jnz LookupLoop
-
-;;; Store the current value of chainlen.
-
-        mov [chainlenwmask], edx
-
-;;; Point edi to the string under scrutiny, and esi to the string we
-;;; are hoping to match it up with. In actuality, esi and edi are
-;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
-;;; initialized to -(MAX_MATCH_8 - scanalign).
-
-        mov esi, [window]
-        mov edi, [scan]
-        add esi, ecx
-        mov eax, [scanalign]
-        mov edx, 0fffffef8h; -(MAX_MATCH_8)
-        lea edi, [edi + eax + 0108h] ;MAX_MATCH_8]
-        lea esi, [esi + eax + 0108h] ;MAX_MATCH_8]
-
-;;; Test the strings for equality, 8 bytes at a time. At the end,
-;;; adjust edx so that it is offset to the exact byte that mismatched.
-;;;
-;;; We already know at this point that the first three bytes of the
-;;; strings match each other, and they can be safely passed over before
-;;; starting the compare loop. So what this code does is skip over 0-3
-;;; bytes, as much as necessary in order to dword-align the edi
-;;; pointer. (esi will still be misaligned three times out of four.)
-;;;
-;;; It should be confessed that this loop usually does not represent
-;;; much of the total running time. Replacing it with a more
-;;; straightforward "rep cmpsb" would not drastically degrade
-;;; performance.
-
-LoopCmps:
-        mov eax, [esi + edx]
-        xor eax, [edi + edx]
-        jnz LeaveLoopCmps
-        mov eax, [esi + edx + 4]
-        xor eax, [edi + edx + 4]
-        jnz LeaveLoopCmps4
-        add edx, 8
-        jnz LoopCmps
-        jmp short LenMaximum
-LeaveLoopCmps4: add edx, 4
-LeaveLoopCmps:  test    eax, 0000FFFFh
-        jnz LenLower
-        add edx,  2
-        shr eax, 16
-LenLower:   sub al, 1
-        adc edx, 0
-
-;;; Calculate the length of the match. If it is longer than MAX_MATCH,
-;;; then automatically accept it as the best possible match and leave.
-
-        lea eax, [edi + edx]
-        mov edi, [scan]
-        sub eax, edi
-        cmp eax, MAX_MATCH
-        jge LenMaximum
-
-;;; If the length of the match is not longer than the best match we
-;;; have so far, then forget it and return to the lookup loop.
-
-        mov edx, [deflatestate]
-        mov ebx, [bestlen]
-        cmp eax, ebx
-        jg  LongerMatch
-        mov esi, [windowbestlen]
-        mov edi, [edx + dsPrev]
-        mov ebx, [scanend]
-        mov edx, [chainlenwmask]
-        jmp LookupLoop
-
-;;;         s->match_start = cur_match;
-;;;         best_len = len;
-;;;         if (len >= nice_match) break;
-;;;         scan_end = *(ushf*)(scan+best_len-1);
-
-LongerMatch:    mov ebx, [nicematch]
-        mov [bestlen], eax
-        mov [edx + dsMatchStart], ecx
-        cmp eax, ebx
-        jge LeaveNow
-        mov esi, [window]
-        add esi, eax
-        mov [windowbestlen], esi
-        movzx   ebx, word ptr [edi + eax - 1]
-        mov edi, [edx + dsPrev]
-        mov [scanend], ebx
-        mov edx, [chainlenwmask]
-        jmp LookupLoop
-
-;;; Accept the current string, with the maximum possible length.
-
-LenMaximum: mov edx, [deflatestate]
-        mov dword ptr [bestlen], MAX_MATCH
-        mov [edx + dsMatchStart], ecx
-
-;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
-;;; return s->lookahead;
-
-LeaveNow:
-        mov edx, [deflatestate]
-        mov ebx, [bestlen]
-        mov eax, [edx + dsLookahead]
-        cmp ebx, eax
-        jg  LookaheadRet
-        mov eax, ebx
-LookaheadRet:
-
-;;; Restore the stack and return from whence we came.
-
-        add esp, LocalVarsSize
-        pop ebx
-        pop esi
-        pop edi
-        pop ebp
-
-        ret
-; please don't remove this string !
-; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!
-    db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah
-
-
-IFDEF NOOLDPENTIUMCODE
-    IFDEF NOUNDERLINE
-    longest_match       endp
-    ELSE
-    _longest_match      endp
-    ENDIF
-
-    IFDEF NOUNDERLINE
-    match_init      proc near
-                    ret
-    match_init      endp
-    ELSE
-    _match_init     proc near
-                    ret
-    _match_init     endp
-    ENDIF    
-ELSE
-    IFDEF NOUNDERLINE
-    longest_match_686   endp
-    ELSE
-    _longest_match_686  endp
-    ENDIF
-ENDIF
-
-_TEXT   ends
-end
diff --git a/third_party/zlib/contrib/masmx86/gvmat32c.c b/third_party/zlib/contrib/masmx86/gvmat32c.c
deleted file mode 100644
index 7ad2b27..0000000
--- a/third_party/zlib/contrib/masmx86/gvmat32c.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86
- * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
- * File written by Gilles Vollant, by modifiying the longest_match
- *  from Jean-loup Gailly in deflate.c
- *  it prepare all parameters and call the assembly longest_match_gvasm
- *  longest_match execute standard C code is wmask != 0x7fff
- *     (assembly code is faster with a fixed wmask)
- *
- * Read comment at beginning of gvmat32.asm for more information
- */
-
-#if defined(ASMV) && (!defined(NOOLDPENTIUMCODE))
-#include "deflate.h"
-
-/* if your C compiler don't add underline before function name,
-        define ADD_UNDERLINE_ASMFUNC */
-#ifdef ADD_UNDERLINE_ASMFUNC
-#define longest_match_7fff _longest_match_7fff
-#define longest_match_686  _longest_match_686
-#define cpudetect32        _cpudetect32
-#endif
-
-
-unsigned long cpudetect32();
-
-uInt longest_match_c(
-    deflate_state *s,
-    IPos cur_match);                             /* current match */
-
-
-uInt longest_match_7fff(
-    deflate_state *s,
-    IPos cur_match);                             /* current match */
-
-uInt longest_match_686(
-    deflate_state *s,
-    IPos cur_match);                             /* current match */
-
-
-static uInt iIsPPro=2;
-
-void match_init ()
-{
-    iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
-}
-
-uInt longest_match(
-    deflate_state *s,
-    IPos cur_match)                             /* current match */
-{
-    if (iIsPPro!=0)
-        return longest_match_686(s,cur_match);
-
-    if (s->w_mask != 0x7fff)
-        return longest_match_686(s,cur_match);
-
-    /* now ((s->w_mask == 0x7fff) && (iIsPPro==0)) */
-        return longest_match_7fff(s,cur_match);
-}
-
-
-#endif /* defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) */
diff --git a/third_party/zlib/contrib/masmx86/inffas32.asm b/third_party/zlib/contrib/masmx86/inffas32.asm
index 4a20512..03d20f8 100644
--- a/third_party/zlib/contrib/masmx86/inffas32.asm
+++ b/third_party/zlib/contrib/masmx86/inffas32.asm
@@ -16,7 +16,7 @@
 ; * enabled.  I will attempt to merge the MMX code into this version.  Newer
 ; * versions of this and inffast.S can be found at
 ; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/
-; * 
+; *
 ; * 2005 : modification by Gilles Vollant
 ; */
 ; For Visual C++ 4.x and higher and ML 6.x and higher
@@ -33,7 +33,7 @@
 
 
 ; zlib122sup is 0 fort zlib 1.2.2.1 and lower
-; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head 
+; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head
 ;        in inflate_state in inflate.h)
 zlib1222sup      equ    8
 
@@ -73,11 +73,6 @@ inflate_fast_use_mmx:
 
 
 _TEXT			segment
-PUBLIC _inflate_fast
-
-ALIGN 4
-_inflate_fast:
-	jmp inflate_fast_entry
 
 
 
@@ -163,7 +158,8 @@ distbits_state	 equ	(76+4+zlib1222sup)	;/* state->distbits */
 ;SECTION .text
 
 ALIGN 4
-inflate_fast_entry:
+_inflate_fast proc near
+.FPO (16, 4, 0, 0, 1, 0)
 	push  edi
 	push  esi
 	push  ebp
@@ -644,9 +640,9 @@ L_init_mmx:
 	movd mm0,ebp
 	mov  ebp,ebx
 ; 896 "inffast.S"
-	movd mm4,[esp+0]
+	movd mm4,dword ptr [esp+0]
 	movq mm3,mm4
-	movd mm5,[esp+4]
+	movd mm5,dword ptr [esp+4]
 	movq mm2,mm5
 	pxor mm1,mm1
 	mov  ebx, [esp+8]
@@ -660,7 +656,7 @@ L_do_loop_mmx:
 	ja  L_get_length_code_mmx
 
 	movd mm6,ebp
-	movd mm7,[esi]
+	movd mm7,dword ptr [esi]
 	add  esi,4
 	psllq mm7,mm6
 	add  ebp,32
@@ -717,7 +713,7 @@ L_decode_distance_mmx:
 	ja L_get_dist_code_mmx
 
 	movd mm6,ebp
-	movd mm7,[esi]
+	movd mm7,dword ptr [esi]
 	add  esi,4
 	psllq mm7,mm6
 	add  ebp,32
@@ -1078,6 +1074,7 @@ L_done:
 	pop  esi
 	pop  edi
 	ret
+_inflate_fast endp
 
 _TEXT	ends
 end
diff --git a/third_party/zlib/contrib/masmx86/mkasm.bat b/third_party/zlib/contrib/masmx86/mkasm.bat
deleted file mode 100755
index 70a51f8..0000000
--- a/third_party/zlib/contrib/masmx86/mkasm.bat
+++ /dev/null
@@ -1,3 +0,0 @@
-cl /DASMV /I..\.. /O2 /c gvmat32c.c
-ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm
-ml /coff /Zi /c /Flinffas32.lst inffas32.asm
diff --git a/third_party/zlib/contrib/masmx86/readme.txt b/third_party/zlib/contrib/masmx86/readme.txt
index 7b57167..3271f72 100644
--- a/third_party/zlib/contrib/masmx86/readme.txt
+++ b/third_party/zlib/contrib/masmx86/readme.txt
@@ -1,21 +1,27 @@
-
-Summary
--------
-This directory contains ASM implementations of the functions
-longest_match() and inflate_fast().
-
-
-Use instructions
-----------------
-Copy these files into the zlib source directory, then run the
-appropriate makefile, as suggested below.
-
-
-Build instructions
-------------------
-* With Microsoft C and MASM:
-nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="gvmat32c.obj gvmat32.obj inffas32.obj"
-
-* With Borland C and TASM:
-make -f win32/Makefile.bor LOCAL_ZLIB="-DASMV -DASMINF" OBJA="gvmat32c.obj gvmat32.obj inffas32.obj" OBJPA="+gvmat32c.obj+gvmat32.obj+inffas32.obj"
-
+
+Summary
+-------
+This directory contains ASM implementations of the functions
+longest_match() and inflate_fast().
+
+
+Use instructions
+----------------
+Assemble using MASM, and copy the object files into the zlib source
+directory, then run the appropriate makefile, as suggested below.  You can
+donwload MASM from here:
+
+    http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64
+
+You can also get objects files here:
+
+    http://www.winimage.com/zLibDll/zlib124_masm_obj.zip
+
+Build instructions
+------------------
+* With Microsoft C and MASM:
+nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj"
+
+* With Borland C and TASM:
+make -f win32/Makefile.bor LOCAL_ZLIB="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj" OBJPA="+match686c.obj+match686.obj+inffas32.obj"
+
diff --git a/third_party/zlib/contrib/minizip/ChangeLogUnzip b/third_party/zlib/contrib/minizip/ChangeLogUnzip
deleted file mode 100644
index 50ca6a9..0000000
--- a/third_party/zlib/contrib/minizip/ChangeLogUnzip
+++ /dev/null
@@ -1,67 +0,0 @@
-Change in 1.01e (12 feb 05)
-- Fix in zipOpen2 for globalcomment (Rolf Kalbermatter)
-- Fix possible memory leak in unzip.c (Zoran Stevanovic)
-
-Change in 1.01b (20 may 04)
-- Integrate patch from Debian package (submited by Mark Brown)
-- Add tools mztools from Xavier Roche
-
-Change in 1.01 (8 may 04)
-- fix buffer overrun risk in unzip.c (Xavier Roche)
-- fix a minor buffer insecurity in minizip.c (Mike Whittaker)
-
-Change in 1.00: (10 sept 03)
-- rename to 1.00
-- cosmetic code change
-
-Change in 0.22: (19 May 03)
-- crypting support (unless you define NOCRYPT)
-- append file in existing zipfile
-
-Change in 0.21: (10 Mar 03)
-- bug fixes
-
-Change in 0.17: (27 Jan 02)
-- bug fixes
-
-Change in 0.16: (19 Jan 02)
-- Support of ioapi for virtualize zip file access
-
-Change in 0.15: (19 Mar 98)
-- fix memory leak in minizip.c
-
-Change in 0.14: (10 Mar 98)
-- fix bugs in minizip.c sample for zipping big file
-- fix problem in month in date handling
-- fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for
-    comment handling
-
-Change in 0.13: (6 Mar 98)
-- fix bugs in zip.c
-- add real minizip sample
-
-Change in 0.12: (4 Mar 98)
-- add zip.c and zip.h for creates .zip file
-- fix change_file_date in miniunz.c for Unix (Jean-loup Gailly)
-- fix miniunz.c for file without specific record for directory
-
-Change in 0.11: (3 Mar 98)
-- fix bug in unzGetCurrentFileInfo for get extra field and comment
-- enhance miniunz sample, remove the bad unztst.c sample
-
-Change in 0.10: (2 Mar 98)
-- fix bug in unzReadCurrentFile
-- rename unzip* to unz* function and structure
-- remove Windows-like hungary notation variable name
-- modify some structure in unzip.h
-- add somes comment in source
-- remove unzipGetcCurrentFile function
-- replace ZUNZEXPORT by ZEXPORT
-- add unzGetLocalExtrafield for get the local extrafield info
-- add a new sample, miniunz.c
-
-Change in 0.4: (25 Feb 98)
-- suppress the type unzipFileInZip.
-  Only on file in the zipfile can be open at the same time
-- fix somes typo in code
-- added tm_unz structure in unzip_file_info (date/time in readable format)
diff --git a/third_party/zlib/contrib/minizip/crypt.h b/third_party/zlib/contrib/minizip/crypt.h
index 622f4bc..1e9e820 100644
--- a/third_party/zlib/contrib/minizip/crypt.h
+++ b/third_party/zlib/contrib/minizip/crypt.h
@@ -32,7 +32,7 @@
 /***********************************************************************
  * Return the next byte in the pseudo-random sequence
  */
-static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
+static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab)
 {
     unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an
                      * unpredictable manner on 16-bit systems; not a problem
@@ -45,7 +45,7 @@ static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
 /***********************************************************************
  * Update the encryption keys with the next byte of plain text
  */
-static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
+static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c)
 {
     (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
     (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
@@ -62,7 +62,7 @@ static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int
  * Initialize the encryption keys and the random header according to
  * the given password.
  */
-static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
+static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab)
 {
     *(pkeys+0) = 305419896L;
     *(pkeys+1) = 591751049L;
@@ -87,13 +87,12 @@ static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned lon
 #    define ZCR_SEED2 3141592654UL     /* use PI as default pattern */
 #  endif
 
-static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
-    const char *passwd;         /* password string */
-    unsigned char *buf;         /* where to write header */
-    int bufSize;
-    unsigned long* pkeys;
-    const unsigned long* pcrc_32_tab;
-    unsigned long crcForCrypting;
+static int crypthead(const char* passwd,      /* password string */
+                     unsigned char* buf,      /* where to write header */
+                     int bufSize,
+                     unsigned long* pkeys,
+                     const z_crc_t* pcrc_32_tab,
+                     unsigned long crcForCrypting)
 {
     int n;                       /* index in random header */
     int t;                       /* temporary */
@@ -124,8 +123,8 @@ static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
     {
         buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
     }
-    buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
-    buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
+    buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
+    buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
     return n;
 }
 
diff --git a/third_party/zlib/contrib/minizip/ioapi.c b/third_party/zlib/contrib/minizip/ioapi.c
index f1bee23..7f5c191 100644
--- a/third_party/zlib/contrib/minizip/ioapi.c
+++ b/third_party/zlib/contrib/minizip/ioapi.c
@@ -1,74 +1,98 @@
-/* ioapi.c -- IO base function header for compress/uncompress .zip
-   files using zlib + zip or unzip API
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
 
-   Version 1.01e, February 12th, 2005
-
-   Copyright (C) 1998-2005 Gilles Vollant
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "zlib.h"
-#include "ioapi.h"
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
 
+         Modifications for Zip64 support
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
 
+         For more info read MiniZip_info.txt
 
-/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+*/
 
-#ifndef SEEK_CUR
-#define SEEK_CUR    1
+#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS)))
+        #define _CRT_SECURE_NO_WARNINGS
 #endif
 
-#ifndef SEEK_END
-#define SEEK_END    2
+#if defined(__APPLE__) || defined(IOAPI_NO_64)
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
 #endif
 
-#ifndef SEEK_SET
-#define SEEK_SET    0
-#endif
 
-voidpf ZCALLBACK fopen_file_func OF((
-   voidpf opaque,
-   const char* filename,
-   int mode));
+#include "ioapi.h"
 
-uLong ZCALLBACK fread_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   void* buf,
-   uLong size));
+voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
+{
+    if (pfilefunc->zfile_func64.zopen64_file != NULL)
+        return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode);
+    else
+    {
+        return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode);
+    }
+}
 
-uLong ZCALLBACK fwrite_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   const void* buf,
-   uLong size));
+long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)
+{
+    if (pfilefunc->zfile_func64.zseek64_file != NULL)
+        return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
+    else
+    {
+        uLong offsetTruncated = (uLong)offset;
+        if (offsetTruncated != offset)
+            return -1;
+        else
+            return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);
+    }
+}
 
-long ZCALLBACK ftell_file_func OF((
-   voidpf opaque,
-   voidpf stream));
+ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)
+{
+    if (pfilefunc->zfile_func64.zseek64_file != NULL)
+        return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
+    else
+    {
+        uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
+        if ((tell_uLong) == MAXU32)
+            return (ZPOS64_T)-1;
+        else
+            return tell_uLong;
+    }
+}
 
-long ZCALLBACK fseek_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   uLong offset,
-   int origin));
+void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)
+{
+    p_filefunc64_32->zfile_func64.zopen64_file = NULL;
+    p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
+    p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
+    p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
+    p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
+    p_filefunc64_32->zfile_func64.ztell64_file = NULL;
+    p_filefunc64_32->zfile_func64.zseek64_file = NULL;
+    p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
+    p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
+    p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
+    p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
+    p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
+}
 
-int ZCALLBACK fclose_file_func OF((
-   voidpf opaque,
-   voidpf stream));
 
-int ZCALLBACK ferror_file_func OF((
-   voidpf opaque,
-   voidpf stream));
 
+static voidpf  ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));
+static uLong   ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+static uLong   ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size));
+static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream));
+static long    ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
+static int     ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream));
+static int     ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream));
 
-voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
-   voidpf opaque;
-   const char* filename;
-   int mode;
+static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode)
 {
     FILE* file = NULL;
     const char* mode_fopen = NULL;
@@ -86,44 +110,55 @@ voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
     return file;
 }
 
+static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode)
+{
+    FILE* file = NULL;
+    const char* mode_fopen = NULL;
+    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+        mode_fopen = "rb";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+        mode_fopen = "r+b";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+        mode_fopen = "wb";
+
+    if ((filename!=NULL) && (mode_fopen != NULL))
+        file = FOPEN_FUNC((const char*)filename, mode_fopen);
+    return file;
+}
+
 
-uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
-   voidpf opaque;
-   voidpf stream;
-   void* buf;
-   uLong size;
+static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
 {
     uLong ret;
     ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
     return ret;
 }
 
-
-uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
-   voidpf opaque;
-   voidpf stream;
-   const void* buf;
-   uLong size;
+static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)
 {
     uLong ret;
     ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
     return ret;
 }
 
-long ZCALLBACK ftell_file_func (opaque, stream)
-   voidpf opaque;
-   voidpf stream;
+static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
 {
     long ret;
     ret = ftell((FILE *)stream);
     return ret;
 }
 
-long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
-   voidpf opaque;
-   voidpf stream;
-   uLong offset;
-   int origin;
+
+static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
+{
+    ZPOS64_T ret;
+    ret = FTELLO_FUNC((FILE *)stream);
+    return ret;
+}
+
+static long ZCALLBACK fseek_file_func (voidpf  opaque, voidpf stream, uLong offset, int origin)
 {
     int fseek_origin=0;
     long ret;
@@ -141,22 +176,45 @@ long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
     default: return -1;
     }
     ret = 0;
-    fseek((FILE *)stream, offset, fseek_origin);
+    if (fseek((FILE *)stream, offset, fseek_origin) != 0)
+        ret = -1;
     return ret;
 }
 
-int ZCALLBACK fclose_file_func (opaque, stream)
-   voidpf opaque;
-   voidpf stream;
+static long ZCALLBACK fseek64_file_func (voidpf  opaque, voidpf stream, ZPOS64_T offset, int origin)
+{
+    int fseek_origin=0;
+    long ret;
+    switch (origin)
+    {
+    case ZLIB_FILEFUNC_SEEK_CUR :
+        fseek_origin = SEEK_CUR;
+        break;
+    case ZLIB_FILEFUNC_SEEK_END :
+        fseek_origin = SEEK_END;
+        break;
+    case ZLIB_FILEFUNC_SEEK_SET :
+        fseek_origin = SEEK_SET;
+        break;
+    default: return -1;
+    }
+    ret = 0;
+
+    if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0)
+                        ret = -1;
+
+    return ret;
+}
+
+
+static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
 {
     int ret;
     ret = fclose((FILE *)stream);
     return ret;
 }
 
-int ZCALLBACK ferror_file_func (opaque, stream)
-   voidpf opaque;
-   voidpf stream;
+static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
 {
     int ret;
     ret = ferror((FILE *)stream);
@@ -175,3 +233,15 @@ void fill_fopen_filefunc (pzlib_filefunc_def)
     pzlib_filefunc_def->zerror_file = ferror_file_func;
     pzlib_filefunc_def->opaque = NULL;
 }
+
+void fill_fopen64_filefunc (zlib_filefunc64_def*  pzlib_filefunc_def)
+{
+    pzlib_filefunc_def->zopen64_file = fopen64_file_func;
+    pzlib_filefunc_def->zread_file = fread_file_func;
+    pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+    pzlib_filefunc_def->ztell64_file = ftell64_file_func;
+    pzlib_filefunc_def->zseek64_file = fseek64_file_func;
+    pzlib_filefunc_def->zclose_file = fclose_file_func;
+    pzlib_filefunc_def->zerror_file = ferror_file_func;
+    pzlib_filefunc_def->opaque = NULL;
+}
diff --git a/third_party/zlib/contrib/minizip/ioapi.h b/third_party/zlib/contrib/minizip/ioapi.h
index 7d457ba..8dcbdb0 100644
--- a/third_party/zlib/contrib/minizip/ioapi.h
+++ b/third_party/zlib/contrib/minizip/ioapi.h
@@ -1,13 +1,112 @@
 /* ioapi.h -- IO base function header for compress/uncompress .zip
-   files using zlib + zip or unzip API
+   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
 
-   Version 1.01e, February 12th, 2005
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications for Zip64 support
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+         For more info read MiniZip_info.txt
+
+         Changes
+
+    Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
+    Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
+               More if/def section may be needed to support other platforms
+    Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
+                          (but you should use iowin32.c for windows instead)
 
-   Copyright (C) 1998-2005 Gilles Vollant
 */
 
-#ifndef _ZLIBIOAPI_H
-#define _ZLIBIOAPI_H
+#ifndef _ZLIBIOAPI64_H
+#define _ZLIBIOAPI64_H
+
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
+
+  // Linux needs this to support file operation on files larger then 4+GB
+  // But might need better if/def to select just the platforms that needs them.
+
+        #ifndef __USE_FILE_OFFSET64
+                #define __USE_FILE_OFFSET64
+        #endif
+        #ifndef __USE_LARGEFILE64
+                #define __USE_LARGEFILE64
+        #endif
+        #ifndef _LARGEFILE64_SOURCE
+                #define _LARGEFILE64_SOURCE
+        #endif
+        #ifndef _FILE_OFFSET_BIT
+                #define _FILE_OFFSET_BIT 64
+        #endif
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "zlib.h"
+
+#if defined(USE_FILE32API)
+#define fopen64 fopen
+#define ftello64 ftell
+#define fseeko64 fseek
+#else
+#ifdef __FreeBSD__
+#define fopen64 fopen
+#define ftello64 ftello
+#define fseeko64 fseeko
+#endif
+#ifdef _MSC_VER
+ #define fopen64 fopen
+ #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
+  #define ftello64 _ftelli64
+  #define fseeko64 _fseeki64
+ #else // old MSC
+  #define ftello64 ftell
+  #define fseeko64 fseek
+ #endif
+#endif
+#endif
+
+/*
+#ifndef ZPOS64_T
+  #ifdef _WIN32
+                #define ZPOS64_T fpos_t
+  #else
+    #include <stdint.h>
+    #define ZPOS64_T uint64_t
+  #endif
+#endif
+*/
+
+#ifdef HAVE_MINIZIP64_CONF_H
+#include "mz64conf.h"
+#endif
+
+/* a type choosen by DEFINE */
+#ifdef HAVE_64BIT_INT_CUSTOM
+typedef  64BIT_INT_CUSTOM_TYPE ZPOS64_T;
+#else
+#ifdef HAS_STDINT_H
+#include "stdint.h"
+typedef uint64_t ZPOS64_T;
+#else
+
+/* Maximum unsigned 32-bit value used as placeholder for zip64 */
+#define MAXU32 0xffffffff
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef unsigned __int64 ZPOS64_T;
+#else
+typedef unsigned long long int ZPOS64_T;
+#endif
+#endif
+#endif
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 
 #define ZLIB_FILEFUNC_SEEK_CUR (1)
@@ -23,26 +122,27 @@
 
 
 #ifndef ZCALLBACK
-
-#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
-#define ZCALLBACK CALLBACK
-#else
-#define ZCALLBACK
-#endif
+ #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
+   #define ZCALLBACK CALLBACK
+ #else
+   #define ZCALLBACK
+ #endif
 #endif
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
-typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
-typedef uLong  (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
-typedef uLong  (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
-typedef long   (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
-typedef long   (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
-typedef int    (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
-typedef int    (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
 
+
+typedef voidpf   (ZCALLBACK *open_file_func)      OF((voidpf opaque, const char* filename, int mode));
+typedef uLong    (ZCALLBACK *read_file_func)      OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+typedef uLong    (ZCALLBACK *write_file_func)     OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+typedef int      (ZCALLBACK *close_file_func)     OF((voidpf opaque, voidpf stream));
+typedef int      (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
+
+typedef long     (ZCALLBACK *tell_file_func)      OF((voidpf opaque, voidpf stream));
+typedef long     (ZCALLBACK *seek_file_func)      OF((voidpf opaque, voidpf stream, uLong offset, int origin));
+
+
+/* here is the "old" 32 bits structure structure */
 typedef struct zlib_filefunc_def_s
 {
     open_file_func      zopen_file;
@@ -55,21 +155,54 @@ typedef struct zlib_filefunc_def_s
     voidpf              opaque;
 } zlib_filefunc_def;
 
+typedef ZPOS64_T (ZCALLBACK *tell64_file_func)    OF((voidpf opaque, voidpf stream));
+typedef long     (ZCALLBACK *seek64_file_func)    OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
+typedef voidpf   (ZCALLBACK *open64_file_func)    OF((voidpf opaque, const void* filename, int mode));
 
+typedef struct zlib_filefunc64_def_s
+{
+    open64_file_func    zopen64_file;
+    read_file_func      zread_file;
+    write_file_func     zwrite_file;
+    tell64_file_func    ztell64_file;
+    seek64_file_func    zseek64_file;
+    close_file_func     zclose_file;
+    testerror_file_func zerror_file;
+    voidpf              opaque;
+} zlib_filefunc64_def;
 
+void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
 void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
 
-#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
-#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
-#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
-#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
-#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
-#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
+/* now internal definition, only for zip.c and unzip.h */
+typedef struct zlib_filefunc64_32_def_s
+{
+    zlib_filefunc64_def zfile_func64;
+    open_file_func      zopen32_file;
+    tell_file_func      ztell32_file;
+    seek_file_func      zseek32_file;
+} zlib_filefunc64_32_def;
+
+
+#define ZREAD64(filefunc,filestream,buf,size)     ((*((filefunc).zfile_func64.zread_file))   ((filefunc).zfile_func64.opaque,filestream,buf,size))
+#define ZWRITE64(filefunc,filestream,buf,size)    ((*((filefunc).zfile_func64.zwrite_file))  ((filefunc).zfile_func64.opaque,filestream,buf,size))
+//#define ZTELL64(filefunc,filestream)            ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
+//#define ZSEEK64(filefunc,filestream,pos,mode)   ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))
+#define ZCLOSE64(filefunc,filestream)             ((*((filefunc).zfile_func64.zclose_file))  ((filefunc).zfile_func64.opaque,filestream))
+#define ZERROR64(filefunc,filestream)             ((*((filefunc).zfile_func64.zerror_file))  ((filefunc).zfile_func64.opaque,filestream))
 
+voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode));
+long    call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin));
+ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream));
+
+void    fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
+
+#define ZOPEN64(filefunc,filename,mode)         (call_zopen64((&(filefunc)),(filename),(mode)))
+#define ZTELL64(filefunc,filestream)            (call_ztell64((&(filefunc)),(filestream)))
+#define ZSEEK64(filefunc,filestream,pos,mode)   (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
-
diff --git a/third_party/zlib/contrib/minizip/iowin32.c b/third_party/zlib/contrib/minizip/iowin32.c
index a9b5f78..a46d96c 100644
--- a/third_party/zlib/contrib/minizip/iowin32.c
+++ b/third_party/zlib/contrib/minizip/iowin32.c
@@ -1,10 +1,14 @@
 /* iowin32.c -- IO base function header for compress/uncompress .zip
-   files using zlib + zip or unzip API
-   This IO API version uses the Win32 API (for Microsoft Windows)
+     Version 1.1, February 14h, 2010
+     part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
 
-   Version 1.01e, February 12th, 2005
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications for Zip64 support
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+     For more info read MiniZip_info.txt
 
-   Copyright (C) 1998-2005 Gilles Vollant
 */
 
 #include <stdlib.h>
@@ -21,40 +25,20 @@
 #define INVALID_SET_FILE_POINTER ((DWORD)-1)
 #endif
 
-voidpf ZCALLBACK win32_open_file_func OF((
-   voidpf opaque,
-   const char* filename,
-   int mode));
-
-uLong ZCALLBACK win32_read_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   void* buf,
-   uLong size));
-
-uLong ZCALLBACK win32_write_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   const void* buf,
-   uLong size));
-
-long ZCALLBACK win32_tell_file_func OF((
-   voidpf opaque,
-   voidpf stream));
-
-long ZCALLBACK win32_seek_file_func OF((
-   voidpf opaque,
-   voidpf stream,
-   uLong offset,
-   int origin));
-
-int ZCALLBACK win32_close_file_func OF((
-   voidpf opaque,
-   voidpf stream));
-
-int ZCALLBACK win32_error_file_func OF((
-   voidpf opaque,
-   voidpf stream));
+
+#if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API)))
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+#define IOWIN32_USING_WINRT_API 1
+#endif
+#endif
+
+voidpf  ZCALLBACK win32_open_file_func  OF((voidpf opaque, const char* filename, int mode));
+uLong   ZCALLBACK win32_read_file_func  OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+uLong   ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+ZPOS64_T ZCALLBACK win32_tell64_file_func  OF((voidpf opaque, voidpf stream));
+long    ZCALLBACK win32_seek64_file_func  OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
+int     ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream));
+int     ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream));
 
 typedef struct
 {
@@ -62,69 +46,163 @@ typedef struct
     int error;
 } WIN32FILE_IOWIN;
 
-voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode)
-   voidpf opaque;
-   const char* filename;
-   int mode;
-{
-    const char* mode_fopen = NULL;
-    DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
-    HANDLE hFile = 0;
-    voidpf ret=NULL;
 
-    dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0;
+static void win32_translate_open_mode(int mode,
+                                      DWORD* lpdwDesiredAccess,
+                                      DWORD* lpdwCreationDisposition,
+                                      DWORD* lpdwShareMode,
+                                      DWORD* lpdwFlagsAndAttributes)
+{
+    *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0;
 
     if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
     {
-        dwDesiredAccess = GENERIC_READ;
-        dwCreationDisposition = OPEN_EXISTING;
-        dwShareMode = FILE_SHARE_READ;
+        *lpdwDesiredAccess = GENERIC_READ;
+        *lpdwCreationDisposition = OPEN_EXISTING;
+        *lpdwShareMode = FILE_SHARE_READ;
     }
-    else
-    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+    else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
     {
-        dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
-        dwCreationDisposition = OPEN_EXISTING;
+        *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
+        *lpdwCreationDisposition = OPEN_EXISTING;
     }
-    else
-    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+    else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
     {
-        dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
-        dwCreationDisposition = CREATE_ALWAYS;
+        *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
+        *lpdwCreationDisposition = CREATE_ALWAYS;
     }
+}
 
-    if ((filename!=NULL) && (dwDesiredAccess != 0))
-        hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL,
-                      dwCreationDisposition, dwFlagsAndAttributes, NULL);
-
-    if (hFile == INVALID_HANDLE_VALUE)
-        hFile = NULL;
+static voidpf win32_build_iowin(HANDLE hFile)
+{
+    voidpf ret=NULL;
 
-    if (hFile != NULL)
+    if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
     {
         WIN32FILE_IOWIN w32fiow;
         w32fiow.hf = hFile;
         w32fiow.error = 0;
         ret = malloc(sizeof(WIN32FILE_IOWIN));
+
         if (ret==NULL)
             CloseHandle(hFile);
-        else *((WIN32FILE_IOWIN*)ret) = w32fiow;
+        else
+            *((WIN32FILE_IOWIN*)ret) = w32fiow;
     }
     return ret;
 }
 
+voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int mode)
+{
+    const char* mode_fopen = NULL;
+    DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
+    HANDLE hFile = NULL;
+
+    win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);
+
+#ifdef IOWIN32_USING_WINRT_API
+#ifdef UNICODE
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+        hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
+#else
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+    {
+        WCHAR filenameW[FILENAME_MAX + 0x200 + 1];
+        MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200);
+        hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
+    }
+#endif
+#else
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+        hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
+#endif
+
+    return win32_build_iowin(hFile);
+}
+
+
+voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int mode)
+{
+    const char* mode_fopen = NULL;
+    DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
+    HANDLE hFile = NULL;
+
+    win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);
+
+#ifdef IOWIN32_USING_WINRT_API
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+    {
+        WCHAR filenameW[FILENAME_MAX + 0x200 + 1];
+        MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200);
+        hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
+    }
+#else
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+        hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
+#endif
+
+    return win32_build_iowin(hFile);
+}
+
 
-uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size)
-   voidpf opaque;
-   voidpf stream;
-   void* buf;
-   uLong size;
+voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int mode)
+{
+    const char* mode_fopen = NULL;
+    DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
+    HANDLE hFile = NULL;
+
+    win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);
+
+#ifdef IOWIN32_USING_WINRT_API
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+        hFile = CreateFile2((LPCWSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition,NULL);
+#else
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+        hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
+#endif
+
+    return win32_build_iowin(hFile);
+}
+
+
+voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mode)
+{
+    const char* mode_fopen = NULL;
+    DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
+    HANDLE hFile = NULL;
+
+    win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);
+
+#ifdef IOWIN32_USING_WINRT_API
+#ifdef UNICODE
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+        hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
+#else
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+    {
+        WCHAR filenameW[FILENAME_MAX + 0x200 + 1];
+        MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200);
+        hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
+    }
+#endif
+#else
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+        hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
+#endif
+
+    return win32_build_iowin(hFile);
+}
+
+
+uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size)
 {
     uLong ret=0;
     HANDLE hFile = NULL;
     if (stream!=NULL)
         hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+
     if (hFile != NULL)
+    {
         if (!ReadFile(hFile, buf, size, &ret, NULL))
         {
             DWORD dwErr = GetLastError();
@@ -132,23 +210,21 @@ uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size)
                 dwErr = 0;
             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
         }
+    }
 
     return ret;
 }
 
 
-uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size)
-   voidpf opaque;
-   voidpf stream;
-   const void* buf;
-   uLong size;
+uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size)
 {
     uLong ret=0;
     HANDLE hFile = NULL;
     if (stream!=NULL)
         hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
 
-    if (hFile !=NULL)
+    if (hFile != NULL)
+    {
         if (!WriteFile(hFile, buf, size, &ret, NULL))
         {
             DWORD dwErr = GetLastError();
@@ -156,13 +232,32 @@ uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size)
                 dwErr = 0;
             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
         }
+    }
 
     return ret;
 }
 
-long ZCALLBACK win32_tell_file_func (opaque, stream)
-   voidpf opaque;
-   voidpf stream;
+static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos,  DWORD dwMoveMethod)
+{
+#ifdef IOWIN32_USING_WINRT_API
+    return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod);
+#else
+    LONG lHigh = pos.HighPart;
+    DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, FILE_CURRENT);
+    BOOL fOk = TRUE;
+    if (dwNewPos == 0xFFFFFFFF)
+        if (GetLastError() != NO_ERROR)
+            fOk = FALSE;
+    if ((newPos != NULL) && (fOk))
+    {
+        newPos->LowPart = dwNewPos;
+        newPos->HighPart = lHigh;
+    }
+    return fOk;
+#endif
+}
+
+long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream)
 {
     long ret=-1;
     HANDLE hFile = NULL;
@@ -170,24 +265,47 @@ long ZCALLBACK win32_tell_file_func (opaque, stream)
         hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
     if (hFile != NULL)
     {
-        DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
-        if (dwSet == INVALID_SET_FILE_POINTER)
+        LARGE_INTEGER pos;
+        pos.QuadPart = 0;
+
+        if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT))
         {
             DWORD dwErr = GetLastError();
             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
             ret = -1;
         }
         else
-            ret=(long)dwSet;
+            ret=(long)pos.LowPart;
     }
     return ret;
 }
 
-long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin)
-   voidpf opaque;
-   voidpf stream;
-   uLong offset;
-   int origin;
+ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream)
+{
+    ZPOS64_T ret= (ZPOS64_T)-1;
+    HANDLE hFile = NULL;
+    if (stream!=NULL)
+        hFile = ((WIN32FILE_IOWIN*)stream)->hf;
+
+    if (hFile)
+    {
+        LARGE_INTEGER pos;
+        pos.QuadPart = 0;
+
+        if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT))
+        {
+            DWORD dwErr = GetLastError();
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+            ret = (ZPOS64_T)-1;
+        }
+        else
+            ret=pos.QuadPart;
+    }
+    return ret;
+}
+
+
+long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,int origin)
 {
     DWORD dwMoveMethod=0xFFFFFFFF;
     HANDLE hFile = NULL;
@@ -211,8 +329,9 @@ long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin)
 
     if (hFile != NULL)
     {
-        DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod);
-        if (dwSet == INVALID_SET_FILE_POINTER)
+        LARGE_INTEGER pos;
+        pos.QuadPart = offset;
+        if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod))
         {
             DWORD dwErr = GetLastError();
             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
@@ -224,9 +343,46 @@ long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin)
     return ret;
 }
 
-int ZCALLBACK win32_close_file_func (opaque, stream)
-   voidpf opaque;
-   voidpf stream;
+long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin)
+{
+    DWORD dwMoveMethod=0xFFFFFFFF;
+    HANDLE hFile = NULL;
+    long ret=-1;
+
+    if (stream!=NULL)
+        hFile = ((WIN32FILE_IOWIN*)stream)->hf;
+
+    switch (origin)
+    {
+        case ZLIB_FILEFUNC_SEEK_CUR :
+            dwMoveMethod = FILE_CURRENT;
+            break;
+        case ZLIB_FILEFUNC_SEEK_END :
+            dwMoveMethod = FILE_END;
+            break;
+        case ZLIB_FILEFUNC_SEEK_SET :
+            dwMoveMethod = FILE_BEGIN;
+            break;
+        default: return -1;
+    }
+
+    if (hFile)
+    {
+        LARGE_INTEGER pos;
+        pos.QuadPart = offset;
+        if (!MySetFilePointerEx(hFile, pos, NULL, FILE_CURRENT))
+        {
+            DWORD dwErr = GetLastError();
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+            ret = -1;
+        }
+        else
+            ret=0;
+    }
+    return ret;
+}
+
+int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream)
 {
     int ret=-1;
 
@@ -244,9 +400,7 @@ int ZCALLBACK win32_close_file_func (opaque, stream)
     return ret;
 }
 
-int ZCALLBACK win32_error_file_func (opaque, stream)
-   voidpf opaque;
-   voidpf stream;
+int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream)
 {
     int ret=-1;
     if (stream!=NULL)
@@ -256,8 +410,7 @@ int ZCALLBACK win32_error_file_func (opaque, stream)
     return ret;
 }
 
-void fill_win32_filefunc (pzlib_filefunc_def)
-  zlib_filefunc_def* pzlib_filefunc_def;
+void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def)
 {
     pzlib_filefunc_def->zopen_file = win32_open_file_func;
     pzlib_filefunc_def->zread_file = win32_read_file_func;
@@ -266,5 +419,43 @@ void fill_win32_filefunc (pzlib_filefunc_def)
     pzlib_filefunc_def->zseek_file = win32_seek_file_func;
     pzlib_filefunc_def->zclose_file = win32_close_file_func;
     pzlib_filefunc_def->zerror_file = win32_error_file_func;
-    pzlib_filefunc_def->opaque=NULL;
+    pzlib_filefunc_def->opaque = NULL;
+}
+
+void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def)
+{
+    pzlib_filefunc_def->zopen64_file = win32_open64_file_func;
+    pzlib_filefunc_def->zread_file = win32_read_file_func;
+    pzlib_filefunc_def->zwrite_file = win32_write_file_func;
+    pzlib_filefunc_def->ztell64_file = win32_tell64_file_func;
+    pzlib_filefunc_def->zseek64_file = win32_seek64_file_func;
+    pzlib_filefunc_def->zclose_file = win32_close_file_func;
+    pzlib_filefunc_def->zerror_file = win32_error_file_func;
+    pzlib_filefunc_def->opaque = NULL;
+}
+
+
+void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def)
+{
+    pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA;
+    pzlib_filefunc_def->zread_file = win32_read_file_func;
+    pzlib_filefunc_def->zwrite_file = win32_write_file_func;
+    pzlib_filefunc_def->ztell64_file = win32_tell64_file_func;
+    pzlib_filefunc_def->zseek64_file = win32_seek64_file_func;
+    pzlib_filefunc_def->zclose_file = win32_close_file_func;
+    pzlib_filefunc_def->zerror_file = win32_error_file_func;
+    pzlib_filefunc_def->opaque = NULL;
+}
+
+
+void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def)
+{
+    pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW;
+    pzlib_filefunc_def->zread_file = win32_read_file_func;
+    pzlib_filefunc_def->zwrite_file = win32_write_file_func;
+    pzlib_filefunc_def->ztell64_file = win32_tell64_file_func;
+    pzlib_filefunc_def->zseek64_file = win32_seek64_file_func;
+    pzlib_filefunc_def->zclose_file = win32_close_file_func;
+    pzlib_filefunc_def->zerror_file = win32_error_file_func;
+    pzlib_filefunc_def->opaque = NULL;
 }
diff --git a/third_party/zlib/contrib/minizip/iowin32.h b/third_party/zlib/contrib/minizip/iowin32.h
index a3a437a..0ca0969 100644
--- a/third_party/zlib/contrib/minizip/iowin32.h
+++ b/third_party/zlib/contrib/minizip/iowin32.h
@@ -1,10 +1,14 @@
 /* iowin32.h -- IO base function header for compress/uncompress .zip
-   files using zlib + zip or unzip API
-   This IO API version uses the Win32 API (for Microsoft Windows)
+     Version 1.1, February 14h, 2010
+     part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
 
-   Version 1.01e, February 12th, 2005
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications for Zip64 support
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+         For more info read MiniZip_info.txt
 
-   Copyright (C) 1998-2005 Gilles Vollant
 */
 
 #include <windows.h>
@@ -15,6 +19,9 @@ extern "C" {
 #endif
 
 void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+void fill_win32_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def));
+void fill_win32_filefunc64A OF((zlib_filefunc64_def* pzlib_filefunc_def));
+void fill_win32_filefunc64W OF((zlib_filefunc64_def* pzlib_filefunc_def));
 
 #ifdef __cplusplus
 }
diff --git a/third_party/zlib/contrib/minizip/miniunz.c b/third_party/zlib/contrib/minizip/miniunz.c
index cf9a03b..3d65401 100644
--- a/third_party/zlib/contrib/minizip/miniunz.c
+++ b/third_party/zlib/contrib/minizip/miniunz.c
@@ -1,10 +1,43 @@
 /*
    miniunz.c
-   Version 1.01e, February 12th, 2005
+   Version 1.1, February 14h, 2010
+   sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
 
-   Copyright (C) 1998-2005 Gilles Vollant
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications of Unzip for Zip64
+         Copyright (C) 2007-2008 Even Rouault
+
+         Modifications for Zip64 support on both zip and unzip
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
 */
 
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
+        #ifndef __USE_FILE_OFFSET64
+                #define __USE_FILE_OFFSET64
+        #endif
+        #ifndef __USE_LARGEFILE64
+                #define __USE_LARGEFILE64
+        #endif
+        #ifndef _LARGEFILE64_SOURCE
+                #define _LARGEFILE64_SOURCE
+        #endif
+        #ifndef _FILE_OFFSET_BIT
+                #define _FILE_OFFSET_BIT 64
+        #endif
+#endif
+
+#ifdef __APPLE__
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -13,21 +46,22 @@
 #include <errno.h>
 #include <fcntl.h>
 
-#ifdef unix
-# include <unistd.h>
-# include <utime.h>
-#else
+#ifdef _WIN32
 # include <direct.h>
 # include <io.h>
+#else
+# include <unistd.h>
+# include <utime.h>
 #endif
 
+
 #include "unzip.h"
 
 #define CASESENSITIVITY (0)
 #define WRITEBUFFERSIZE (8192)
 #define MAXFILENAME (256)
 
-#ifdef WIN32
+#ifdef _WIN32
 #define USEWIN32IOAPI
 #include "iowin32.h"
 #endif
@@ -51,11 +85,11 @@ void change_file_date(filename,dosdate,tmu_date)
     uLong dosdate;
     tm_unz tmu_date;
 {
-#ifdef WIN32
+#ifdef _WIN32
   HANDLE hFile;
   FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
 
-  hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE,
+  hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE,
                       0,NULL,OPEN_EXISTING,0,NULL);
   GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
   DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
@@ -63,7 +97,7 @@ void change_file_date(filename,dosdate,tmu_date)
   SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
   CloseHandle(hFile);
 #else
-#ifdef unix
+#ifdef unix || __APPLE__
   struct utimbuf ut;
   struct tm newdate;
   newdate.tm_sec = tmu_date.tm_sec;
@@ -91,12 +125,12 @@ int mymkdir(dirname)
     const char* dirname;
 {
     int ret=0;
-#ifdef WIN32
-    ret = mkdir(dirname);
-#else
-#ifdef unix
+#ifdef _WIN32
+    ret = _mkdir(dirname);
+#elif unix
+    ret = mkdir (dirname,0775);
+#elif __APPLE__
     ret = mkdir (dirname,0775);
-#endif
 #endif
     return ret;
 }
@@ -112,6 +146,11 @@ int makedir (newdir)
     return 0;
 
   buffer = (char*)malloc(len+1);
+        if (buffer==NULL)
+        {
+                printf("Error allocating memory\n");
+                return UNZ_INTERNALERROR;
+        }
   strcpy(buffer,newdir);
 
   if (buffer[len-1] == '/') {
@@ -164,34 +203,61 @@ void do_help()
            "  -p  extract crypted file using password\n\n");
 }
 
+void Display64BitsSize(ZPOS64_T n, int size_char)
+{
+  /* to avoid compatibility problem , we do here the conversion */
+  char number[21];
+  int offset=19;
+  int pos_string = 19;
+  number[20]=0;
+  for (;;) {
+      number[offset]=(char)((n%10)+'0');
+      if (number[offset] != '0')
+          pos_string=offset;
+      n/=10;
+      if (offset==0)
+          break;
+      offset--;
+  }
+  {
+      int size_display_string = 19-pos_string;
+      while (size_char > size_display_string)
+      {
+          size_char--;
+          printf(" ");
+      }
+  }
+
+  printf("%s",&number[pos_string]);
+}
 
 int do_list(uf)
     unzFile uf;
 {
     uLong i;
-    unz_global_info gi;
+    unz_global_info64 gi;
     int err;
 
-    err = unzGetGlobalInfo (uf,&gi);
+    err = unzGetGlobalInfo64(uf,&gi);
     if (err!=UNZ_OK)
         printf("error %d with zipfile in unzGetGlobalInfo \n",err);
-    printf(" Length  Method   Size  Ratio   Date    Time   CRC-32     Name\n");
-    printf(" ------  ------   ----  -----   ----    ----   ------     ----\n");
+    printf("  Length  Method     Size Ratio   Date    Time   CRC-32     Name\n");
+    printf("  ------  ------     ---- -----   ----    ----   ------     ----\n");
     for (i=0;i<gi.number_entry;i++)
     {
         char filename_inzip[256];
-        unz_file_info file_info;
+        unz_file_info64 file_info;
         uLong ratio=0;
         const char *string_method;
         char charCrypt=' ';
-        err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+        err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
         if (err!=UNZ_OK)
         {
             printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
             break;
         }
         if (file_info.uncompressed_size>0)
-            ratio = (file_info.compressed_size*100)/file_info.uncompressed_size;
+            ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size);
 
         /* display a '*' if the file is crypted */
         if ((file_info.flag & 1) != 0)
@@ -211,12 +277,17 @@ int do_list(uf)
               string_method="Defl:F"; /* 2:fast , 3 : extra fast*/
         }
         else
+        if (file_info.compression_method==Z_BZIP2ED)
+        {
+              string_method="BZip2 ";
+        }
+        else
             string_method="Unkn. ";
 
-        printf("%7lu  %6s%c%7lu %3lu%%  %2.2lu-%2.2lu-%2.2lu  %2.2lu:%2.2lu  %8.8lx   %s\n",
-                file_info.uncompressed_size,string_method,
-                charCrypt,
-                file_info.compressed_size,
+        Display64BitsSize(file_info.uncompressed_size,7);
+        printf("  %6s%c",string_method,charCrypt);
+        Display64BitsSize(file_info.compressed_size,7);
+        printf(" %3lu%%  %2.2lu-%2.2lu-%2.2lu  %2.2lu:%2.2lu  %8.8lx   %s\n",
                 ratio,
                 (uLong)file_info.tmu_date.tm_mon + 1,
                 (uLong)file_info.tmu_date.tm_mday,
@@ -252,9 +323,9 @@ int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)
     void* buf;
     uInt size_buf;
 
-    unz_file_info file_info;
+    unz_file_info64 file_info;
     uLong ratio=0;
-    err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+    err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
 
     if (err!=UNZ_OK)
     {
@@ -306,7 +377,7 @@ int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)
         {
             char rep=0;
             FILE* ftestexist;
-            ftestexist = fopen(write_filename,"rb");
+            ftestexist = FOPEN_FUNC(write_filename,"rb");
             if (ftestexist!=NULL)
             {
                 fclose(ftestexist);
@@ -317,7 +388,7 @@ int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)
 
                     printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename);
                     ret = scanf("%1s",answer);
-                    if (ret != 1) 
+                    if (ret != 1)
                     {
                        exit(EXIT_FAILURE);
                     }
@@ -337,8 +408,7 @@ int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)
 
         if ((skip==0) && (err==UNZ_OK))
         {
-            fout=fopen(write_filename,"wb");
-
+            fout=FOPEN_FUNC(write_filename,"wb");
             /* some zipfile don't contain directory alone before file */
             if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
                                 (filename_withoutpath!=(char*)filename_inzip))
@@ -347,7 +417,7 @@ int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)
                 *(filename_withoutpath-1)='\0';
                 makedir(write_filename);
                 *(filename_withoutpath-1)=c;
-                fout=fopen(write_filename,"wb");
+                fout=FOPEN_FUNC(write_filename,"wb");
             }
 
             if (fout==NULL)
@@ -409,11 +479,11 @@ int do_extract(uf,opt_extract_without_path,opt_overwrite,password)
     const char* password;
 {
     uLong i;
-    unz_global_info gi;
+    unz_global_info64 gi;
     int err;
     FILE* fout=NULL;
 
-    err = unzGetGlobalInfo (uf,&gi);
+    err = unzGetGlobalInfo64(uf,&gi);
     if (err!=UNZ_OK)
         printf("error %d with zipfile in unzGetGlobalInfo \n",err);
 
@@ -470,6 +540,7 @@ int main(argc,argv)
     const char *password=NULL;
     char filename_try[MAXFILENAME+16] = "";
     int i;
+    int ret_value=0;
     int opt_do_list=0;
     int opt_do_extract=1;
     int opt_do_extract_withoutpath=0;
@@ -532,26 +603,26 @@ int main(argc,argv)
     {
 
 #        ifdef USEWIN32IOAPI
-        zlib_filefunc_def ffunc;
+        zlib_filefunc64_def ffunc;
 #        endif
 
         strncpy(filename_try, zipfilename,MAXFILENAME-1);
-        /* strncpy doesn't append the trailing NULL, if the string is too long. */
+        /* strncpy doesnt append the trailing NULL, of the string is too long. */
         filename_try[ MAXFILENAME ] = '\0';
 
 #        ifdef USEWIN32IOAPI
-        fill_win32_filefunc(&ffunc);
-        uf = unzOpen2(zipfilename,&ffunc);
+        fill_win32_filefunc64A(&ffunc);
+        uf = unzOpen2_64(zipfilename,&ffunc);
 #        else
-        uf = unzOpen(zipfilename);
+        uf = unzOpen64(zipfilename);
 #        endif
         if (uf==NULL)
         {
             strcat(filename_try,".zip");
 #            ifdef USEWIN32IOAPI
-            uf = unzOpen2(filename_try,&ffunc);
+            uf = unzOpen2_64(filename_try,&ffunc);
 #            else
-            uf = unzOpen(filename_try);
+            uf = unzOpen64(filename_try);
 #            endif
         }
     }
@@ -564,22 +635,26 @@ int main(argc,argv)
     printf("%s opened\n",filename_try);
 
     if (opt_do_list==1)
-        return do_list(uf);
+        ret_value = do_list(uf);
     else if (opt_do_extract==1)
     {
-        if (opt_extractdir && chdir(dirname)) 
+#ifdef _WIN32
+        if (opt_extractdir && _chdir(dirname))
+#else
+        if (opt_extractdir && chdir(dirname))
+#endif
         {
           printf("Error changing into %s, aborting\n", dirname);
           exit(-1);
         }
 
         if (filename_to_extract == NULL)
-            return do_extract(uf,opt_do_extract_withoutpath,opt_overwrite,password);
+            ret_value = do_extract(uf, opt_do_extract_withoutpath, opt_overwrite, password);
         else
-            return do_extract_onefile(uf,filename_to_extract,
-                                      opt_do_extract_withoutpath,opt_overwrite,password);
+            ret_value = do_extract_onefile(uf, filename_to_extract, opt_do_extract_withoutpath, opt_overwrite, password);
     }
-    unzCloseCurrentFile(uf);
 
-    return 0;
+    unzClose(uf);
+
+    return ret_value;
 }
diff --git a/third_party/zlib/contrib/minizip/minizip.c b/third_party/zlib/contrib/minizip/minizip.c
index 2aae64c..4288962 100644
--- a/third_party/zlib/contrib/minizip/minizip.c
+++ b/third_party/zlib/contrib/minizip/minizip.c
@@ -1,10 +1,46 @@
 /*
    minizip.c
-   Version 1.01e, February 12th, 2005
+   Version 1.1, February 14h, 2010
+   sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
 
-   Copyright (C) 1998-2005 Gilles Vollant
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+         Modifications of Unzip for Zip64
+         Copyright (C) 2007-2008 Even Rouault
+
+         Modifications for Zip64 support on both zip and unzip
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
 */
 
+
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
+        #ifndef __USE_FILE_OFFSET64
+                #define __USE_FILE_OFFSET64
+        #endif
+        #ifndef __USE_LARGEFILE64
+                #define __USE_LARGEFILE64
+        #endif
+        #ifndef _LARGEFILE64_SOURCE
+                #define _LARGEFILE64_SOURCE
+        #endif
+        #ifndef _FILE_OFFSET_BIT
+                #define _FILE_OFFSET_BIT 64
+        #endif
+#endif
+
+#ifdef __APPLE__
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+
+
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -12,21 +48,21 @@
 #include <errno.h>
 #include <fcntl.h>
 
-#ifdef unix
+#ifdef _WIN32
+# include <direct.h>
+# include <io.h>
+#else
 # include <unistd.h>
 # include <utime.h>
 # include <sys/types.h>
 # include <sys/stat.h>
-#else
-# include <direct.h>
-# include <io.h>
 #endif
 
 #include "zip.h"
 
-#ifdef WIN32
-#define USEWIN32IOAPI
-#include "iowin32.h"
+#ifdef _WIN32
+        #define USEWIN32IOAPI
+        #include "iowin32.h"
 #endif
 
 
@@ -34,7 +70,7 @@
 #define WRITEBUFFERSIZE (16384)
 #define MAXFILENAME (256)
 
-#ifdef WIN32
+#ifdef _WIN32
 uLong filetime(f, tmzip, dt)
     char *f;                /* name of file to get info on */
     tm_zip *tmzip;             /* return value: access, modific. and creation times */
@@ -44,9 +80,9 @@ uLong filetime(f, tmzip, dt)
   {
       FILETIME ftLocal;
       HANDLE hFind;
-      WIN32_FIND_DATA  ff32;
+      WIN32_FIND_DATAA ff32;
 
-      hFind = FindFirstFile(f,&ff32);
+      hFind = FindFirstFileA(f,&ff32);
       if (hFind != INVALID_HANDLE_VALUE)
       {
         FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
@@ -58,7 +94,7 @@ uLong filetime(f, tmzip, dt)
   return ret;
 }
 #else
-#ifdef unix
+#ifdef unix || __APPLE__
 uLong filetime(f, tmzip, dt)
     char *f;               /* name of file to get info on */
     tm_zip *tmzip;         /* return value: access, modific. and creation times */
@@ -77,7 +113,7 @@ uLong filetime(f, tmzip, dt)
       len = MAXFILENAME;
 
     strncpy(name, f,MAXFILENAME-1);
-    /* strncpy doesn't append the trailing NULL, if the string is too long. */
+    /* strncpy doesnt append the trailing NULL, of the string is too long. */
     name[ MAXFILENAME ] = '\0';
 
     if (name[len - 1] == '/')
@@ -119,7 +155,7 @@ int check_exist_file(filename)
 {
     FILE* ftestexist;
     int ret = 1;
-    ftestexist = fopen(filename,"rb");
+    ftestexist = FOPEN_FUNC(filename,"rb");
     if (ftestexist==NULL)
         ret = 0;
     else
@@ -129,18 +165,19 @@ int check_exist_file(filename)
 
 void do_banner()
 {
-    printf("MiniZip 1.01b, demo of zLib + Zip package written by Gilles Vollant\n");
-    printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
+    printf("MiniZip 1.1, demo of zLib + MiniZip64 package, written by Gilles Vollant\n");
+    printf("more info on MiniZip at http://www.winimage.com/zLibDll/minizip.html\n\n");
 }
 
 void do_help()
 {
-    printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] file.zip [files_to_add]\n\n" \
+    printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \
            "  -o  Overwrite existing file.zip\n" \
            "  -a  Append to existing file.zip\n" \
            "  -0  Store only\n" \
            "  -1  Compress faster\n" \
-           "  -9  Compress better\n\n");
+           "  -9  Compress better\n\n" \
+           "  -j  exclude path. store only the file name.\n\n");
 }
 
 /* calculate the CRC32 of a file,
@@ -149,7 +186,8 @@ int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigne
 {
    unsigned long calculate_crc=0;
    int err=ZIP_OK;
-   FILE * fin = fopen(filenameinzip,"rb");
+   FILE * fin = FOPEN_FUNC(filenameinzip,"rb");
+
    unsigned long size_read = 0;
    unsigned long total_read = 0;
    if (fin==NULL)
@@ -179,10 +217,32 @@ int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigne
         fclose(fin);
 
     *result_crc=calculate_crc;
-    printf("file %s crc %x\n",filenameinzip,calculate_crc);
+    printf("file %s crc %lx\n", filenameinzip, calculate_crc);
     return err;
 }
 
+int isLargeFile(const char* filename)
+{
+  int largeFile = 0;
+  ZPOS64_T pos = 0;
+  FILE* pFile = FOPEN_FUNC(filename, "rb");
+
+  if(pFile != NULL)
+  {
+    int n = FSEEKO_FUNC(pFile, 0, SEEK_END);
+    pos = FTELLO_FUNC(pFile);
+
+                printf("File : %s is %lld bytes\n", filename, pos);
+
+    if(pos >= 0xffffffff)
+     largeFile = 1;
+
+                fclose(pFile);
+  }
+
+ return largeFile;
+}
+
 int main(argc,argv)
     int argc;
     char *argv[];
@@ -190,6 +250,7 @@ int main(argc,argv)
     int i;
     int opt_overwrite=0;
     int opt_compress_level=Z_DEFAULT_COMPRESSION;
+    int opt_exclude_path=0;
     int zipfilenamearg = 0;
     char filename_try[MAXFILENAME+16];
     int zipok;
@@ -222,6 +283,8 @@ int main(argc,argv)
                         opt_overwrite = 2;
                     if ((c>='0') && (c<='9'))
                         opt_compress_level = c-'0';
+                    if ((c=='j') || (c=='J'))
+                        opt_exclude_path = 1;
 
                     if (((c=='p') || (c=='P')) && (i+1<argc))
                     {
@@ -231,8 +294,12 @@ int main(argc,argv)
                 }
             }
             else
+            {
                 if (zipfilenamearg == 0)
+                {
                     zipfilenamearg = i ;
+                }
+            }
         }
     }
 
@@ -245,7 +312,9 @@ int main(argc,argv)
     }
 
     if (zipfilenamearg==0)
+    {
         zipok=0;
+    }
     else
     {
         int i,len;
@@ -253,7 +322,7 @@ int main(argc,argv)
 
         zipok = 1 ;
         strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1);
-        /* strncpy doesn't append the trailing NULL, if the string is too long. */
+        /* strncpy doesnt append the trailing NULL, of the string is too long. */
         filename_try[ MAXFILENAME ] = '\0';
 
         len=(int)strlen(filename_try);
@@ -302,11 +371,11 @@ int main(argc,argv)
         zipFile zf;
         int errclose;
 #        ifdef USEWIN32IOAPI
-        zlib_filefunc_def ffunc;
-        fill_win32_filefunc(&ffunc);
-        zf = zipOpen2(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc);
+        zlib_filefunc64_def ffunc;
+        fill_win32_filefunc64A(&ffunc);
+        zf = zipOpen2_64(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc);
 #        else
-        zf = zipOpen(filename_try,(opt_overwrite==2) ? 2 : 0);
+        zf = zipOpen64(filename_try,(opt_overwrite==2) ? 2 : 0);
 #        endif
 
         if (zf == NULL)
@@ -329,8 +398,10 @@ int main(argc,argv)
                 FILE * fin;
                 int size_read;
                 const char* filenameinzip = argv[i];
+                const char *savefilenameinzip;
                 zip_fileinfo zi;
                 unsigned long crcFile=0;
+                int zip64 = 0;
 
                 zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
                 zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
@@ -348,19 +419,48 @@ int main(argc,argv)
                 if ((password != NULL) && (err==ZIP_OK))
                     err = getFileCrc(filenameinzip,buf,size_buf,&crcFile);
 
-                err = zipOpenNewFileInZip3(zf,filenameinzip,&zi,
+                zip64 = isLargeFile(filenameinzip);
+
+                                                         /* The path name saved, should not include a leading slash. */
+               /*if it did, windows/xp and dynazip couldn't read the zip file. */
+                 savefilenameinzip = filenameinzip;
+                 while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' )
+                 {
+                     savefilenameinzip++;
+                 }
+
+                 /*should the zip file contain any path at all?*/
+                 if( opt_exclude_path )
+                 {
+                     const char *tmpptr;
+                     const char *lastslash = 0;
+                     for( tmpptr = savefilenameinzip; *tmpptr; tmpptr++)
+                     {
+                         if( *tmpptr == '\\' || *tmpptr == '/')
+                         {
+                             lastslash = tmpptr;
+                         }
+                     }
+                     if( lastslash != NULL )
+                     {
+                         savefilenameinzip = lastslash+1; // base filename follows last slash.
+                     }
+                 }
+
+                 /**/
+                err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi,
                                  NULL,0,NULL,0,NULL /* comment*/,
                                  (opt_compress_level != 0) ? Z_DEFLATED : 0,
                                  opt_compress_level,0,
                                  /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
                                  -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
-                                 password,crcFile);
+                                 password,crcFile, zip64);
 
                 if (err != ZIP_OK)
                     printf("error in opening %s in zipfile\n",filenameinzip);
                 else
                 {
-                    fin = fopen(filenameinzip,"rb");
+                    fin = FOPEN_FUNC(filenameinzip,"rb");
                     if (fin==NULL)
                     {
                         err=ZIP_ERRNO;
diff --git a/third_party/zlib/contrib/minizip/mztools.c b/third_party/zlib/contrib/minizip/mztools.c
index 8a50ee4..96891c2 100644
--- a/third_party/zlib/contrib/minizip/mztools.c
+++ b/third_party/zlib/contrib/minizip/mztools.c
@@ -42,7 +42,7 @@ uLong* bytesRecovered;
     int entries = 0;
     uLong totalBytes = 0;
     char header[30];
-    char filename[256];
+    char filename[1024];
     char extra[1024];
     int offset = 0;
     int offsetCD = 0;
@@ -62,7 +62,7 @@ uLong* bytesRecovered;
         unsigned int fnsize = READ_16(header + 26); /* file name length */
         unsigned int extsize = READ_16(header + 28); /* extra field length */
         filename[0] = extra[0] = '\0';
-        
+
         /* Header */
         if (fwrite(header, 1, 30, fpOut) == 30) {
           offset += 30;
@@ -70,12 +70,17 @@ uLong* bytesRecovered;
           err = Z_ERRNO;
           break;
         }
-        
+
         /* Filename */
         if (fnsize > 0) {
-          if (fread(filename, 1, fnsize, fpZip) == fnsize) {
-            if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
-              offset += fnsize;
+          if (fnsize < sizeof(filename)) {
+            if (fread(filename, 1, fnsize, fpZip) == fnsize) {
+                if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
+                offset += fnsize;
+              } else {
+                err = Z_ERRNO;
+                break;
+              }
             } else {
               err = Z_ERRNO;
               break;
@@ -91,9 +96,14 @@ uLong* bytesRecovered;
 
         /* Extra field */
         if (extsize > 0) {
-          if (fread(extra, 1, extsize, fpZip) == extsize) {
-            if (fwrite(extra, 1, extsize, fpOut) == extsize) {
-              offset += extsize;
+          if (extsize < sizeof(extra)) {
+            if (fread(extra, 1, extsize, fpZip) == extsize) {
+              if (fwrite(extra, 1, extsize, fpOut) == extsize) {
+                offset += extsize;
+                } else {
+                err = Z_ERRNO;
+                break;
+              }
             } else {
               err = Z_ERRNO;
               break;
@@ -103,7 +113,7 @@ uLong* bytesRecovered;
             break;
           }
         }
-        
+
         /* Data */
         {
           int dataSize = cpsize;
@@ -133,7 +143,7 @@ uLong* bytesRecovered;
             }
           }
         }
-        
+
         /* Central directory entry */
         {
           char header[46];
@@ -159,7 +169,7 @@ uLong* bytesRecovered;
           /* Header */
           if (fwrite(header, 1, 46, fpOutCD) == 46) {
             offsetCD += 46;
-            
+
             /* Filename */
             if (fnsize > 0) {
               if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) {
@@ -172,7 +182,7 @@ uLong* bytesRecovered;
               err = Z_STREAM_ERROR;
               break;
             }
-            
+
             /* Extra field */
             if (extsize > 0) {
               if (fwrite(extra, 1, extsize, fpOutCD) == extsize) {
@@ -182,7 +192,7 @@ uLong* bytesRecovered;
                 break;
               }
             }
-            
+
             /* Comment field */
             if (comsize > 0) {
               if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) {
@@ -192,8 +202,8 @@ uLong* bytesRecovered;
                 break;
               }
             }
-            
-            
+
+
           } else {
             err = Z_ERRNO;
             break;
@@ -225,17 +235,17 @@ uLong* bytesRecovered;
       WRITE_32(header + 12, offsetCD);    /* size of CD */
       WRITE_32(header + 16, offset);      /* offset to CD */
       WRITE_16(header + 20, comsize);     /* comment */
-      
+
       /* Header */
       if (fwrite(header, 1, 22, fpOutCD) == 22) {
-        
+
         /* Comment field */
         if (comsize > 0) {
           if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) {
             err = Z_ERRNO;
           }
         }
-        
+
       } else {
         err = Z_ERRNO;
       }
@@ -257,14 +267,14 @@ uLong* bytesRecovered;
         fclose(fpOutCD);
       }
     }
-    
+
     /* Close */
     fclose(fpZip);
     fclose(fpOut);
-    
+
     /* Wipe temporary file */
     (void)remove(fileOutTmp);
-    
+
     /* Number of recovered entries */
     if (err == Z_OK) {
       if (nRecovered != NULL) {
diff --git a/third_party/zlib/contrib/minizip/mztools.h b/third_party/zlib/contrib/minizip/mztools.h
index eee78dc..a49a426 100644
--- a/third_party/zlib/contrib/minizip/mztools.h
+++ b/third_party/zlib/contrib/minizip/mztools.h
@@ -17,15 +17,21 @@ extern "C" {
 
 #include "unzip.h"
 
-/* Repair a ZIP file (missing central directory) 
+/* Repair a ZIP file (missing central directory)
    file: file to recover
    fileOut: output file after recovery
    fileOutTmp: temporary file name used for recovery
 */
-extern int ZEXPORT unzRepair(const char* file, 
-                             const char* fileOut, 
-                             const char* fileOutTmp, 
+extern int ZEXPORT unzRepair(const char* file,
+                             const char* fileOut,
+                             const char* fileOutTmp,
                              uLong* nRecovered,
                              uLong* bytesRecovered);
 
+
+#ifdef __cplusplus
+}
+#endif
+
+
 #endif
diff --git a/third_party/zlib/contrib/minizip/unzip.c b/third_party/zlib/contrib/minizip/unzip.c
index fe2f1f0..9093504 100644
--- a/third_party/zlib/contrib/minizip/unzip.c
+++ b/third_party/zlib/contrib/minizip/unzip.c
@@ -1,43 +1,77 @@
 /* unzip.c -- IO for uncompress .zip files using zlib
-   Version 1.01e, February 12th, 2005
+   Version 1.1, February 14h, 2010
+   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
 
-   Copyright (C) 1998-2005 Gilles Vollant
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
 
-   Read unzip.h for more info
-*/
+         Modifications of Unzip for Zip64
+         Copyright (C) 2007-2008 Even Rouault
+
+         Modifications for Zip64 support on both zip and unzip
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+         For more info read MiniZip_info.txt
+
+
+  ------------------------------------------------------------------------------------
+  Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
+  compatibility with older software. The following is from the original crypt.c.
+  Code woven in by Terry Thorsen 1/2003.
 
-/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
-compatibility with older software. The following is from the original crypt.c. Code
-woven in by Terry Thorsen 1/2003.
-*/
-/*
   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
 
   See the accompanying file LICENSE, version 2000-Apr-09 or later
   (the contents of which are also included in zip.h) for terms of use.
   If, for some reason, all these files are missing, the Info-ZIP license
   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
-*/
-/*
-  crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
+
+        crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
 
   The encryption/decryption parts of this source code (as opposed to the
   non-echoing password parts) were originally written in Europe.  The
   whole source package can be freely distributed, including from the USA.
   (Prior to January 2000, re-export from the US was a violation of US law.)
- */
 
-/*
-  This encryption code is a direct transcription of the algorithm from
+        This encryption code is a direct transcription of the algorithm from
   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
   file (appnote.txt) is distributed with the PKZIP program (even in the
   version without encryption capabilities).
- */
+
+        ------------------------------------------------------------------------------------
+
+        Changes in unzip.c
+
+        2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos
+  2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz*
+  2007-2008 - Even Rouault - Remove old C style function prototypes
+  2007-2008 - Even Rouault - Add unzip support for ZIP64
+
+        Copyright (C) 2007-2008 Even Rouault
+
+
+        Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again).
+  Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G
+                                should only read the compressed/uncompressed size from the Zip64 format if
+                                the size from normal header was 0xFFFFFFFF
+  Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant
+        Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required)
+                                Patch created by Daniel Borca
+
+  Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
+
+  Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson
+
+*/
 
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+
+#ifndef NOUNCRYPT
+        #define NOUNCRYPT
+#endif
+
 #include "zlib.h"
 #include "unzip.h"
 
@@ -85,16 +119,14 @@ woven in by Terry Thorsen 1/2003.
 #define SIZEZIPLOCALHEADER (0x1e)
 
 
-
-
 const char unz_copyright[] =
    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
 
 /* unz_file_info_interntal contain internal info about a file in zipfile*/
-typedef struct unz_file_info_internal_s
+typedef struct unz_file_info64_internal_s
 {
-    uLong offset_curfile;/* relative offset of local header 4 bytes */
-} unz_file_info_internal;
+    ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
+} unz_file_info64_internal;
 
 
 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
@@ -104,52 +136,61 @@ typedef struct
     char  *read_buffer;         /* internal buffer for compressed data */
     z_stream stream;            /* zLib stream structure for inflate */
 
-    uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
+#ifdef HAVE_BZIP2
+    bz_stream bstream;          /* bzLib stream structure for bziped */
+#endif
+
+    ZPOS64_T pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
     uLong stream_initialised;   /* flag set if stream structure is initialised*/
 
-    uLong offset_local_extrafield;/* offset of the local extra field */
+    ZPOS64_T offset_local_extrafield;/* offset of the local extra field */
     uInt  size_local_extrafield;/* size of the local extra field */
-    uLong pos_local_extrafield;   /* position in the local extra field in read*/
+    ZPOS64_T pos_local_extrafield;   /* position in the local extra field in read*/
+    ZPOS64_T total_out_64;
 
     uLong crc32;                /* crc32 of all data uncompressed */
     uLong crc32_wait;           /* crc32 we must obtain after decompress all */
-    uLong rest_read_compressed; /* number of byte to be decompressed */
-    uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
-    zlib_filefunc_def z_filefunc;
+    ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */
+    ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/
+    zlib_filefunc64_32_def z_filefunc;
     voidpf filestream;        /* io structore of the zipfile */
     uLong compression_method;   /* compression method (0==store) */
-    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+    ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
     int   raw;
-} file_in_zip_read_info_s;
+} file_in_zip64_read_info_s;
 
 
-/* unz_s contain internal information about the zipfile
+/* unz64_s contain internal information about the zipfile
 */
 typedef struct
 {
-    zlib_filefunc_def z_filefunc;
+    zlib_filefunc64_32_def z_filefunc;
+    int is64bitOpenFunction;
     voidpf filestream;        /* io structore of the zipfile */
-    unz_global_info gi;       /* public global information */
-    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
-    uLong num_file;             /* number of the current file in the zipfile*/
-    uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
-    uLong current_file_ok;      /* flag about the usability of the current file*/
-    uLong central_pos;          /* position of the beginning of the central dir*/
-
-    uLong size_central_dir;     /* size of the central directory  */
-    uLong offset_central_dir;   /* offset of start of central directory with
+    unz_global_info64 gi;       /* public global information */
+    ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+    ZPOS64_T num_file;             /* number of the current file in the zipfile*/
+    ZPOS64_T pos_in_central_dir;   /* pos of the current file in the central dir*/
+    ZPOS64_T current_file_ok;      /* flag about the usability of the current file*/
+    ZPOS64_T central_pos;          /* position of the beginning of the central dir*/
+
+    ZPOS64_T size_central_dir;     /* size of the central directory  */
+    ZPOS64_T offset_central_dir;   /* offset of start of central directory with
                                    respect to the starting disk number */
 
-    unz_file_info cur_file_info; /* public info about the current file in zip*/
-    unz_file_info_internal cur_file_info_internal; /* private info about it*/
-    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
+    unz_file_info64 cur_file_info; /* public info about the current file in zip*/
+    unz_file_info64_internal cur_file_info_internal; /* private info about it*/
+    file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current
                                         file if we are decompressing it */
     int encrypted;
+
+    int isZip64;
+
 #    ifndef NOUNCRYPT
     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
-    const unsigned long* pcrc_32_tab;
+    const z_crc_t* pcrc_32_tab;
 #    endif
-} unz_s;
+} unz64_s;
 
 
 #ifndef NOUNCRYPT
@@ -159,22 +200,19 @@ typedef struct
 /* ===========================================================================
      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
    for end of file.
-   IN assertion: the stream s has been successfully opened for reading.
+   IN assertion: the stream s has been sucessfully opened for reading.
 */
 
 
-local int unzlocal_getByte OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
+local int unz64local_getByte OF((
+    const zlib_filefunc64_32_def* pzlib_filefunc_def,
     voidpf filestream,
     int *pi));
 
-local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    int *pi;
+local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)
 {
     unsigned char c;
-    int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
+    int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
     if (err==1)
     {
         *pi = (int)c;
@@ -182,7 +220,7 @@ local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
     }
     else
     {
-        if (ZERROR(*pzlib_filefunc_def,filestream))
+        if (ZERROR64(*pzlib_filefunc_def,filestream))
             return UNZ_ERRNO;
         else
             return UNZ_EOF;
@@ -193,26 +231,25 @@ local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
 /* ===========================================================================
    Reads a long in LSB order from the given gz_stream. Sets
 */
-local int unzlocal_getShort OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
+local int unz64local_getShort OF((
+    const zlib_filefunc64_32_def* pzlib_filefunc_def,
     voidpf filestream,
     uLong *pX));
 
-local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    uLong *pX;
+local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+                             voidpf filestream,
+                             uLong *pX)
 {
     uLong x ;
-    int i;
+    int i = 0;
     int err;
 
-    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+    err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
     x = (uLong)i;
 
     if (err==UNZ_OK)
-        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x += ((uLong)i)<<8;
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((uLong)i)<<8;
 
     if (err==UNZ_OK)
         *pX = x;
@@ -221,33 +258,32 @@ local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
     return err;
 }
 
-local int unzlocal_getLong OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
+local int unz64local_getLong OF((
+    const zlib_filefunc64_32_def* pzlib_filefunc_def,
     voidpf filestream,
     uLong *pX));
 
-local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    uLong *pX;
+local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+                            voidpf filestream,
+                            uLong *pX)
 {
     uLong x ;
-    int i;
+    int i = 0;
     int err;
 
-    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+    err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
     x = (uLong)i;
 
     if (err==UNZ_OK)
-        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x += ((uLong)i)<<8;
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((uLong)i)<<8;
 
     if (err==UNZ_OK)
-        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
-    x += ((uLong)i)<<16;
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((uLong)i)<<16;
 
     if (err==UNZ_OK)
-        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
     x += ((uLong)i)<<24;
 
     if (err==UNZ_OK)
@@ -257,11 +293,60 @@ local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
     return err;
 }
 
+local int unz64local_getLong64 OF((
+    const zlib_filefunc64_32_def* pzlib_filefunc_def,
+    voidpf filestream,
+    ZPOS64_T *pX));
+
+
+local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+                            voidpf filestream,
+                            ZPOS64_T *pX)
+{
+    ZPOS64_T x ;
+    int i = 0;
+    int err;
+
+    err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x = (ZPOS64_T)i;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<8;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<16;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<24;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<32;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<40;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<48;
+
+    if (err==UNZ_OK)
+        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+    x |= ((ZPOS64_T)i)<<56;
+
+    if (err==UNZ_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+}
 
 /* My own strcmpi / strcasecmp */
-local int strcmpcasenosensitive_internal (fileName1,fileName2)
-    const char* fileName1;
-    const char* fileName2;
+local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)
 {
     for (;;)
     {
@@ -295,17 +380,17 @@ local int strcmpcasenosensitive_internal (fileName1,fileName2)
 
 /*
    Compare two filename (fileName1,fileName2).
-   If iCaseSensitivity = 1, comparison is case sensitive (like strcmp)
-   If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
                                                                 or strcasecmp)
-   If iCaseSensitivity = 0, case sensitivity is default of your operating system
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
         (like 1 on Unix, 2 on Windows)
 
 */
-extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
-    const char* fileName1;
-    const char* fileName2;
-    int iCaseSensitivity;
+extern int ZEXPORT unzStringFileNameCompare (const char*  fileName1,
+                                                 const char*  fileName2,
+                                                 int iCaseSensitivity)
+
 {
     if (iCaseSensitivity==0)
         iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
@@ -324,25 +409,20 @@ extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivit
   Locate the Central directory of a zipfile (at the end, just before
     the global comment)
 */
-local uLong unzlocal_SearchCentralDir OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream));
-
-local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
+local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));
+local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
 {
     unsigned char* buf;
-    uLong uSizeFile;
-    uLong uBackRead;
-    uLong uMaxBack=0xffff; /* maximum size of global comment */
-    uLong uPosFound=0;
+    ZPOS64_T uSizeFile;
+    ZPOS64_T uBackRead;
+    ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+    ZPOS64_T uPosFound=0;
 
-    if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+    if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
         return 0;
 
 
-    uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
+    uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
 
     if (uMaxBack>uSizeFile)
         uMaxBack = uSizeFile;
@@ -354,7 +434,8 @@ local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
     uBackRead = 4;
     while (uBackRead<uMaxBack)
     {
-        uLong uReadSize,uReadPos ;
+        uLong uReadSize;
+        ZPOS64_T uReadPos ;
         int i;
         if (uBackRead+BUFREADCOMMENT>uMaxBack)
             uBackRead = uMaxBack;
@@ -363,11 +444,11 @@ local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
         uReadPos = uSizeFile-uBackRead ;
 
         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
-                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
-        if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+                     (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+        if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
             break;
 
-        if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+        if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
             break;
 
         for (i=(int)uReadSize-3; (i--)>0;)
@@ -385,6 +466,112 @@ local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
     return uPosFound;
 }
 
+
+/*
+  Locate the Central directory 64 of a zipfile (at the end, just before
+    the global comment)
+*/
+local ZPOS64_T unz64local_SearchCentralDir64 OF((
+    const zlib_filefunc64_32_def* pzlib_filefunc_def,
+    voidpf filestream));
+
+local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
+                                      voidpf filestream)
+{
+    unsigned char* buf;
+    ZPOS64_T uSizeFile;
+    ZPOS64_T uBackRead;
+    ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+    ZPOS64_T uPosFound=0;
+    uLong uL;
+                ZPOS64_T relativeOffset;
+
+    if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+        return 0;
+
+
+    uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+    if (uMaxBack>uSizeFile)
+        uMaxBack = uSizeFile;
+
+    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+    if (buf==NULL)
+        return 0;
+
+    uBackRead = 4;
+    while (uBackRead<uMaxBack)
+    {
+        uLong uReadSize;
+        ZPOS64_T uReadPos;
+        int i;
+        if (uBackRead+BUFREADCOMMENT>uMaxBack)
+            uBackRead = uMaxBack;
+        else
+            uBackRead+=BUFREADCOMMENT;
+        uReadPos = uSizeFile-uBackRead ;
+
+        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+                     (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+        if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            break;
+
+        if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+            break;
+
+        for (i=(int)uReadSize-3; (i--)>0;)
+            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+                ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
+            {
+                uPosFound = uReadPos+i;
+                break;
+            }
+
+        if (uPosFound!=0)
+            break;
+    }
+    TRYFREE(buf);
+    if (uPosFound == 0)
+        return 0;
+
+    /* Zip64 end of central directory locator */
+    if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        return 0;
+
+    /* the signature, already checked */
+    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+        return 0;
+
+    /* number of the disk with the start of the zip64 end of  central directory */
+    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+        return 0;
+    if (uL != 0)
+        return 0;
+
+    /* relative offset of the zip64 end of central directory record */
+    if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
+        return 0;
+
+    /* total number of disks */
+    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+        return 0;
+    if (uL != 1)
+        return 0;
+
+    /* Goto end of central directory record */
+    if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        return 0;
+
+     /* the signature */
+    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+        return 0;
+
+    if (uL != 0x06064b50)
+        return 0;
+
+    return relativeOffset;
+}
+
 /*
   Open a Zip file. path contain the full pathname (by example,
      on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
@@ -394,19 +581,20 @@ local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
      Else, the return value is a unzFile Handle, usable with other function
        of this unzip package.
 */
-extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
-    const char *path;
-    zlib_filefunc_def* pzlib_filefunc_def;
+local unzFile unzOpenInternal (const void *path,
+                               zlib_filefunc64_32_def* pzlib_filefunc64_32_def,
+                               int is64bitOpenFunction)
 {
-    unz_s us;
-    unz_s *s;
-    uLong central_pos,uL;
+    unz64_s us;
+    unz64_s *s;
+    ZPOS64_T central_pos;
+    uLong   uL;
 
     uLong number_disk;          /* number of the current dist, used for
                                    spaning ZIP, unsupported, always 0*/
     uLong number_disk_with_CD;  /* number the the disk with central dir, used
                                    for spaning ZIP, unsupported, always 0*/
-    uLong number_entry_CD;      /* total number of entries in
+    ZPOS64_T number_entry_CD;      /* total number of entries in
                                    the central dir
                                    (same than number_entry on nospan) */
 
@@ -415,63 +603,137 @@ extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
     if (unz_copyright[0]!=' ')
         return NULL;
 
-    if (pzlib_filefunc_def==NULL)
-        fill_fopen_filefunc(&us.z_filefunc);
+    us.z_filefunc.zseek32_file = NULL;
+    us.z_filefunc.ztell32_file = NULL;
+    if (pzlib_filefunc64_32_def==NULL)
+        fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
     else
-        us.z_filefunc = *pzlib_filefunc_def;
+        us.z_filefunc = *pzlib_filefunc64_32_def;
+    us.is64bitOpenFunction = is64bitOpenFunction;
 
-    us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
+
+
+    us.filestream = ZOPEN64(us.z_filefunc,
                                                  path,
                                                  ZLIB_FILEFUNC_MODE_READ |
                                                  ZLIB_FILEFUNC_MODE_EXISTING);
     if (us.filestream==NULL)
         return NULL;
 
-    central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
-    if (central_pos==0)
-        err=UNZ_ERRNO;
+    central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
+    if (central_pos)
+    {
+        uLong uS;
+        ZPOS64_T uL64;
+
+        us.isZip64 = 1;
 
-    if (ZSEEK(us.z_filefunc, us.filestream,
+        if (ZSEEK64(us.z_filefunc, us.filestream,
                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
         err=UNZ_ERRNO;
 
-    /* the signature, already checked */
-    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
-        err=UNZ_ERRNO;
+        /* the signature, already checked */
+        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+            err=UNZ_ERRNO;
 
-    /* number of this disk */
-    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
-        err=UNZ_ERRNO;
+        /* size of zip64 end of central directory record */
+        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK)
+            err=UNZ_ERRNO;
 
-    /* number of the disk with the start of the central directory */
-    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
-        err=UNZ_ERRNO;
+        /* version made by */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
+            err=UNZ_ERRNO;
 
-    /* total number of entries in the central dir on this disk */
-    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
-        err=UNZ_ERRNO;
+        /* version needed to extract */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
+            err=UNZ_ERRNO;
 
-    /* total number of entries in the central dir */
-    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
-        err=UNZ_ERRNO;
+        /* number of this disk */
+        if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+            err=UNZ_ERRNO;
 
-    if ((number_entry_CD!=us.gi.number_entry) ||
-        (number_disk_with_CD!=0) ||
-        (number_disk!=0))
-        err=UNZ_BADZIPFILE;
+        /* number of the disk with the start of the central directory */
+        if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+            err=UNZ_ERRNO;
 
-    /* size of the central directory */
-    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
-        err=UNZ_ERRNO;
+        /* total number of entries in the central directory on this disk */
+        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* total number of entries in the central directory */
+        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
+            err=UNZ_ERRNO;
 
-    /* offset of start of central directory with respect to the
+        if ((number_entry_CD!=us.gi.number_entry) ||
+            (number_disk_with_CD!=0) ||
+            (number_disk!=0))
+            err=UNZ_BADZIPFILE;
+
+        /* size of the central directory */
+        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* offset of start of central directory with respect to the
           starting disk number */
-    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
-        err=UNZ_ERRNO;
+        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
+            err=UNZ_ERRNO;
 
-    /* zipfile comment length */
-    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
-        err=UNZ_ERRNO;
+        us.gi.size_comment = 0;
+    }
+    else
+    {
+        central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
+        if (central_pos==0)
+            err=UNZ_ERRNO;
+
+        us.isZip64 = 0;
+
+        if (ZSEEK64(us.z_filefunc, us.filestream,
+                                        central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            err=UNZ_ERRNO;
+
+        /* the signature, already checked */
+        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* number of this disk */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* number of the disk with the start of the central directory */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+            err=UNZ_ERRNO;
+
+        /* total number of entries in the central dir on this disk */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+            err=UNZ_ERRNO;
+        us.gi.number_entry = uL;
+
+        /* total number of entries in the central dir */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+            err=UNZ_ERRNO;
+        number_entry_CD = uL;
+
+        if ((number_entry_CD!=us.gi.number_entry) ||
+            (number_disk_with_CD!=0) ||
+            (number_disk!=0))
+            err=UNZ_BADZIPFILE;
+
+        /* size of the central directory */
+        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+            err=UNZ_ERRNO;
+        us.size_central_dir = uL;
+
+        /* offset of start of central directory with respect to the
+            starting disk number */
+        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+            err=UNZ_ERRNO;
+        us.offset_central_dir = uL;
+
+        /* zipfile comment length */
+        if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
+            err=UNZ_ERRNO;
+    }
 
     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
         (err==UNZ_OK))
@@ -479,7 +741,7 @@ extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
 
     if (err!=UNZ_OK)
     {
-        ZCLOSE(us.z_filefunc, us.filestream);
+        ZCLOSE64(us.z_filefunc, us.filestream);
         return NULL;
     }
 
@@ -490,36 +752,70 @@ extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
     us.encrypted = 0;
 
 
-    s=(unz_s*)ALLOC(sizeof(unz_s));
-    *s=us;
-    unzGoToFirstFile((unzFile)s);
+    s=(unz64_s*)ALLOC(sizeof(unz64_s));
+    if( s != NULL)
+    {
+        *s=us;
+        unzGoToFirstFile((unzFile)s);
+    }
     return (unzFile)s;
 }
 
 
-extern unzFile ZEXPORT unzOpen (path)
-    const char *path;
+extern unzFile ZEXPORT unzOpen2 (const char *path,
+                                        zlib_filefunc_def* pzlib_filefunc32_def)
 {
-    return unzOpen2(path, NULL);
+    if (pzlib_filefunc32_def != NULL)
+    {
+        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
+        fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
+        return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0);
+    }
+    else
+        return unzOpenInternal(path, NULL, 0);
+}
+
+extern unzFile ZEXPORT unzOpen2_64 (const void *path,
+                                     zlib_filefunc64_def* pzlib_filefunc_def)
+{
+    if (pzlib_filefunc_def != NULL)
+    {
+        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
+        zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
+        zlib_filefunc64_32_def_fill.ztell32_file = NULL;
+        zlib_filefunc64_32_def_fill.zseek32_file = NULL;
+        return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1);
+    }
+    else
+        return unzOpenInternal(path, NULL, 1);
+}
+
+extern unzFile ZEXPORT unzOpen (const char *path)
+{
+    return unzOpenInternal(path, NULL, 0);
+}
+
+extern unzFile ZEXPORT unzOpen64 (const void *path)
+{
+    return unzOpenInternal(path, NULL, 1);
 }
 
 /*
-  Close a ZipFile opened with unzipOpen.
-  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
-    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+  Close a ZipFile opened with unzOpen.
+  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+    these files MUST be closed with unzCloseCurrentFile before call unzClose.
   return UNZ_OK if there is no problem. */
-extern int ZEXPORT unzClose (file)
-    unzFile file;
+extern int ZEXPORT unzClose (unzFile file)
 {
-    unz_s* s;
+    unz64_s* s;
     if (file==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
 
     if (s->pfile_in_zip_read!=NULL)
         unzCloseCurrentFile(file);
 
-    ZCLOSE(s->z_filefunc, s->filestream);
+    ZCLOSE64(s->z_filefunc, s->filestream);
     TRYFREE(s);
     return UNZ_OK;
 }
@@ -529,28 +825,34 @@ extern int ZEXPORT unzClose (file)
   Write info about the ZipFile in the *pglobal_info structure.
   No preparation of the structure is needed
   return UNZ_OK if there is no problem. */
-extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
-    unzFile file;
-    unz_global_info *pglobal_info;
+extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info)
 {
-    unz_s* s;
+    unz64_s* s;
     if (file==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
     *pglobal_info=s->gi;
     return UNZ_OK;
 }
 
-
+extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32)
+{
+    unz64_s* s;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz64_s*)file;
+    /* to do : check if number_entry is not truncated */
+    pglobal_info32->number_entry = (uLong)s->gi.number_entry;
+    pglobal_info32->size_comment = s->gi.size_comment;
+    return UNZ_OK;
+}
 /*
    Translate date/time from Dos format to tm_unz (readable more easilty)
 */
-local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
-    uLong ulDosDate;
-    tm_unz* ptm;
+local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm)
 {
-    uLong uDate;
-    uDate = (uLong)(ulDosDate>>16);
+    ZPOS64_T uDate;
+    uDate = (ZPOS64_T)(ulDosDate>>16);
     ptm->tm_mday = (uInt)(uDate&0x1f) ;
     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
@@ -563,9 +865,9 @@ local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
 /*
   Get Info about the current file in the zipfile, with internal only info
 */
-local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
-                                                  unz_file_info *pfile_info,
-                                                  unz_file_info_internal
+local int unz64local_GetCurrentFileInfoInternal OF((unzFile file,
+                                                  unz_file_info64 *pfile_info,
+                                                  unz_file_info64_internal
                                                   *pfile_info_internal,
                                                   char *szFileName,
                                                   uLong fileNameBufferSize,
@@ -574,33 +876,29 @@ local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
                                                   char *szComment,
                                                   uLong commentBufferSize));
 
-local int unzlocal_GetCurrentFileInfoInternal (file,
-                                              pfile_info,
-                                              pfile_info_internal,
-                                              szFileName, fileNameBufferSize,
-                                              extraField, extraFieldBufferSize,
-                                              szComment,  commentBufferSize)
-    unzFile file;
-    unz_file_info *pfile_info;
-    unz_file_info_internal *pfile_info_internal;
-    char *szFileName;
-    uLong fileNameBufferSize;
-    void *extraField;
-    uLong extraFieldBufferSize;
-    char *szComment;
-    uLong commentBufferSize;
+local int unz64local_GetCurrentFileInfoInternal (unzFile file,
+                                                  unz_file_info64 *pfile_info,
+                                                  unz_file_info64_internal
+                                                  *pfile_info_internal,
+                                                  char *szFileName,
+                                                  uLong fileNameBufferSize,
+                                                  void *extraField,
+                                                  uLong extraFieldBufferSize,
+                                                  char *szComment,
+                                                  uLong commentBufferSize)
 {
-    unz_s* s;
-    unz_file_info file_info;
-    unz_file_info_internal file_info_internal;
+    unz64_s* s;
+    unz_file_info64 file_info;
+    unz_file_info64_internal file_info_internal;
     int err=UNZ_OK;
     uLong uMagic;
     long lSeek=0;
+    uLong uL;
 
     if (file==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
-    if (ZSEEK(s->z_filefunc, s->filestream,
+    s=(unz64_s*)file;
+    if (ZSEEK64(s->z_filefunc, s->filestream,
               s->pos_in_central_dir+s->byte_before_the_zipfile,
               ZLIB_FILEFUNC_SEEK_SET)!=0)
         err=UNZ_ERRNO;
@@ -608,57 +906,63 @@ local int unzlocal_GetCurrentFileInfoInternal (file,
 
     /* we check the magic */
     if (err==UNZ_OK)
-        if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+    {
+        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
             err=UNZ_ERRNO;
         else if (uMagic!=0x02014b50)
             err=UNZ_BADZIPFILE;
+    }
 
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
         err=UNZ_ERRNO;
 
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
         err=UNZ_ERRNO;
 
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
         err=UNZ_ERRNO;
 
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
         err=UNZ_ERRNO;
 
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
         err=UNZ_ERRNO;
 
-    unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
+    unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
 
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
         err=UNZ_ERRNO;
 
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
         err=UNZ_ERRNO;
+    file_info.compressed_size = uL;
 
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
         err=UNZ_ERRNO;
+    file_info.uncompressed_size = uL;
 
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
         err=UNZ_ERRNO;
 
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
         err=UNZ_ERRNO;
 
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
         err=UNZ_ERRNO;
 
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
         err=UNZ_ERRNO;
 
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
         err=UNZ_ERRNO;
 
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
         err=UNZ_ERRNO;
 
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
+                // relative offset of local header
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
         err=UNZ_ERRNO;
+    file_info_internal.offset_curfile = uL;
 
     lSeek+=file_info.size_filename;
     if ((err==UNZ_OK) && (szFileName!=NULL))
@@ -673,33 +977,105 @@ local int unzlocal_GetCurrentFileInfoInternal (file,
             uSizeRead = fileNameBufferSize;
 
         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
-            if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
+            if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
                 err=UNZ_ERRNO;
         lSeek -= uSizeRead;
     }
 
-
+    // Read extrafield
     if ((err==UNZ_OK) && (extraField!=NULL))
     {
-        uLong uSizeRead ;
+        ZPOS64_T uSizeRead ;
         if (file_info.size_file_extra<extraFieldBufferSize)
             uSizeRead = file_info.size_file_extra;
         else
             uSizeRead = extraFieldBufferSize;
 
         if (lSeek!=0)
-            if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+        {
+            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
                 lSeek=0;
             else
                 err=UNZ_ERRNO;
+        }
+
         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
-            if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
+            if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead)
                 err=UNZ_ERRNO;
-        lSeek += file_info.size_file_extra - uSizeRead;
+
+        lSeek += file_info.size_file_extra - (uLong)uSizeRead;
     }
     else
-        lSeek+=file_info.size_file_extra;
+        lSeek += file_info.size_file_extra;
+
+
+    if ((err==UNZ_OK) && (file_info.size_file_extra != 0))
+    {
+                                uLong acc = 0;
+
+        // since lSeek now points to after the extra field we need to move back
+        lSeek -= file_info.size_file_extra;
+
+        if (lSeek!=0)
+        {
+            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+                lSeek=0;
+            else
+                err=UNZ_ERRNO;
+        }
 
+        while(acc < file_info.size_file_extra)
+        {
+            uLong headerId;
+                                                uLong dataSize;
+
+            if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK)
+                err=UNZ_ERRNO;
+
+            if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK)
+                err=UNZ_ERRNO;
+
+            /* ZIP64 extra fields */
+            if (headerId == 0x0001)
+            {
+                                                        uLong uL;
+
+                                                                if(file_info.uncompressed_size == MAXU32)
+                                                                {
+                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
+                                                                                        err=UNZ_ERRNO;
+                                                                }
+
+                                                                if(file_info.compressed_size == MAXU32)
+                                                                {
+                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
+                                                                                  err=UNZ_ERRNO;
+                                                                }
+
+                                                                if(file_info_internal.offset_curfile == MAXU32)
+                                                                {
+                                                                        /* Relative Header offset */
+                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
+                                                                                err=UNZ_ERRNO;
+                                                                }
+
+                                                                if(file_info.disk_num_start == MAXU32)
+                                                                {
+                                                                        /* Disk Start Number */
+                                                                        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+                                                                                err=UNZ_ERRNO;
+                                                                }
+
+            }
+            else
+            {
+                if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)
+                    err=UNZ_ERRNO;
+            }
+
+            acc += 2 + 2 + dataSize;
+        }
+    }
 
     if ((err==UNZ_OK) && (szComment!=NULL))
     {
@@ -713,18 +1089,22 @@ local int unzlocal_GetCurrentFileInfoInternal (file,
             uSizeRead = commentBufferSize;
 
         if (lSeek!=0)
-            if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+        {
+            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
                 lSeek=0;
             else
                 err=UNZ_ERRNO;
+        }
+
         if ((file_info.size_file_comment>0) && (commentBufferSize>0))
-            if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
+            if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
                 err=UNZ_ERRNO;
         lSeek+=file_info.size_file_comment - uSizeRead;
     }
     else
         lSeek+=file_info.size_file_comment;
 
+
     if ((err==UNZ_OK) && (pfile_info!=NULL))
         *pfile_info=file_info;
 
@@ -741,41 +1121,70 @@ local int unzlocal_GetCurrentFileInfoInternal (file,
   No preparation of the structure is needed
   return UNZ_OK if there is no problem.
 */
-extern int ZEXPORT unzGetCurrentFileInfo (file,
-                                          pfile_info,
-                                          szFileName, fileNameBufferSize,
-                                          extraField, extraFieldBufferSize,
-                                          szComment,  commentBufferSize)
-    unzFile file;
-    unz_file_info *pfile_info;
-    char *szFileName;
-    uLong fileNameBufferSize;
-    void *extraField;
-    uLong extraFieldBufferSize;
-    char *szComment;
-    uLong commentBufferSize;
+extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file,
+                                          unz_file_info64 * pfile_info,
+                                          char * szFileName, uLong fileNameBufferSize,
+                                          void *extraField, uLong extraFieldBufferSize,
+                                          char* szComment,  uLong commentBufferSize)
 {
-    return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
+    return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,
                                                 szFileName,fileNameBufferSize,
                                                 extraField,extraFieldBufferSize,
                                                 szComment,commentBufferSize);
 }
 
+extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
+                                          unz_file_info * pfile_info,
+                                          char * szFileName, uLong fileNameBufferSize,
+                                          void *extraField, uLong extraFieldBufferSize,
+                                          char* szComment,  uLong commentBufferSize)
+{
+    int err;
+    unz_file_info64 file_info64;
+    err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL,
+                                                szFileName,fileNameBufferSize,
+                                                extraField,extraFieldBufferSize,
+                                                szComment,commentBufferSize);
+    if ((err==UNZ_OK) && (pfile_info != NULL))
+    {
+        pfile_info->version = file_info64.version;
+        pfile_info->version_needed = file_info64.version_needed;
+        pfile_info->flag = file_info64.flag;
+        pfile_info->compression_method = file_info64.compression_method;
+        pfile_info->dosDate = file_info64.dosDate;
+        pfile_info->crc = file_info64.crc;
+
+        pfile_info->size_filename = file_info64.size_filename;
+        pfile_info->size_file_extra = file_info64.size_file_extra;
+        pfile_info->size_file_comment = file_info64.size_file_comment;
+
+        pfile_info->disk_num_start = file_info64.disk_num_start;
+        pfile_info->internal_fa = file_info64.internal_fa;
+        pfile_info->external_fa = file_info64.external_fa;
+
+        pfile_info->tmu_date = file_info64.tmu_date,
+
+
+        pfile_info->compressed_size = (uLong)file_info64.compressed_size;
+        pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size;
+
+    }
+    return err;
+}
 /*
   Set the current file of the zipfile to the first file.
   return UNZ_OK if there is no problem
 */
-extern int ZEXPORT unzGoToFirstFile (file)
-    unzFile file;
+extern int ZEXPORT unzGoToFirstFile (unzFile file)
 {
     int err=UNZ_OK;
-    unz_s* s;
+    unz64_s* s;
     if (file==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
     s->pos_in_central_dir=s->offset_central_dir;
     s->num_file=0;
-    err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+    err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
                                              &s->cur_file_info_internal,
                                              NULL,0,NULL,0,NULL,0);
     s->current_file_ok = (err == UNZ_OK);
@@ -787,15 +1196,14 @@ extern int ZEXPORT unzGoToFirstFile (file)
   return UNZ_OK if there is no problem
   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
 */
-extern int ZEXPORT unzGoToNextFile (file)
-    unzFile file;
+extern int ZEXPORT unzGoToNextFile (unzFile  file)
 {
-    unz_s* s;
+    unz64_s* s;
     int err;
 
     if (file==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
     if (!s->current_file_ok)
         return UNZ_END_OF_LIST_OF_FILE;
     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
@@ -805,7 +1213,7 @@ extern int ZEXPORT unzGoToNextFile (file)
     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
     s->num_file++;
-    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
                                                &s->cur_file_info_internal,
                                                NULL,0,NULL,0,NULL,0);
     s->current_file_ok = (err == UNZ_OK);
@@ -815,27 +1223,24 @@ extern int ZEXPORT unzGoToNextFile (file)
 
 /*
   Try locate the file szFileName in the zipfile.
-  For the iCaseSensitivity signification, see unzipStringFileNameCompare
+  For the iCaseSensitivity signification, see unzStringFileNameCompare
 
   return value :
   UNZ_OK if the file is found. It becomes the current file.
   UNZ_END_OF_LIST_OF_FILE if the file is not found
 */
-extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
-    unzFile file;
-    const char *szFileName;
-    int iCaseSensitivity;
+extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
 {
-    unz_s* s;
+    unz64_s* s;
     int err;
 
     /* We remember the 'current' position in the file so that we can jump
      * back there if we fail.
      */
-    unz_file_info cur_file_infoSaved;
-    unz_file_info_internal cur_file_info_internalSaved;
-    uLong num_fileSaved;
-    uLong pos_in_central_dirSaved;
+    unz_file_info64 cur_file_infoSaved;
+    unz_file_info64_internal cur_file_info_internalSaved;
+    ZPOS64_T num_fileSaved;
+    ZPOS64_T pos_in_central_dirSaved;
 
 
     if (file==NULL)
@@ -844,7 +1249,7 @@ extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
         return UNZ_PARAMERROR;
 
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
     if (!s->current_file_ok)
         return UNZ_END_OF_LIST_OF_FILE;
 
@@ -859,7 +1264,7 @@ extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
     while (err == UNZ_OK)
     {
         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
-        err = unzGetCurrentFileInfo(file,NULL,
+        err = unzGetCurrentFileInfo64(file,NULL,
                                     szCurrentFileName,sizeof(szCurrentFileName)-1,
                                     NULL,0,NULL,0);
         if (err == UNZ_OK)
@@ -895,20 +1300,18 @@ extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
 /*
 typedef struct unz_file_pos_s
 {
-    uLong pos_in_zip_directory;   // offset in file
-    uLong num_of_file;            // # of file
+    ZPOS64_T pos_in_zip_directory;   // offset in file
+    ZPOS64_T num_of_file;            // # of file
 } unz_file_pos;
 */
 
-extern int ZEXPORT unzGetFilePos(file, file_pos)
-    unzFile file;
-    unz_file_pos* file_pos;
+extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos*  file_pos)
 {
-    unz_s* s;
+    unz64_s* s;
 
     if (file==NULL || file_pos==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
     if (!s->current_file_ok)
         return UNZ_END_OF_LIST_OF_FILE;
 
@@ -918,23 +1321,35 @@ extern int ZEXPORT unzGetFilePos(file, file_pos)
     return UNZ_OK;
 }
 
-extern int ZEXPORT unzGoToFilePos(file, file_pos)
-    unzFile file;
-    unz_file_pos* file_pos;
+extern int ZEXPORT unzGetFilePos(
+    unzFile file,
+    unz_file_pos* file_pos)
+{
+    unz64_file_pos file_pos64;
+    int err = unzGetFilePos64(file,&file_pos64);
+    if (err==UNZ_OK)
+    {
+        file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory;
+        file_pos->num_of_file = (uLong)file_pos64.num_of_file;
+    }
+    return err;
+}
+
+extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos)
 {
-    unz_s* s;
+    unz64_s* s;
     int err;
 
     if (file==NULL || file_pos==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
 
     /* jump to the right spot */
     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
     s->num_file           = file_pos->num_of_file;
 
     /* set the current file */
-    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
                                                &s->cur_file_info_internal,
                                                NULL,0,NULL,0,NULL,0);
     /* return results */
@@ -942,6 +1357,19 @@ extern int ZEXPORT unzGoToFilePos(file, file_pos)
     return err;
 }
 
+extern int ZEXPORT unzGoToFilePos(
+    unzFile file,
+    unz_file_pos* file_pos)
+{
+    unz64_file_pos file_pos64;
+    if (file_pos == NULL)
+        return UNZ_PARAMERROR;
+
+    file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
+    file_pos64.num_of_file = file_pos->num_of_file;
+    return unzGoToFilePos64(file,&file_pos64);
+}
+
 /*
 // Unzip Helper Functions - should be here?
 ///////////////////////////////////////////
@@ -954,13 +1382,9 @@ extern int ZEXPORT unzGoToFilePos(file, file_pos)
   store in *piSizeVar the size of extra info in local header
         (filename and size of extra field data)
 */
-local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
-                                                    poffset_local_extrafield,
-                                                    psize_local_extrafield)
-    unz_s* s;
-    uInt* piSizeVar;
-    uLong *poffset_local_extrafield;
-    uInt  *psize_local_extrafield;
+local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar,
+                                                    ZPOS64_T * poffset_local_extrafield,
+                                                    uInt  * psize_local_extrafield)
 {
     uLong uMagic,uData,uFlags;
     uLong size_filename;
@@ -971,65 +1395,66 @@ local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
     *poffset_local_extrafield = 0;
     *psize_local_extrafield = 0;
 
-    if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
+    if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
         return UNZ_ERRNO;
 
 
     if (err==UNZ_OK)
-        if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+    {
+        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
             err=UNZ_ERRNO;
         else if (uMagic!=0x04034b50)
             err=UNZ_BADZIPFILE;
+    }
 
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
         err=UNZ_ERRNO;
 /*
     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
         err=UNZ_BADZIPFILE;
 */
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
         err=UNZ_ERRNO;
 
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
         err=UNZ_ERRNO;
     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
         err=UNZ_BADZIPFILE;
 
     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
+/* #ifdef HAVE_BZIP2 */
+                         (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
+/* #endif */
                          (s->cur_file_info.compression_method!=Z_DEFLATED))
         err=UNZ_BADZIPFILE;
 
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
         err=UNZ_ERRNO;
 
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
         err=UNZ_ERRNO;
-    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
-                              ((uFlags & 8)==0))
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0))
         err=UNZ_BADZIPFILE;
 
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
         err=UNZ_ERRNO;
-    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
-                              ((uFlags & 8)==0))
+    else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0))
         err=UNZ_BADZIPFILE;
 
-    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
+    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
         err=UNZ_ERRNO;
-    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
-                              ((uFlags & 8)==0))
+    else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0))
         err=UNZ_BADZIPFILE;
 
-
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
         err=UNZ_ERRNO;
     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
         err=UNZ_BADZIPFILE;
 
     *piSizeVar += (uInt)size_filename;
 
-    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
+    if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
         err=UNZ_ERRNO;
     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
                                     SIZEZIPLOCALHEADER + size_filename;
@@ -1044,18 +1469,14 @@ local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
   Open for reading data the current file in the zipfile.
   If there is no error and the file is opened, the return value is UNZ_OK.
 */
-extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
-    unzFile file;
-    int* method;
-    int* level;
-    int raw;
-    const char* password;
+extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
+                                            int* level, int raw, const char* password)
 {
     int err=UNZ_OK;
     uInt iSizeVar;
-    unz_s* s;
-    file_in_zip_read_info_s* pfile_in_zip_read_info;
-    uLong offset_local_extrafield;  /* offset of the local extra field */
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
+    ZPOS64_T offset_local_extrafield;  /* offset of the local extra field */
     uInt  size_local_extrafield;    /* size of the local extra field */
 #    ifndef NOUNCRYPT
     char source[12];
@@ -1066,19 +1487,17 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
 
     if (file==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
     if (!s->current_file_ok)
         return UNZ_PARAMERROR;
 
     if (s->pfile_in_zip_read != NULL)
         unzCloseCurrentFile(file);
 
-    if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
-                &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
+    if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
         return UNZ_BADZIPFILE;
 
-    pfile_in_zip_read_info = (file_in_zip_read_info_s*)
-                                        ALLOC(sizeof(file_in_zip_read_info_s));
+    pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));
     if (pfile_in_zip_read_info==NULL)
         return UNZ_INTERNALERROR;
 
@@ -1111,31 +1530,60 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
     }
 
     if ((s->cur_file_info.compression_method!=0) &&
+/* #ifdef HAVE_BZIP2 */
+        (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
+/* #endif */
         (s->cur_file_info.compression_method!=Z_DEFLATED))
+
         err=UNZ_BADZIPFILE;
 
     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
     pfile_in_zip_read_info->crc32=0;
-    pfile_in_zip_read_info->compression_method =
-            s->cur_file_info.compression_method;
+    pfile_in_zip_read_info->total_out_64=0;
+    pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;
     pfile_in_zip_read_info->filestream=s->filestream;
     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
 
     pfile_in_zip_read_info->stream.total_out = 0;
 
-    if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
-        (!raw))
+    if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw))
     {
+#ifdef HAVE_BZIP2
+      pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
+      pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
+      pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
+      pfile_in_zip_read_info->bstream.state = (voidpf)0;
+
       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
       pfile_in_zip_read_info->stream.zfree = (free_func)0;
       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
       pfile_in_zip_read_info->stream.next_in = (voidpf)0;
       pfile_in_zip_read_info->stream.avail_in = 0;
 
+      err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
+      if (err == Z_OK)
+        pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED;
+      else
+      {
+        TRYFREE(pfile_in_zip_read_info);
+        return err;
+      }
+#else
+      pfile_in_zip_read_info->raw=1;
+#endif
+    }
+    else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))
+    {
+      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+      pfile_in_zip_read_info->stream.zfree = (free_func)0;
+      pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+      pfile_in_zip_read_info->stream.next_in = 0;
+      pfile_in_zip_read_info->stream.avail_in = 0;
+
       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
       if (err == Z_OK)
-        pfile_in_zip_read_info->stream_initialised=1;
+        pfile_in_zip_read_info->stream_initialised=Z_DEFLATED;
       else
       {
         TRYFREE(pfile_in_zip_read_info);
@@ -1162,6 +1610,7 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
 
     s->pfile_in_zip_read = pfile_in_zip_read_info;
+                s->encrypted = 0;
 
 #    ifndef NOUNCRYPT
     if (password != NULL)
@@ -1169,12 +1618,12 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
         int i;
         s->pcrc_32_tab = get_crc_table();
         init_keys(password,s->keys,s->pcrc_32_tab);
-        if (ZSEEK(s->z_filefunc, s->filestream,
+        if (ZSEEK64(s->z_filefunc, s->filestream,
                   s->pfile_in_zip_read->pos_in_zipfile +
                      s->pfile_in_zip_read->byte_before_the_zipfile,
                   SEEK_SET)!=0)
             return UNZ_INTERNALERROR;
-        if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
+        if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12)
             return UNZ_INTERNALERROR;
 
         for (i = 0; i<12; i++)
@@ -1189,28 +1638,39 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
     return UNZ_OK;
 }
 
-extern int ZEXPORT unzOpenCurrentFile (file)
-    unzFile file;
+extern int ZEXPORT unzOpenCurrentFile (unzFile file)
 {
     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
 }
 
-extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
-    unzFile file;
-    const char* password;
+extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char*  password)
 {
     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
 }
 
-extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
-    unzFile file;
-    int* method;
-    int* level;
-    int raw;
+extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw)
 {
     return unzOpenCurrentFile3(file, method, level, raw, NULL);
 }
 
+/** Addition for GDAL : START */
+
+extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file)
+{
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
+    s=(unz64_s*)file;
+    if (file==NULL)
+        return 0; //UNZ_PARAMERROR;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+    if (pfile_in_zip_read_info==NULL)
+        return 0; //UNZ_PARAMERROR;
+    return pfile_in_zip_read_info->pos_in_zipfile +
+                         pfile_in_zip_read_info->byte_before_the_zipfile;
+}
+
+/** Addition for GDAL : END */
+
 /*
   Read bytes from the current file.
   buf contain buffer where data must be copied
@@ -1221,25 +1681,22 @@ extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
   return <0 with error code if there is an error
     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
 */
-extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
-    unzFile file;
-    voidp buf;
-    unsigned len;
+extern int ZEXPORT unzReadCurrentFile  (unzFile file, voidp buf, unsigned len)
 {
     int err=UNZ_OK;
     uInt iRead = 0;
-    unz_s* s;
-    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
     if (file==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
     pfile_in_zip_read_info=s->pfile_in_zip_read;
 
     if (pfile_in_zip_read_info==NULL)
         return UNZ_PARAMERROR;
 
 
-    if ((pfile_in_zip_read_info->read_buffer == NULL))
+    if (pfile_in_zip_read_info->read_buffer == NULL)
         return UNZ_END_OF_LIST_OF_FILE;
     if (len==0)
         return 0;
@@ -1270,13 +1727,13 @@ extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
             if (uReadThis == 0)
                 return UNZ_EOF;
-            if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
+            if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
                       pfile_in_zip_read_info->filestream,
                       pfile_in_zip_read_info->pos_in_zipfile +
                          pfile_in_zip_read_info->byte_before_the_zipfile,
                          ZLIB_FILEFUNC_SEEK_SET)!=0)
                 return UNZ_ERRNO;
-            if (ZREAD(pfile_in_zip_read_info->z_filefunc,
+            if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
                       pfile_in_zip_read_info->filestream,
                       pfile_in_zip_read_info->read_buffer,
                       uReadThis)!=uReadThis)
@@ -1322,6 +1779,8 @@ extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
                 *(pfile_in_zip_read_info->stream.next_out+i) =
                         *(pfile_in_zip_read_info->stream.next_in+i);
 
+            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy;
+
             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
                                 pfile_in_zip_read_info->stream.next_out,
                                 uDoCopy);
@@ -1333,11 +1792,54 @@ extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
             pfile_in_zip_read_info->stream.total_out += uDoCopy;
             iRead += uDoCopy;
         }
-        else
+        else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED)
         {
+#ifdef HAVE_BZIP2
             uLong uTotalOutBefore,uTotalOutAfter;
             const Bytef *bufBefore;
             uLong uOutThis;
+
+            pfile_in_zip_read_info->bstream.next_in        = (char*)pfile_in_zip_read_info->stream.next_in;
+            pfile_in_zip_read_info->bstream.avail_in       = pfile_in_zip_read_info->stream.avail_in;
+            pfile_in_zip_read_info->bstream.total_in_lo32  = pfile_in_zip_read_info->stream.total_in;
+            pfile_in_zip_read_info->bstream.total_in_hi32  = 0;
+            pfile_in_zip_read_info->bstream.next_out       = (char*)pfile_in_zip_read_info->stream.next_out;
+            pfile_in_zip_read_info->bstream.avail_out      = pfile_in_zip_read_info->stream.avail_out;
+            pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;
+            pfile_in_zip_read_info->bstream.total_out_hi32 = 0;
+
+            uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;
+            bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out;
+
+            err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);
+
+            uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;
+            uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
+
+            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis));
+            pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
+            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+
+            pfile_in_zip_read_info->stream.next_in   = (Bytef*)pfile_in_zip_read_info->bstream.next_in;
+            pfile_in_zip_read_info->stream.avail_in  = pfile_in_zip_read_info->bstream.avail_in;
+            pfile_in_zip_read_info->stream.total_in  = pfile_in_zip_read_info->bstream.total_in_lo32;
+            pfile_in_zip_read_info->stream.next_out  = (Bytef*)pfile_in_zip_read_info->bstream.next_out;
+            pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;
+            pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;
+
+            if (err==BZ_STREAM_END)
+              return (iRead==0) ? UNZ_EOF : iRead;
+            if (err!=BZ_OK)
+              break;
+#endif
+        } // end Z_BZIP2ED
+        else
+        {
+            ZPOS64_T uTotalOutBefore,uTotalOutAfter;
+            const Bytef *bufBefore;
+            ZPOS64_T uOutThis;
             int flush=Z_SYNC_FLUSH;
 
             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
@@ -1357,6 +1859,8 @@ extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
             uOutThis = uTotalOutAfter-uTotalOutBefore;
 
+            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
+
             pfile_in_zip_read_info->crc32 =
                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
                         (uInt)(uOutThis));
@@ -1382,14 +1886,13 @@ extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
 /*
   Give the current position in uncompressed data
 */
-extern z_off_t ZEXPORT unztell (file)
-    unzFile file;
+extern z_off_t ZEXPORT unztell (unzFile file)
 {
-    unz_s* s;
-    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
     if (file==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
     pfile_in_zip_read_info=s->pfile_in_zip_read;
 
     if (pfile_in_zip_read_info==NULL)
@@ -1398,18 +1901,33 @@ extern z_off_t ZEXPORT unztell (file)
     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
 }
 
+extern ZPOS64_T ZEXPORT unztell64 (unzFile file)
+{
+
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return (ZPOS64_T)-1;
+    s=(unz64_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+    if (pfile_in_zip_read_info==NULL)
+        return (ZPOS64_T)-1;
+
+    return pfile_in_zip_read_info->total_out_64;
+}
+
 
 /*
   return 1 if the end of file was reached, 0 elsewhere
 */
-extern int ZEXPORT unzeof (file)
-    unzFile file;
+extern int ZEXPORT unzeof (unzFile file)
 {
-    unz_s* s;
-    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
     if (file==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
     pfile_in_zip_read_info=s->pfile_in_zip_read;
 
     if (pfile_in_zip_read_info==NULL)
@@ -1424,9 +1942,9 @@ extern int ZEXPORT unzeof (file)
 
 
 /*
-  Read extra field from the current file (opened by unzOpenCurrentFile)
-  This is the local-header version of the extra field (sometimes, there is
-    more info in the local-header version than in the central-header)
+Read extra field from the current file (opened by unzOpenCurrentFile)
+This is the local-header version of the extra field (sometimes, there is
+more info in the local-header version than in the central-header)
 
   if buf==NULL, it return the size of the local extra field that can be read
 
@@ -1435,19 +1953,16 @@ extern int ZEXPORT unzeof (file)
   the return value is the number of bytes copied in buf, or (if <0)
     the error code
 */
-extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
-    unzFile file;
-    voidp buf;
-    unsigned len;
+extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len)
 {
-    unz_s* s;
-    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
     uInt read_now;
-    uLong size_to_read;
+    ZPOS64_T size_to_read;
 
     if (file==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
     pfile_in_zip_read_info=s->pfile_in_zip_read;
 
     if (pfile_in_zip_read_info==NULL)
@@ -1467,14 +1982,14 @@ extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
     if (read_now==0)
         return 0;
 
-    if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
+    if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
               pfile_in_zip_read_info->filestream,
               pfile_in_zip_read_info->offset_local_extrafield +
               pfile_in_zip_read_info->pos_local_extrafield,
               ZLIB_FILEFUNC_SEEK_SET)!=0)
         return UNZ_ERRNO;
 
-    if (ZREAD(pfile_in_zip_read_info->z_filefunc,
+    if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
               pfile_in_zip_read_info->filestream,
               buf,read_now)!=read_now)
         return UNZ_ERRNO;
@@ -1483,19 +1998,18 @@ extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
 }
 
 /*
-  Close the file in zip opened with unzipOpenCurrentFile
+  Close the file in zip opened with unzOpenCurrentFile
   Return UNZ_CRCERROR if all the file was read but the CRC is not good
 */
-extern int ZEXPORT unzCloseCurrentFile (file)
-    unzFile file;
+extern int ZEXPORT unzCloseCurrentFile (unzFile file)
 {
     int err=UNZ_OK;
 
-    unz_s* s;
-    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    unz64_s* s;
+    file_in_zip64_read_info_s* pfile_in_zip_read_info;
     if (file==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
     pfile_in_zip_read_info=s->pfile_in_zip_read;
 
     if (pfile_in_zip_read_info==NULL)
@@ -1512,8 +2026,13 @@ extern int ZEXPORT unzCloseCurrentFile (file)
 
     TRYFREE(pfile_in_zip_read_info->read_buffer);
     pfile_in_zip_read_info->read_buffer = NULL;
-    if (pfile_in_zip_read_info->stream_initialised)
+    if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
         inflateEnd(&pfile_in_zip_read_info->stream);
+#ifdef HAVE_BZIP2
+    else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
+        BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
+#endif
+
 
     pfile_in_zip_read_info->stream_initialised = 0;
     TRYFREE(pfile_in_zip_read_info);
@@ -1529,29 +2048,25 @@ extern int ZEXPORT unzCloseCurrentFile (file)
   uSizeBuf is the size of the szComment buffer.
   return the number of byte copied or an error code <0
 */
-extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
-    unzFile file;
-    char *szComment;
-    uLong uSizeBuf;
+extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf)
 {
-    int err=UNZ_OK;
-    unz_s* s;
+    unz64_s* s;
     uLong uReadThis ;
     if (file==NULL)
-        return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+        return (int)UNZ_PARAMERROR;
+    s=(unz64_s*)file;
 
     uReadThis = uSizeBuf;
     if (uReadThis>s->gi.size_comment)
         uReadThis = s->gi.size_comment;
 
-    if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
+    if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
         return UNZ_ERRNO;
 
     if (uReadThis>0)
     {
       *szComment='\0';
-      if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
+      if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
         return UNZ_ERRNO;
     }
 
@@ -1561,14 +2076,13 @@ extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
 }
 
 /* Additions by RX '2004 */
-extern uLong ZEXPORT unzGetOffset (file)
-    unzFile file;
+extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file)
 {
-    unz_s* s;
+    unz64_s* s;
 
     if (file==NULL)
-          return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+          return 0; //UNZ_PARAMERROR;
+    s=(unz64_s*)file;
     if (!s->current_file_ok)
       return 0;
     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
@@ -1577,22 +2091,35 @@ extern uLong ZEXPORT unzGetOffset (file)
     return s->pos_in_central_dir;
 }
 
-extern int ZEXPORT unzSetOffset (file, pos)
-        unzFile file;
-        uLong pos;
+extern uLong ZEXPORT unzGetOffset (unzFile file)
+{
+    ZPOS64_T offset64;
+
+    if (file==NULL)
+          return 0; //UNZ_PARAMERROR;
+    offset64 = unzGetOffset64(file);
+    return (uLong)offset64;
+}
+
+extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos)
 {
-    unz_s* s;
+    unz64_s* s;
     int err;
 
     if (file==NULL)
         return UNZ_PARAMERROR;
-    s=(unz_s*)file;
+    s=(unz64_s*)file;
 
     s->pos_in_central_dir = pos;
     s->num_file = s->gi.number_entry;      /* hack */
-    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
                                               &s->cur_file_info_internal,
                                               NULL,0,NULL,0,NULL,0);
     s->current_file_ok = (err == UNZ_OK);
     return err;
 }
+
+extern int ZEXPORT unzSetOffset (unzFile file, uLong pos)
+{
+    return unzSetOffset64(file,pos);
+}
diff --git a/third_party/zlib/contrib/minizip/unzip.h b/third_party/zlib/contrib/minizip/unzip.h
index 6a7e155..2104e39 100644
--- a/third_party/zlib/contrib/minizip/unzip.h
+++ b/third_party/zlib/contrib/minizip/unzip.h
@@ -1,20 +1,20 @@
 /* unzip.h -- IO for uncompress .zip files using zlib
-   Version 1.01e, February 12th, 2005
+   Version 1.1, February 14h, 2010
+   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
 
-   Copyright (C) 1998-2005 Gilles Vollant
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
 
-   This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
-     WinZip, InfoZip tools and compatible.
+         Modifications of Unzip for Zip64
+         Copyright (C) 2007-2008 Even Rouault
 
-   Multi volume ZipFile (span) are not supported.
-   Encryption compatible with pkzip 2.04g only supported
-   Old compressions used by old PKZip 1.x are not supported
+         Modifications for Zip64 support on both zip and unzip
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
 
+         For more info read MiniZip_info.txt
 
-   I WAIT FEEDBACK at mail info at winimage.com
-   Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
+         ---------------------------------------------------------------------------------
 
-   Condition of use and distribution are the same than zlib :
+        Condition of use and distribution are the same than zlib :
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -32,18 +32,16 @@
      misrepresented as being the original software.
   3. This notice may not be removed or altered from any source distribution.
 
+  ---------------------------------------------------------------------------------
 
-*/
+        Changes
+
+        See header of unzip64.c
 
-/* for more info about .ZIP format, see
-      http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
-      http://www.info-zip.org/pub/infozip/doc/
-   PkWare has also a specification at :
-      ftp://ftp.pkware.com/probdesc.zip
 */
 
-#ifndef _unz_H
-#define _unz_H
+#ifndef _unz64_H
+#define _unz64_H
 
 #ifdef __cplusplus
 extern "C" {
@@ -53,10 +51,16 @@ extern "C" {
 #include "zlib.h"
 #endif
 
-#ifndef _ZLIBIOAPI_H
+#ifndef  _ZLIBIOAPI_H
 #include "ioapi.h"
 #endif
 
+#ifdef HAVE_BZIP2
+#include "bzlib.h"
+#endif
+
+#define Z_BZIP2ED 12
+
 #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
 /* like the STRICT of WIN32, we define a pointer that cannot be converted
     from (void*) without cast */
@@ -89,15 +93,42 @@ typedef struct tm_unz_s
 
 /* unz_global_info structure contain global data about the ZIPfile
    These data comes from the end of central dir */
+typedef struct unz_global_info64_s
+{
+    ZPOS64_T number_entry;         /* total number of entries in
+                                     the central dir on this disk */
+    uLong size_comment;         /* size of the global comment of the zipfile */
+} unz_global_info64;
+
 typedef struct unz_global_info_s
 {
     uLong number_entry;         /* total number of entries in
-                       the central dir on this disk */
+                                     the central dir on this disk */
     uLong size_comment;         /* size of the global comment of the zipfile */
 } unz_global_info;
 
-
 /* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info64_s
+{
+    uLong version;              /* version made by                 2 bytes */
+    uLong version_needed;       /* version needed to extract       2 bytes */
+    uLong flag;                 /* general purpose bit flag        2 bytes */
+    uLong compression_method;   /* compression method              2 bytes */
+    uLong dosDate;              /* last mod file date in Dos fmt   4 bytes */
+    uLong crc;                  /* crc-32                          4 bytes */
+    ZPOS64_T compressed_size;   /* compressed size                 8 bytes */
+    ZPOS64_T uncompressed_size; /* uncompressed size               8 bytes */
+    uLong size_filename;        /* filename length                 2 bytes */
+    uLong size_file_extra;      /* extra field length              2 bytes */
+    uLong size_file_comment;    /* file comment length             2 bytes */
+
+    uLong disk_num_start;       /* disk number start               2 bytes */
+    uLong internal_fa;          /* internal file attributes        2 bytes */
+    uLong external_fa;          /* external file attributes        4 bytes */
+
+    tm_unz tmu_date;
+} unz_file_info64;
+
 typedef struct unz_file_info_s
 {
     uLong version;              /* version made by                 2 bytes */
@@ -124,15 +155,16 @@ extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
                                                  int iCaseSensitivity));
 /*
    Compare two filename (fileName1,fileName2).
-   If iCaseSensitivity = 1, comparison is case sensitive (like strcmp)
-   If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
                                 or strcasecmp)
-   If iCaseSensitivity = 0, case sensitivity is default of your operating system
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
     (like 1 on Unix, 2 on Windows)
 */
 
 
 extern unzFile ZEXPORT unzOpen OF((const char *path));
+extern unzFile ZEXPORT unzOpen64 OF((const void *path));
 /*
   Open a Zip file. path contain the full pathname (by example,
      on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
@@ -141,8 +173,14 @@ extern unzFile ZEXPORT unzOpen OF((const char *path));
        return value is NULL.
      Else, the return value is a unzFile Handle, usable with other function
        of this unzip package.
+     the "64" function take a const void* pointer, because the path is just the
+       value passed to the open64_file_func callback.
+     Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path
+       is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char*
+       does not describe the reality
 */
 
+
 extern unzFile ZEXPORT unzOpen2 OF((const char *path,
                                     zlib_filefunc_def* pzlib_filefunc_def));
 /*
@@ -150,15 +188,25 @@ extern unzFile ZEXPORT unzOpen2 OF((const char *path,
       for read/write the zip file (see ioapi.h)
 */
 
+extern unzFile ZEXPORT unzOpen2_64 OF((const void *path,
+                                    zlib_filefunc64_def* pzlib_filefunc_def));
+/*
+   Open a Zip file, like unz64Open, but provide a set of file low level API
+      for read/write the zip file (see ioapi.h)
+*/
+
 extern int ZEXPORT unzClose OF((unzFile file));
 /*
-  Close a ZipFile opened with unzipOpen.
+  Close a ZipFile opened with unzOpen.
   If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
-    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+    these files MUST be closed with unzCloseCurrentFile before call unzClose.
   return UNZ_OK if there is no problem. */
 
 extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
                                         unz_global_info *pglobal_info));
+
+extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file,
+                                        unz_global_info64 *pglobal_info));
 /*
   Write info about the ZipFile in the *pglobal_info structure.
   No preparation of the structure is needed
@@ -221,8 +269,31 @@ extern int ZEXPORT unzGoToFilePos(
     unzFile file,
     unz_file_pos* file_pos);
 
+typedef struct unz64_file_pos_s
+{
+    ZPOS64_T pos_in_zip_directory;   /* offset in zip file directory */
+    ZPOS64_T num_of_file;            /* # of file */
+} unz64_file_pos;
+
+extern int ZEXPORT unzGetFilePos64(
+    unzFile file,
+    unz64_file_pos* file_pos);
+
+extern int ZEXPORT unzGoToFilePos64(
+    unzFile file,
+    const unz64_file_pos* file_pos);
+
 /* ****************************************** */
 
+extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file,
+                         unz_file_info64 *pfile_info,
+                         char *szFileName,
+                         uLong fileNameBufferSize,
+                         void *extraField,
+                         uLong extraFieldBufferSize,
+                         char *szComment,
+                         uLong commentBufferSize));
+
 extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
                          unz_file_info *pfile_info,
                          char *szFileName,
@@ -244,6 +315,14 @@ extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
             (commentBufferSize is the size of the buffer)
 */
 
+
+/** Addition for GDAL : START */
+
+extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file));
+
+/** Addition for GDAL : END */
+
+
 /***************************************************************************/
 /* for reading the content of the current zipfile, you can open it, read data
    from it, and close it (you can close it before reading all the file)
@@ -312,6 +391,8 @@ extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
 */
 
 extern z_off_t ZEXPORT unztell OF((unzFile file));
+
+extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file));
 /*
   Give the current position in uncompressed data
 */
@@ -340,9 +421,11 @@ extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
 /***************************************************************************/
 
 /* Get the current file offset */
+extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file);
 extern uLong ZEXPORT unzGetOffset (unzFile file);
 
 /* Set the current file offset */
+extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos);
 extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
 
 
@@ -351,4 +434,4 @@ extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
 }
 #endif
 
-#endif /* _unz_H */
+#endif /* _unz64_H */
diff --git a/third_party/zlib/contrib/minizip/zip.c b/third_party/zlib/contrib/minizip/zip.c
index bb678ee..ea54853 100644
--- a/third_party/zlib/contrib/minizip/zip.c
+++ b/third_party/zlib/contrib/minizip/zip.c
@@ -1,12 +1,24 @@
 /* zip.c -- IO on .zip files using zlib
-   Version 1.01e, February 12th, 2005
+   Version 1.1, February 14h, 2010
+   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
 
-   27 Dec 2004 Rolf Kalbermatter
-   Modification to zipOpen2 to support globalComment retrieval.
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
 
-   Copyright (C) 1998-2005 Gilles Vollant
+         Modifications for Zip64 support
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+         For more info read MiniZip_info.txt
+
+         Changes
+   Oct-2009 - Mathias Svensson - Remove old C style function prototypes
+   Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives
+   Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions.
+   Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data
+                                 It is used when recreting zip archive with RAW when deleting items from a zip.
+                                 ZIP64 data is automaticly added to items that needs it, and existing ZIP64 data need to be removed.
+   Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required)
+   Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
 
-   Read zip.h for more info
 */
 
 
@@ -39,7 +51,7 @@
 #endif
 
 #ifndef Z_BUFSIZE
-#define Z_BUFSIZE (16384)
+#define Z_BUFSIZE (64*1024) //(16384)
 #endif
 
 #ifndef Z_MAXFILENAMEINZIP
@@ -60,6 +72,10 @@
 
 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
 
+
+// NOT sure that this work on ALL platform
+#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32))
+
 #ifndef SEEK_CUR
 #define SEEK_CUR    1
 #endif
@@ -79,8 +95,7 @@
 #  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
 #endif
 #endif
-const char zip_copyright[] =
-   " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
+const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
 
 
 #define SIZEDATA_INDATABLOCK (4096-(4*4))
@@ -88,6 +103,8 @@ const char zip_copyright[] =
 #define LOCALHEADERMAGIC    (0x04034b50)
 #define CENTRALHEADERMAGIC  (0x02014b50)
 #define ENDHEADERMAGIC      (0x06054b50)
+#define ZIP64ENDHEADERMAGIC      (0x6064b50)
+#define ZIP64ENDLOCHEADERMAGIC   (0x7064b50)
 
 #define FLAG_LOCALHEADER_OFFSET (0x06)
 #define CRC_LOCALHEADER_OFFSET  (0x0e)
@@ -99,7 +116,7 @@ typedef struct linkedlist_datablock_internal_s
   struct linkedlist_datablock_internal_s* next_datablock;
   uLong  avail_in_this_block;
   uLong  filled_in_this_block;
-  uLong  unused; /* for future use and alignment */
+  uLong  unused; /* for future use and alignement */
   unsigned char data[SIZEDATA_INDATABLOCK];
 } linkedlist_datablock_internal;
 
@@ -113,44 +130,55 @@ typedef struct linkedlist_data_s
 typedef struct
 {
     z_stream stream;            /* zLib stream structure for inflate */
+#ifdef HAVE_BZIP2
+    bz_stream bstream;          /* bzLib stream structure for bziped */
+#endif
+
     int  stream_initialised;    /* 1 is stream is initialised */
     uInt pos_in_buffered_data;  /* last written byte in buffered_data */
 
-    uLong pos_local_header;     /* offset of the local header of the file
-                                     currently writing */
+    ZPOS64_T pos_local_header;     /* offset of the local header of the file
+                                     currenty writing */
     char* central_header;       /* central header data for the current file */
+    uLong size_centralExtra;
     uLong size_centralheader;   /* size of the central header for cur file */
+    uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */
     uLong flag;                 /* flag of the file currently writing */
 
-    int  method;                /* compression method of file currently wr.*/
+    int  method;                /* compression method of file currenty wr.*/
     int  raw;                   /* 1 for directly writing raw data */
     Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
     uLong dosDate;
     uLong crc32;
     int  encrypt;
+    int  zip64;               /* Add ZIP64 extened information in the extra field */
+    ZPOS64_T pos_zip64extrainfo;
+    ZPOS64_T totalCompressedData;
+    ZPOS64_T totalUncompressedData;
 #ifndef NOCRYPT
     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
-    const unsigned long* pcrc_32_tab;
+    const z_crc_t* pcrc_32_tab;
     int crypt_header_size;
 #endif
-} curfile_info;
+} curfile64_info;
 
 typedef struct
 {
-    zlib_filefunc_def z_filefunc;
+    zlib_filefunc64_32_def z_filefunc;
     voidpf filestream;        /* io structore of the zipfile */
     linkedlist_data central_dir;/* datablock with central dir in construction*/
     int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/
-    curfile_info ci;            /* info on the file curretly writing */
+    curfile64_info ci;            /* info on the file curretly writing */
+
+    ZPOS64_T begin_pos;            /* position of the beginning of the zipfile */
+    ZPOS64_T add_position_when_writting_offset;
+    ZPOS64_T number_entry;
 
-    uLong begin_pos;            /* position of the beginning of the zipfile */
-    uLong add_position_when_writting_offset;
-    uLong number_entry;
 #ifndef NO_ADDFILEINEXISTINGZIP
     char *globalcomment;
 #endif
-} zip_internal;
 
+} zip64_internal;
 
 
 #ifndef NOCRYPT
@@ -172,8 +200,7 @@ local linkedlist_datablock_internal* allocate_new_datablock()
     return ldi;
 }
 
-local void free_datablock(ldi)
-    linkedlist_datablock_internal* ldi;
+local void free_datablock(linkedlist_datablock_internal* ldi)
 {
     while (ldi!=NULL)
     {
@@ -183,24 +210,19 @@ local void free_datablock(ldi)
     }
 }
 
-local void init_linkedlist(ll)
-    linkedlist_data* ll;
+local void init_linkedlist(linkedlist_data* ll)
 {
     ll->first_block = ll->last_block = NULL;
 }
 
-local void free_linkedlist(ll)
-    linkedlist_data* ll;
+local void free_linkedlist(linkedlist_data* ll)
 {
     free_datablock(ll->first_block);
     ll->first_block = ll->last_block = NULL;
 }
 
 
-local int add_data_in_datablock(ll,buf,len)
-    linkedlist_data* ll;
-    const void* buf;
-    uLong len;
+local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len)
 {
     linkedlist_datablock_internal* ldi;
     const unsigned char* from_copy;
@@ -258,18 +280,13 @@ local int add_data_in_datablock(ll,buf,len)
 #ifndef NO_ADDFILEINEXISTINGZIP
 /* ===========================================================================
    Inputs a long in LSB order to the given file
-   nbByte == 1, 2 or 4 (byte, short or long)
+   nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T)
 */
 
-local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def,
-                                voidpf filestream, uLong x, int nbByte));
-local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    uLong x;
-    int nbByte;
+local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte));
+local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)
 {
-    unsigned char buf[4];
+    unsigned char buf[8];
     int n;
     for (n = 0; n < nbByte; n++)
     {
@@ -284,17 +301,14 @@ local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte)
         }
       }
 
-    if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
+    if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
         return ZIP_ERRNO;
     else
         return ZIP_OK;
 }
 
-local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte));
-local void ziplocal_putValue_inmemory (dest, x, nbByte)
-    void* dest;
-    uLong x;
-    int nbByte;
+local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte));
+local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte)
 {
     unsigned char* buf=(unsigned char*)dest;
     int n;
@@ -315,14 +329,12 @@ local void ziplocal_putValue_inmemory (dest, x, nbByte)
 /****************************************************************************/
 
 
-local uLong ziplocal_TmzDateToDosDate(ptm,dosDate)
-    const tm_zip* ptm;
-    uLong dosDate;
+local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm)
 {
     uLong year = (uLong)ptm->tm_year;
-    if (year>1980)
+    if (year>=1980)
         year-=1980;
-    else if (year>80)
+    else if (year>=80)
         year-=80;
     return
       (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
@@ -332,18 +344,12 @@ local uLong ziplocal_TmzDateToDosDate(ptm,dosDate)
 
 /****************************************************************************/
 
-local int ziplocal_getByte OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    int *pi));
+local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi));
 
-local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    int *pi;
+local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi)
 {
     unsigned char c;
-    int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
+    int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
     if (err==1)
     {
         *pi = (int)c;
@@ -351,7 +357,7 @@ local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi)
     }
     else
     {
-        if (ZERROR(*pzlib_filefunc_def,filestream))
+        if (ZERROR64(*pzlib_filefunc_def,filestream))
             return ZIP_ERRNO;
         else
             return ZIP_EOF;
@@ -362,25 +368,19 @@ local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi)
 /* ===========================================================================
    Reads a long in LSB order from the given gz_stream. Sets
 */
-local int ziplocal_getShort OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    uLong *pX));
-
-local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    uLong *pX;
+local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX));
+
+local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)
 {
     uLong x ;
-    int i;
+    int i = 0;
     int err;
 
-    err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
     x = (uLong)i;
 
     if (err==ZIP_OK)
-        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+        err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
     x += ((uLong)i)<<8;
 
     if (err==ZIP_OK)
@@ -390,33 +390,27 @@ local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX)
     return err;
 }
 
-local int ziplocal_getLong OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream,
-    uLong *pX));
+local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX));
 
-local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
-    uLong *pX;
+local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)
 {
     uLong x ;
-    int i;
+    int i = 0;
     int err;
 
-    err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
     x = (uLong)i;
 
     if (err==ZIP_OK)
-        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+        err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
     x += ((uLong)i)<<8;
 
     if (err==ZIP_OK)
-        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+        err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
     x += ((uLong)i)<<16;
 
     if (err==ZIP_OK)
-        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+        err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
     x += ((uLong)i)<<24;
 
     if (err==ZIP_OK)
@@ -426,6 +420,54 @@ local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX)
     return err;
 }
 
+local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX));
+
+
+local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)
+{
+  ZPOS64_T x;
+  int i = 0;
+  int err;
+
+  err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
+  x = (ZPOS64_T)i;
+
+  if (err==ZIP_OK)
+    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
+  x += ((ZPOS64_T)i)<<8;
+
+  if (err==ZIP_OK)
+    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
+  x += ((ZPOS64_T)i)<<16;
+
+  if (err==ZIP_OK)
+    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
+  x += ((ZPOS64_T)i)<<24;
+
+  if (err==ZIP_OK)
+    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
+  x += ((ZPOS64_T)i)<<32;
+
+  if (err==ZIP_OK)
+    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
+  x += ((ZPOS64_T)i)<<40;
+
+  if (err==ZIP_OK)
+    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
+  x += ((ZPOS64_T)i)<<48;
+
+  if (err==ZIP_OK)
+    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
+  x += ((ZPOS64_T)i)<<56;
+
+  if (err==ZIP_OK)
+    *pX = x;
+  else
+    *pX = 0;
+
+  return err;
+}
+
 #ifndef BUFREADCOMMENT
 #define BUFREADCOMMENT (0x400)
 #endif
@@ -433,87 +475,391 @@ local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX)
   Locate the Central directory of a zipfile (at the end, just before
     the global comment)
 */
-local uLong ziplocal_SearchCentralDir OF((
-    const zlib_filefunc_def* pzlib_filefunc_def,
-    voidpf filestream));
+local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));
 
-local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream)
-    const zlib_filefunc_def* pzlib_filefunc_def;
-    voidpf filestream;
+local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
 {
-    unsigned char* buf;
-    uLong uSizeFile;
-    uLong uBackRead;
-    uLong uMaxBack=0xffff; /* maximum size of global comment */
-    uLong uPosFound=0;
+  unsigned char* buf;
+  ZPOS64_T uSizeFile;
+  ZPOS64_T uBackRead;
+  ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+  ZPOS64_T uPosFound=0;
+
+  if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+    return 0;
 
-    if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
-        return 0;
 
+  uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
 
-    uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
+  if (uMaxBack>uSizeFile)
+    uMaxBack = uSizeFile;
 
-    if (uMaxBack>uSizeFile)
-        uMaxBack = uSizeFile;
+  buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+  if (buf==NULL)
+    return 0;
 
-    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
-    if (buf==NULL)
-        return 0;
+  uBackRead = 4;
+  while (uBackRead<uMaxBack)
+  {
+    uLong uReadSize;
+    ZPOS64_T uReadPos ;
+    int i;
+    if (uBackRead+BUFREADCOMMENT>uMaxBack)
+      uBackRead = uMaxBack;
+    else
+      uBackRead+=BUFREADCOMMENT;
+    uReadPos = uSizeFile-uBackRead ;
+
+    uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+    if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+      break;
+
+    if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+      break;
+
+    for (i=(int)uReadSize-3; (i--)>0;)
+      if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+        ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+      {
+        uPosFound = uReadPos+i;
+        break;
+      }
+
+      if (uPosFound!=0)
+        break;
+  }
+  TRYFREE(buf);
+  return uPosFound;
+}
 
-    uBackRead = 4;
-    while (uBackRead<uMaxBack)
+/*
+Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before
+the global comment)
+*/
+local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));
+
+local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
+{
+  unsigned char* buf;
+  ZPOS64_T uSizeFile;
+  ZPOS64_T uBackRead;
+  ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+  ZPOS64_T uPosFound=0;
+  uLong uL;
+  ZPOS64_T relativeOffset;
+
+  if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+    return 0;
+
+  uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+  if (uMaxBack>uSizeFile)
+    uMaxBack = uSizeFile;
+
+  buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+  if (buf==NULL)
+    return 0;
+
+  uBackRead = 4;
+  while (uBackRead<uMaxBack)
+  {
+    uLong uReadSize;
+    ZPOS64_T uReadPos;
+    int i;
+    if (uBackRead+BUFREADCOMMENT>uMaxBack)
+      uBackRead = uMaxBack;
+    else
+      uBackRead+=BUFREADCOMMENT;
+    uReadPos = uSizeFile-uBackRead ;
+
+    uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+    if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+      break;
+
+    if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+      break;
+
+    for (i=(int)uReadSize-3; (i--)>0;)
     {
-        uLong uReadSize,uReadPos ;
-        int i;
-        if (uBackRead+BUFREADCOMMENT>uMaxBack)
-            uBackRead = uMaxBack;
-        else
-            uBackRead+=BUFREADCOMMENT;
-        uReadPos = uSizeFile-uBackRead ;
+      // Signature "0x07064b50" Zip64 end of central directory locater
+      if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
+      {
+        uPosFound = uReadPos+i;
+        break;
+      }
+    }
 
-        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
-                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
-        if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
-            break;
+      if (uPosFound!=0)
+        break;
+  }
 
-        if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
-            break;
+  TRYFREE(buf);
+  if (uPosFound == 0)
+    return 0;
 
-        for (i=(int)uReadSize-3; (i--)>0;)
-            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
-                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
-            {
-                uPosFound = uReadPos+i;
-                break;
-            }
+  /* Zip64 end of central directory locator */
+  if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
+    return 0;
+
+  /* the signature, already checked */
+  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
+    return 0;
+
+  /* number of the disk with the start of the zip64 end of  central directory */
+  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
+    return 0;
+  if (uL != 0)
+    return 0;
+
+  /* relative offset of the zip64 end of central directory record */
+  if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK)
+    return 0;
+
+  /* total number of disks */
+  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
+    return 0;
+  if (uL != 1)
+    return 0;
 
-        if (uPosFound!=0)
-            break;
+  /* Goto Zip64 end of central directory record */
+  if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
+    return 0;
+
+  /* the signature */
+  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
+    return 0;
+
+  if (uL != 0x06064b50) // signature of 'Zip64 end of central directory'
+    return 0;
+
+  return relativeOffset;
+}
+
+int LoadCentralDirectoryRecord(zip64_internal* pziinit)
+{
+  int err=ZIP_OK;
+  ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+
+  ZPOS64_T size_central_dir;     /* size of the central directory  */
+  ZPOS64_T offset_central_dir;   /* offset of start of central directory */
+  ZPOS64_T central_pos;
+  uLong uL;
+
+  uLong number_disk;          /* number of the current dist, used for
+                              spaning ZIP, unsupported, always 0*/
+  uLong number_disk_with_CD;  /* number the the disk with central dir, used
+                              for spaning ZIP, unsupported, always 0*/
+  ZPOS64_T number_entry;
+  ZPOS64_T number_entry_CD;      /* total number of entries in
+                                the central dir
+                                (same than number_entry on nospan) */
+  uLong VersionMadeBy;
+  uLong VersionNeeded;
+  uLong size_comment;
+
+  int hasZIP64Record = 0;
+
+  // check first if we find a ZIP64 record
+  central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream);
+  if(central_pos > 0)
+  {
+    hasZIP64Record = 1;
+  }
+  else if(central_pos == 0)
+  {
+    central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream);
+  }
+
+/* disable to allow appending to empty ZIP archive
+        if (central_pos==0)
+            err=ZIP_ERRNO;
+*/
+
+  if(hasZIP64Record)
+  {
+    ZPOS64_T sizeEndOfCentralDirectory;
+    if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
+      err=ZIP_ERRNO;
+
+    /* the signature, already checked */
+    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK)
+      err=ZIP_ERRNO;
+
+    /* size of zip64 end of central directory record */
+    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK)
+      err=ZIP_ERRNO;
+
+    /* version made by */
+    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK)
+      err=ZIP_ERRNO;
+
+    /* version needed to extract */
+    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK)
+      err=ZIP_ERRNO;
+
+    /* number of this disk */
+    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK)
+      err=ZIP_ERRNO;
+
+    /* number of the disk with the start of the central directory */
+    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK)
+      err=ZIP_ERRNO;
+
+    /* total number of entries in the central directory on this disk */
+    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK)
+      err=ZIP_ERRNO;
+
+    /* total number of entries in the central directory */
+    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK)
+      err=ZIP_ERRNO;
+
+    if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0))
+      err=ZIP_BADZIPFILE;
+
+    /* size of the central directory */
+    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK)
+      err=ZIP_ERRNO;
+
+    /* offset of start of central directory with respect to the
+    starting disk number */
+    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK)
+      err=ZIP_ERRNO;
+
+    // TODO..
+    // read the comment from the standard central header.
+    size_comment = 0;
+  }
+  else
+  {
+    // Read End of central Directory info
+    if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+      err=ZIP_ERRNO;
+
+    /* the signature, already checked */
+    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK)
+      err=ZIP_ERRNO;
+
+    /* number of this disk */
+    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK)
+      err=ZIP_ERRNO;
+
+    /* number of the disk with the start of the central directory */
+    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK)
+      err=ZIP_ERRNO;
+
+    /* total number of entries in the central dir on this disk */
+    number_entry = 0;
+    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
+      err=ZIP_ERRNO;
+    else
+      number_entry = uL;
+
+    /* total number of entries in the central dir */
+    number_entry_CD = 0;
+    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
+      err=ZIP_ERRNO;
+    else
+      number_entry_CD = uL;
+
+    if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0))
+      err=ZIP_BADZIPFILE;
+
+    /* size of the central directory */
+    size_central_dir = 0;
+    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
+      err=ZIP_ERRNO;
+    else
+      size_central_dir = uL;
+
+    /* offset of start of central directory with respect to the starting disk number */
+    offset_central_dir = 0;
+    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
+      err=ZIP_ERRNO;
+    else
+      offset_central_dir = uL;
+
+
+    /* zipfile global comment length */
+    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK)
+      err=ZIP_ERRNO;
+  }
+
+  if ((central_pos<offset_central_dir+size_central_dir) &&
+    (err==ZIP_OK))
+    err=ZIP_BADZIPFILE;
+
+  if (err!=ZIP_OK)
+  {
+    ZCLOSE64(pziinit->z_filefunc, pziinit->filestream);
+    return ZIP_ERRNO;
+  }
+
+  if (size_comment>0)
+  {
+    pziinit->globalcomment = (char*)ALLOC(size_comment+1);
+    if (pziinit->globalcomment)
+    {
+      size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment);
+      pziinit->globalcomment[size_comment]=0;
     }
-    TRYFREE(buf);
-    return uPosFound;
+  }
+
+  byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir);
+  pziinit->add_position_when_writting_offset = byte_before_the_zipfile;
+
+  {
+    ZPOS64_T size_central_dir_to_read = size_central_dir;
+    size_t buf_size = SIZEDATA_INDATABLOCK;
+    void* buf_read = (void*)ALLOC(buf_size);
+    if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
+      err=ZIP_ERRNO;
+
+    while ((size_central_dir_to_read>0) && (err==ZIP_OK))
+    {
+      ZPOS64_T read_this = SIZEDATA_INDATABLOCK;
+      if (read_this > size_central_dir_to_read)
+        read_this = size_central_dir_to_read;
+
+      if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this)
+        err=ZIP_ERRNO;
+
+      if (err==ZIP_OK)
+        err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this);
+
+      size_central_dir_to_read-=read_this;
+    }
+    TRYFREE(buf_read);
+  }
+  pziinit->begin_pos = byte_before_the_zipfile;
+  pziinit->number_entry = number_entry_CD;
+
+  if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0)
+    err=ZIP_ERRNO;
+
+  return err;
 }
+
+
 #endif /* !NO_ADDFILEINEXISTINGZIP*/
 
+
 /************************************************************/
-extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def)
-    const char *pathname;
-    int append;
-    zipcharpc* globalcomment;
-    zlib_filefunc_def* pzlib_filefunc_def;
+extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def)
 {
-    zip_internal ziinit;
-    zip_internal* zi;
+    zip64_internal ziinit;
+    zip64_internal* zi;
     int err=ZIP_OK;
 
-
-    if (pzlib_filefunc_def==NULL)
-        fill_fopen_filefunc(&ziinit.z_filefunc);
+    ziinit.z_filefunc.zseek32_file = NULL;
+    ziinit.z_filefunc.ztell32_file = NULL;
+    if (pzlib_filefunc64_32_def==NULL)
+        fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64);
     else
-        ziinit.z_filefunc = *pzlib_filefunc_def;
+        ziinit.z_filefunc = *pzlib_filefunc64_32_def;
 
-    ziinit.filestream = (*(ziinit.z_filefunc.zopen_file))
-                 (ziinit.z_filefunc.opaque,
+    ziinit.filestream = ZOPEN64(ziinit.z_filefunc,
                   pathname,
                   (append == APPEND_STATUS_CREATE) ?
                   (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :
@@ -521,7 +867,11 @@ extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc
 
     if (ziinit.filestream == NULL)
         return NULL;
-    ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream);
+
+    if (append == APPEND_STATUS_CREATEAFTER)
+        ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END);
+
+    ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream);
     ziinit.in_opened_file_inzip = 0;
     ziinit.ci.stream_initialised = 0;
     ziinit.number_entry = 0;
@@ -529,10 +879,11 @@ extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc
     init_linkedlist(&(ziinit.central_dir));
 
 
-    zi = (zip_internal*)ALLOC(sizeof(zip_internal));
+
+    zi = (zip64_internal*)ALLOC(sizeof(zip64_internal));
     if (zi==NULL)
     {
-        ZCLOSE(ziinit.z_filefunc,ziinit.filestream);
+        ZCLOSE64(ziinit.z_filefunc,ziinit.filestream);
         return NULL;
     }
 
@@ -541,122 +892,8 @@ extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc
     ziinit.globalcomment = NULL;
     if (append == APPEND_STATUS_ADDINZIP)
     {
-        uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
-
-        uLong size_central_dir;     /* size of the central directory  */
-        uLong offset_central_dir;   /* offset of start of central directory */
-        uLong central_pos,uL;
-
-        uLong number_disk;          /* number of the current dist, used for
-                                    spaning ZIP, unsupported, always 0*/
-        uLong number_disk_with_CD;  /* number the the disk with central dir, used
-                                    for spaning ZIP, unsupported, always 0*/
-        uLong number_entry;
-        uLong number_entry_CD;      /* total number of entries in
-                                    the central dir
-                                    (same than number_entry on nospan) */
-        uLong size_comment;
-
-        central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream);
-        if (central_pos==0)
-            err=ZIP_ERRNO;
-
-        if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
-                                        central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
-            err=ZIP_ERRNO;
-
-        /* the signature, already checked */
-        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        /* number of this disk */
-        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        /* number of the disk with the start of the central directory */
-        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        /* total number of entries in the central dir on this disk */
-        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        /* total number of entries in the central dir */
-        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        if ((number_entry_CD!=number_entry) ||
-            (number_disk_with_CD!=0) ||
-            (number_disk!=0))
-            err=ZIP_BADZIPFILE;
-
-        /* size of the central directory */
-        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        /* offset of start of central directory with respect to the
-            starting disk number */
-        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        /* zipfile global comment length */
-        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK)
-            err=ZIP_ERRNO;
-
-        if ((central_pos<offset_central_dir+size_central_dir) &&
-            (err==ZIP_OK))
-            err=ZIP_BADZIPFILE;
-
-        if (err!=ZIP_OK)
-        {
-            ZCLOSE(ziinit.z_filefunc, ziinit.filestream);
-            return NULL;
-        }
-
-        if (size_comment>0)
-        {
-            ziinit.globalcomment = ALLOC(size_comment+1);
-            if (ziinit.globalcomment)
-            {
-               size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment);
-               ziinit.globalcomment[size_comment]=0;
-            }
-        }
-
-        byte_before_the_zipfile = central_pos -
-                                (offset_central_dir+size_central_dir);
-        ziinit.add_position_when_writting_offset = byte_before_the_zipfile;
-
-        {
-            uLong size_central_dir_to_read = size_central_dir;
-            size_t buf_size = SIZEDATA_INDATABLOCK;
-            void* buf_read = (void*)ALLOC(buf_size);
-            if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
-                  offset_central_dir + byte_before_the_zipfile,
-                  ZLIB_FILEFUNC_SEEK_SET) != 0)
-                  err=ZIP_ERRNO;
-
-            while ((size_central_dir_to_read>0) && (err==ZIP_OK))
-            {
-                uLong read_this = SIZEDATA_INDATABLOCK;
-                if (read_this > size_central_dir_to_read)
-                    read_this = size_central_dir_to_read;
-                if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this)
-                    err=ZIP_ERRNO;
-
-                if (err==ZIP_OK)
-                    err = add_data_in_datablock(&ziinit.central_dir,buf_read,
-                                                (uLong)read_this);
-                size_central_dir_to_read-=read_this;
-            }
-            TRYFREE(buf_read);
-        }
-        ziinit.begin_pos = byte_before_the_zipfile;
-        ziinit.number_entry = number_entry_CD;
-
-        if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
-                  offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
-            err=ZIP_ERRNO;
+      // Read and Cache Central Directory Records
+      err = LoadCentralDirectoryRecord(&ziinit);
     }
 
     if (globalcomment)
@@ -680,53 +917,173 @@ extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc
     }
 }
 
-extern zipFile ZEXPORT zipOpen (pathname, append)
-    const char *pathname;
-    int append;
+extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def)
 {
-    return zipOpen2(pathname,append,NULL,NULL);
+    if (pzlib_filefunc32_def != NULL)
+    {
+        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
+        fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
+        return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
+    }
+    else
+        return zipOpen3(pathname, append, globalcomment, NULL);
 }
 
-extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
-                                         extrafield_local, size_extrafield_local,
-                                         extrafield_global, size_extrafield_global,
-                                         comment, method, level, raw,
-                                         windowBits, memLevel, strategy,
-                                         password, crcForCrypting)
-    zipFile file;
-    const char* filename;
-    const zip_fileinfo* zipfi;
-    const void* extrafield_local;
-    uInt size_extrafield_local;
-    const void* extrafield_global;
-    uInt size_extrafield_global;
-    const char* comment;
-    int method;
-    int level;
-    int raw;
-    int windowBits;
-    int memLevel;
-    int strategy;
-    const char* password;
-    uLong crcForCrypting;
+extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def)
+{
+    if (pzlib_filefunc_def != NULL)
+    {
+        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
+        zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
+        zlib_filefunc64_32_def_fill.ztell32_file = NULL;
+        zlib_filefunc64_32_def_fill.zseek32_file = NULL;
+        return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
+    }
+    else
+        return zipOpen3(pathname, append, globalcomment, NULL);
+}
+
+
+
+extern zipFile ZEXPORT zipOpen (const char* pathname, int append)
 {
-    zip_internal* zi;
+    return zipOpen3((const void*)pathname,append,NULL,NULL);
+}
+
+extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append)
+{
+    return zipOpen3(pathname,append,NULL,NULL);
+}
+
+int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local)
+{
+  /* write the local header */
+  int err;
+  uInt size_filename = (uInt)strlen(filename);
+  uInt size_extrafield = size_extrafield_local;
+
+  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4);
+
+  if (err==ZIP_OK)
+  {
+    if(zi->ci.zip64)
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */
+    else
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
+  }
+
+  if (err==ZIP_OK)
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
+
+  if (err==ZIP_OK)
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
+
+  if (err==ZIP_OK)
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
+
+  // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later
+  if (err==ZIP_OK)
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
+  if (err==ZIP_OK)
+  {
+    if(zi->ci.zip64)
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */
+    else
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
+  }
+  if (err==ZIP_OK)
+  {
+    if(zi->ci.zip64)
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */
+    else
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
+  }
+
+  if (err==ZIP_OK)
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
+
+  if(zi->ci.zip64)
+  {
+    size_extrafield += 20;
+  }
+
+  if (err==ZIP_OK)
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2);
+
+  if ((err==ZIP_OK) && (size_filename > 0))
+  {
+    if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
+      err = ZIP_ERRNO;
+  }
+
+  if ((err==ZIP_OK) && (size_extrafield_local > 0))
+  {
+    if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local)
+      err = ZIP_ERRNO;
+  }
+
+
+  if ((err==ZIP_OK) && (zi->ci.zip64))
+  {
+      // write the Zip64 extended info
+      short HeaderID = 1;
+      short DataSize = 16;
+      ZPOS64_T CompressedSize = 0;
+      ZPOS64_T UncompressedSize = 0;
+
+      // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file)
+      zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream);
+
+      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2);
+      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2);
+
+      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8);
+      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8);
+  }
+
+  return err;
+}
+
+/*
+ NOTE.
+ When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped
+ before calling this function it can be done with zipRemoveExtraInfoBlock
+
+ It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize
+ unnecessary allocations.
+ */
+extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi,
+                                         const void* extrafield_local, uInt size_extrafield_local,
+                                         const void* extrafield_global, uInt size_extrafield_global,
+                                         const char* comment, int method, int level, int raw,
+                                         int windowBits,int memLevel, int strategy,
+                                         const char* password, uLong crcForCrypting,
+                                         uLong versionMadeBy, uLong flagBase, int zip64)
+{
+    zip64_internal* zi;
     uInt size_filename;
     uInt size_comment;
     uInt i;
     int err = ZIP_OK;
 
 #    ifdef NOCRYPT
+    (crcForCrypting);
     if (password != NULL)
         return ZIP_PARAMERROR;
 #    endif
 
     if (file == NULL)
         return ZIP_PARAMERROR;
+
+#ifdef HAVE_BZIP2
+    if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED))
+      return ZIP_PARAMERROR;
+#else
     if ((method!=0) && (method!=Z_DEFLATED))
-        return ZIP_PARAMERROR;
+      return ZIP_PARAMERROR;
+#endif
 
-    zi = (zip_internal*)file;
+    zi = (zip64_internal*)file;
 
     if (zi->in_opened_file_inzip == 1)
     {
@@ -735,7 +1092,6 @@ extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
             return err;
     }
 
-
     if (filename==NULL)
         filename="-";
 
@@ -752,15 +1108,16 @@ extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
     {
         if (zipfi->dosDate != 0)
             zi->ci.dosDate = zipfi->dosDate;
-        else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
+        else
+          zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date);
     }
 
-    zi->ci.flag = 0;
+    zi->ci.flag = flagBase;
     if ((level==8) || (level==9))
       zi->ci.flag |= 2;
-    if ((level==2))
+    if (level==2)
       zi->ci.flag |= 4;
-    if ((level==1))
+    if (level==1)
       zi->ci.flag |= 6;
     if (password != NULL)
       zi->ci.flag |= 1;
@@ -771,37 +1128,43 @@ extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
     zi->ci.stream_initialised = 0;
     zi->ci.pos_in_buffered_data = 0;
     zi->ci.raw = raw;
-    zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ;
-    zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename +
-                                      size_extrafield_global + size_comment;
-    zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
+    zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream);
+
+    zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment;
+    zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data
 
-    ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
+    zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree);
+
+    zi->ci.size_centralExtra = size_extrafield_global;
+    zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
     /* version info */
-    ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
-    ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
-    ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
-    ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
-    ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
+    zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2);
+    zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
+    zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
+    zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
+    zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
+    zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
+    zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
+    zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
+    zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
+    zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
+    zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
+    zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
 
     if (zipfi==NULL)
-        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
+        zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
     else
-        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
+        zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
 
     if (zipfi==NULL)
-        ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
+        zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
     else
-        ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
+        zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
 
-    ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4);
+    if(zi->ci.pos_local_header >= 0xffffffff)
+      zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4);
+    else
+      zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset,4);
 
     for (i=0;i<size_filename;i++)
         *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
@@ -816,63 +1179,66 @@ extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
     if (zi->ci.central_header == NULL)
         return ZIP_INTERNALERROR;
 
-    /* write the local header */
-    err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4);
-
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
-
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
-
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
-
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
-
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
-
-    if (err==ZIP_OK)
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2);
-
-    if ((err==ZIP_OK) && (size_filename>0))
-        if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
-                err = ZIP_ERRNO;
-
-    if ((err==ZIP_OK) && (size_extrafield_local>0))
-        if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local)
-                                                                           !=size_extrafield_local)
-                err = ZIP_ERRNO;
+    zi->ci.zip64 = zip64;
+    zi->ci.totalCompressedData = 0;
+    zi->ci.totalUncompressedData = 0;
+    zi->ci.pos_zip64extrainfo = 0;
+
+    err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local);
+
+#ifdef HAVE_BZIP2
+    zi->ci.bstream.avail_in = (uInt)0;
+    zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
+    zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
+    zi->ci.bstream.total_in_hi32 = 0;
+    zi->ci.bstream.total_in_lo32 = 0;
+    zi->ci.bstream.total_out_hi32 = 0;
+    zi->ci.bstream.total_out_lo32 = 0;
+#endif
 
     zi->ci.stream.avail_in = (uInt)0;
     zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
     zi->ci.stream.next_out = zi->ci.buffered_data;
     zi->ci.stream.total_in = 0;
     zi->ci.stream.total_out = 0;
+    zi->ci.stream.data_type = Z_BINARY;
 
+#ifdef HAVE_BZIP2
+    if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
+#else
     if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
+#endif
     {
-        zi->ci.stream.zalloc = (alloc_func)0;
-        zi->ci.stream.zfree = (free_func)0;
-        zi->ci.stream.opaque = (voidpf)0;
+        if(zi->ci.method == Z_DEFLATED)
+        {
+          zi->ci.stream.zalloc = (alloc_func)0;
+          zi->ci.stream.zfree = (free_func)0;
+          zi->ci.stream.opaque = (voidpf)0;
 
-        if (windowBits>0)
-            windowBits = -windowBits;
+          if (windowBits>0)
+              windowBits = -windowBits;
 
-        err = deflateInit2(&zi->ci.stream, level,
-               Z_DEFLATED, windowBits, memLevel, strategy);
+          err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy);
+
+          if (err==Z_OK)
+              zi->ci.stream_initialised = Z_DEFLATED;
+        }
+        else if(zi->ci.method == Z_BZIP2ED)
+        {
+#ifdef HAVE_BZIP2
+            // Init BZip stuff here
+          zi->ci.bstream.bzalloc = 0;
+          zi->ci.bstream.bzfree = 0;
+          zi->ci.bstream.opaque = (voidpf)0;
+
+          err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35);
+          if(err == BZ_OK)
+            zi->ci.stream_initialised = Z_BZIP2ED;
+#endif
+        }
 
-        if (err==Z_OK)
-            zi->ci.stream_initialised = 1;
     }
+
 #    ifndef NOCRYPT
     zi->ci.crypt_header_size = 0;
     if ((err==Z_OK) && (password != NULL))
@@ -886,7 +1252,7 @@ extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
         sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
         zi->ci.crypt_header_size = sizeHead;
 
-        if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
+        if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
                 err = ZIP_ERRNO;
     }
 #    endif
@@ -896,53 +1262,105 @@ extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
     return err;
 }
 
-extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi,
-                                        extrafield_local, size_extrafield_local,
-                                        extrafield_global, size_extrafield_global,
-                                        comment, method, level, raw)
-    zipFile file;
-    const char* filename;
-    const zip_fileinfo* zipfi;
-    const void* extrafield_local;
-    uInt size_extrafield_local;
-    const void* extrafield_global;
-    uInt size_extrafield_global;
-    const char* comment;
-    int method;
-    int level;
-    int raw;
+extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi,
+                                         const void* extrafield_local, uInt size_extrafield_local,
+                                         const void* extrafield_global, uInt size_extrafield_global,
+                                         const char* comment, int method, int level, int raw,
+                                         int windowBits,int memLevel, int strategy,
+                                         const char* password, uLong crcForCrypting,
+                                         uLong versionMadeBy, uLong flagBase)
+{
+    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
+                                 extrafield_local, size_extrafield_local,
+                                 extrafield_global, size_extrafield_global,
+                                 comment, method, level, raw,
+                                 windowBits, memLevel, strategy,
+                                 password, crcForCrypting, versionMadeBy, flagBase, 0);
+}
+
+extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi,
+                                         const void* extrafield_local, uInt size_extrafield_local,
+                                         const void* extrafield_global, uInt size_extrafield_global,
+                                         const char* comment, int method, int level, int raw,
+                                         int windowBits,int memLevel, int strategy,
+                                         const char* password, uLong crcForCrypting)
+{
+    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
+                                 extrafield_local, size_extrafield_local,
+                                 extrafield_global, size_extrafield_global,
+                                 comment, method, level, raw,
+                                 windowBits, memLevel, strategy,
+                                 password, crcForCrypting, VERSIONMADEBY, 0, 0);
+}
+
+extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
+                                         const void* extrafield_local, uInt size_extrafield_local,
+                                         const void* extrafield_global, uInt size_extrafield_global,
+                                         const char* comment, int method, int level, int raw,
+                                         int windowBits,int memLevel, int strategy,
+                                         const char* password, uLong crcForCrypting, int zip64)
+{
+    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
+                                 extrafield_local, size_extrafield_local,
+                                 extrafield_global, size_extrafield_global,
+                                 comment, method, level, raw,
+                                 windowBits, memLevel, strategy,
+                                 password, crcForCrypting, VERSIONMADEBY, 0, zip64);
+}
+
+extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi,
+                                        const void* extrafield_local, uInt size_extrafield_local,
+                                        const void* extrafield_global, uInt size_extrafield_global,
+                                        const char* comment, int method, int level, int raw)
 {
-    return zipOpenNewFileInZip3 (file, filename, zipfi,
+    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
                                  extrafield_local, size_extrafield_local,
                                  extrafield_global, size_extrafield_global,
                                  comment, method, level, raw,
                                  -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
-                                 NULL, 0);
+                                 NULL, 0, VERSIONMADEBY, 0, 0);
 }
 
-extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi,
-                                        extrafield_local, size_extrafield_local,
-                                        extrafield_global, size_extrafield_global,
-                                        comment, method, level)
-    zipFile file;
-    const char* filename;
-    const zip_fileinfo* zipfi;
-    const void* extrafield_local;
-    uInt size_extrafield_local;
-    const void* extrafield_global;
-    uInt size_extrafield_global;
-    const char* comment;
-    int method;
-    int level;
+extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
+                                        const void* extrafield_local, uInt size_extrafield_local,
+                                        const void* extrafield_global, uInt size_extrafield_global,
+                                        const char* comment, int method, int level, int raw, int zip64)
 {
-    return zipOpenNewFileInZip2 (file, filename, zipfi,
+    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
                                  extrafield_local, size_extrafield_local,
                                  extrafield_global, size_extrafield_global,
-                                 comment, method, level, 0);
+                                 comment, method, level, raw,
+                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
+                                 NULL, 0, VERSIONMADEBY, 0, zip64);
 }
 
-local int zipFlushWriteBuffer(zi)
-  zip_internal* zi;
+extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi,
+                                        const void* extrafield_local, uInt size_extrafield_local,
+                                        const void*extrafield_global, uInt size_extrafield_global,
+                                        const char* comment, int method, int level, int zip64)
+{
+    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
+                                 extrafield_local, size_extrafield_local,
+                                 extrafield_global, size_extrafield_global,
+                                 comment, method, level, 0,
+                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
+                                 NULL, 0, VERSIONMADEBY, 0, zip64);
+}
+
+extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi,
+                                        const void* extrafield_local, uInt size_extrafield_local,
+                                        const void*extrafield_global, uInt size_extrafield_global,
+                                        const char* comment, int method, int level)
+{
+    return zipOpenNewFileInZip4_64 (file, filename, zipfi,
+                                 extrafield_local, size_extrafield_local,
+                                 extrafield_global, size_extrafield_global,
+                                 comment, method, level, 0,
+                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
+                                 NULL, 0, VERSIONMADEBY, 0, 0);
+}
+
+local int zip64FlushWriteBuffer(zip64_internal* zi)
 {
     int err=ZIP_OK;
 
@@ -952,169 +1370,374 @@ local int zipFlushWriteBuffer(zi)
         uInt i;
         int t;
         for (i=0;i<zi->ci.pos_in_buffered_data;i++)
-            zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab,
-                                       zi->ci.buffered_data[i],t);
+            zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t);
 #endif
     }
-    if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data)
-                                                                    !=zi->ci.pos_in_buffered_data)
+
+    if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data)
       err = ZIP_ERRNO;
+
+    zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data;
+
+#ifdef HAVE_BZIP2
+    if(zi->ci.method == Z_BZIP2ED)
+    {
+      zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32;
+      zi->ci.bstream.total_in_lo32 = 0;
+      zi->ci.bstream.total_in_hi32 = 0;
+    }
+    else
+#endif
+    {
+      zi->ci.totalUncompressedData += zi->ci.stream.total_in;
+      zi->ci.stream.total_in = 0;
+    }
+
+
     zi->ci.pos_in_buffered_data = 0;
+
     return err;
 }
 
-extern int ZEXPORT zipWriteInFileInZip (file, buf, len)
-    zipFile file;
-    const void* buf;
-    unsigned len;
+extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len)
 {
-    zip_internal* zi;
+    zip64_internal* zi;
     int err=ZIP_OK;
 
     if (file == NULL)
         return ZIP_PARAMERROR;
-    zi = (zip_internal*)file;
+    zi = (zip64_internal*)file;
 
     if (zi->in_opened_file_inzip == 0)
         return ZIP_PARAMERROR;
 
-    zi->ci.stream.next_in = (void*)buf;
-    zi->ci.stream.avail_in = len;
-    zi->ci.crc32 = crc32(zi->ci.crc32,buf,len);
+    zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len);
 
-    while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
+#ifdef HAVE_BZIP2
+    if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw))
     {
-        if (zi->ci.stream.avail_out == 0)
+      zi->ci.bstream.next_in = (void*)buf;
+      zi->ci.bstream.avail_in = len;
+      err = BZ_RUN_OK;
+
+      while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0))
+      {
+        if (zi->ci.bstream.avail_out == 0)
         {
-            if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
-                err = ZIP_ERRNO;
-            zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
-            zi->ci.stream.next_out = zi->ci.buffered_data;
+          if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
+            err = ZIP_ERRNO;
+          zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
+          zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
         }
 
 
-        if(err != ZIP_OK)
-            break;
+        if(err != BZ_RUN_OK)
+          break;
 
-        if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
+        if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
         {
-            uLong uTotalOutBefore = zi->ci.stream.total_out;
-            err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
-            zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
+          uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32;
+//          uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32;
+          err=BZ2_bzCompress(&zi->ci.bstream,  BZ_RUN);
 
+          zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ;
         }
-        else
-        {
-            uInt copy_this,i;
-            if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
-                copy_this = zi->ci.stream.avail_in;
-            else
-                copy_this = zi->ci.stream.avail_out;
-            for (i=0;i<copy_this;i++)
-                *(((char*)zi->ci.stream.next_out)+i) =
-                    *(((const char*)zi->ci.stream.next_in)+i);
-            {
-                zi->ci.stream.avail_in -= copy_this;
-                zi->ci.stream.avail_out-= copy_this;
-                zi->ci.stream.next_in+= copy_this;
-                zi->ci.stream.next_out+= copy_this;
-                zi->ci.stream.total_in+= copy_this;
-                zi->ci.stream.total_out+= copy_this;
-                zi->ci.pos_in_buffered_data += copy_this;
-            }
-        }
+      }
+
+      if(err == BZ_RUN_OK)
+        err = ZIP_OK;
+    }
+    else
+#endif
+    {
+      zi->ci.stream.next_in = (Bytef*)buf;
+      zi->ci.stream.avail_in = len;
+
+      while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
+      {
+          if (zi->ci.stream.avail_out == 0)
+          {
+              if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
+                  err = ZIP_ERRNO;
+              zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
+              zi->ci.stream.next_out = zi->ci.buffered_data;
+          }
+
+
+          if(err != ZIP_OK)
+              break;
+
+          if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
+          {
+              uLong uTotalOutBefore = zi->ci.stream.total_out;
+              err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
+              if(uTotalOutBefore > zi->ci.stream.total_out)
+              {
+                int bBreak = 0;
+                bBreak++;
+              }
+
+              zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
+          }
+          else
+          {
+              uInt copy_this,i;
+              if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
+                  copy_this = zi->ci.stream.avail_in;
+              else
+                  copy_this = zi->ci.stream.avail_out;
+
+              for (i = 0; i < copy_this; i++)
+                  *(((char*)zi->ci.stream.next_out)+i) =
+                      *(((const char*)zi->ci.stream.next_in)+i);
+              {
+                  zi->ci.stream.avail_in -= copy_this;
+                  zi->ci.stream.avail_out-= copy_this;
+                  zi->ci.stream.next_in+= copy_this;
+                  zi->ci.stream.next_out+= copy_this;
+                  zi->ci.stream.total_in+= copy_this;
+                  zi->ci.stream.total_out+= copy_this;
+                  zi->ci.pos_in_buffered_data += copy_this;
+              }
+          }
+      }// while(...)
     }
 
     return err;
 }
 
-extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32)
-    zipFile file;
-    uLong uncompressed_size;
-    uLong crc32;
+extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32)
+{
+    return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32);
+}
+
+extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32)
 {
-    zip_internal* zi;
-    uLong compressed_size;
+    zip64_internal* zi;
+    ZPOS64_T compressed_size;
+    uLong invalidValue = 0xffffffff;
+    short datasize = 0;
     int err=ZIP_OK;
 
     if (file == NULL)
         return ZIP_PARAMERROR;
-    zi = (zip_internal*)file;
+    zi = (zip64_internal*)file;
 
     if (zi->in_opened_file_inzip == 0)
         return ZIP_PARAMERROR;
     zi->ci.stream.avail_in = 0;
 
     if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
-        while (err==ZIP_OK)
+                {
+                        while (err==ZIP_OK)
+                        {
+                                uLong uTotalOutBefore;
+                                if (zi->ci.stream.avail_out == 0)
+                                {
+                                        if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
+                                                err = ZIP_ERRNO;
+                                        zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
+                                        zi->ci.stream.next_out = zi->ci.buffered_data;
+                                }
+                                uTotalOutBefore = zi->ci.stream.total_out;
+                                err=deflate(&zi->ci.stream,  Z_FINISH);
+                                zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
+                        }
+                }
+    else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
     {
+#ifdef HAVE_BZIP2
+      err = BZ_FINISH_OK;
+      while (err==BZ_FINISH_OK)
+      {
         uLong uTotalOutBefore;
-        if (zi->ci.stream.avail_out == 0)
+        if (zi->ci.bstream.avail_out == 0)
         {
-            if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
-                err = ZIP_ERRNO;
-            zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
-            zi->ci.stream.next_out = zi->ci.buffered_data;
+          if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
+            err = ZIP_ERRNO;
+          zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
+          zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
         }
-        uTotalOutBefore = zi->ci.stream.total_out;
-        err=deflate(&zi->ci.stream,  Z_FINISH);
-        zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
+        uTotalOutBefore = zi->ci.bstream.total_out_lo32;
+        err=BZ2_bzCompress(&zi->ci.bstream,  BZ_FINISH);
+        if(err == BZ_STREAM_END)
+          err = Z_STREAM_END;
+
+        zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore);
+      }
+
+      if(err == BZ_FINISH_OK)
+        err = ZIP_OK;
+#endif
     }
 
     if (err==Z_STREAM_END)
         err=ZIP_OK; /* this is normal */
 
     if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
-        if (zipFlushWriteBuffer(zi)==ZIP_ERRNO)
+                {
+        if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO)
             err = ZIP_ERRNO;
+                }
 
     if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
     {
-        err=deflateEnd(&zi->ci.stream);
+        int tmp_err = deflateEnd(&zi->ci.stream);
+        if (err == ZIP_OK)
+            err = tmp_err;
         zi->ci.stream_initialised = 0;
     }
+#ifdef HAVE_BZIP2
+    else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
+    {
+      int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream);
+                        if (err==ZIP_OK)
+                                err = tmperr;
+                        zi->ci.stream_initialised = 0;
+    }
+#endif
 
     if (!zi->ci.raw)
     {
         crc32 = (uLong)zi->ci.crc32;
-        uncompressed_size = (uLong)zi->ci.stream.total_in;
+        uncompressed_size = zi->ci.totalUncompressedData;
     }
-    compressed_size = (uLong)zi->ci.stream.total_out;
+    compressed_size = zi->ci.totalCompressedData;
+
 #    ifndef NOCRYPT
     compressed_size += zi->ci.crypt_header_size;
 #    endif
 
-    ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
-    ziplocal_putValue_inmemory(zi->ci.central_header+20,
-                                compressed_size,4); /*compr size*/
+    // update Current Item crc and sizes,
+    if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff)
+    {
+      /*version Made by*/
+      zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2);
+      /*version needed*/
+      zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2);
+
+    }
+
+    zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
+
+
+    if(compressed_size >= 0xffffffff)
+      zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/
+    else
+      zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/
+
+    /// set internal file attributes field
     if (zi->ci.stream.data_type == Z_ASCII)
-        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
-    ziplocal_putValue_inmemory(zi->ci.central_header+24,
-                                uncompressed_size,4); /*uncompr size*/
+        zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
+
+    if(uncompressed_size >= 0xffffffff)
+      zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/
+    else
+      zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/
+
+    // Add ZIP64 extra info field for uncompressed size
+    if(uncompressed_size >= 0xffffffff)
+      datasize += 8;
+
+    // Add ZIP64 extra info field for compressed size
+    if(compressed_size >= 0xffffffff)
+      datasize += 8;
+
+    // Add ZIP64 extra info field for relative offset to local file header of current file
+    if(zi->ci.pos_local_header >= 0xffffffff)
+      datasize += 8;
+
+    if(datasize > 0)
+    {
+      char* p = NULL;
+
+      if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)
+      {
+        // we can not write more data to the buffer that we have room for.
+        return ZIP_BADZIPFILE;
+      }
+
+      p = zi->ci.central_header + zi->ci.size_centralheader;
+
+      // Add Extra Information Header for 'ZIP64 information'
+      zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID
+      p += 2;
+      zip64local_putValue_inmemory(p, datasize, 2); // DataSize
+      p += 2;
+
+      if(uncompressed_size >= 0xffffffff)
+      {
+        zip64local_putValue_inmemory(p, uncompressed_size, 8);
+        p += 8;
+      }
+
+      if(compressed_size >= 0xffffffff)
+      {
+        zip64local_putValue_inmemory(p, compressed_size, 8);
+        p += 8;
+      }
+
+      if(zi->ci.pos_local_header >= 0xffffffff)
+      {
+        zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8);
+        p += 8;
+      }
+
+      // Update how much extra free space we got in the memory buffer
+      // and increase the centralheader size so the new ZIP64 fields are included
+      // ( 4 below is the size of HeaderID and DataSize field )
+      zi->ci.size_centralExtraFree -= datasize + 4;
+      zi->ci.size_centralheader += datasize + 4;
+
+      // Update the extra info size field
+      zi->ci.size_centralExtra += datasize + 4;
+      zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2);
+    }
 
     if (err==ZIP_OK)
-        err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
-                                       (uLong)zi->ci.size_centralheader);
+        err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader);
+
     free(zi->ci.central_header);
 
     if (err==ZIP_OK)
     {
-        long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
-        if (ZSEEK(zi->z_filefunc,zi->filestream,
-                  zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        // Update the LocalFileHeader with the new values.
+
+        ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream);
+
+        if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)
             err = ZIP_ERRNO;
 
         if (err==ZIP_OK)
-            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
+            err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
 
-        if (err==ZIP_OK) /* compressed size, unknown */
-            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
+        if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff )
+        {
+          if(zi->ci.pos_zip64extrainfo > 0)
+          {
+            // Update the size in the ZIP64 extended field.
+            if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0)
+              err = ZIP_ERRNO;
+
+            if (err==ZIP_OK) /* compressed size, unknown */
+              err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8);
+
+            if (err==ZIP_OK) /* uncompressed size, unknown */
+              err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8);
+          }
+          else
+              err = ZIP_BADZIPFILE; // Caller passed zip64 = 0, so no room for zip64 info -> fatal
+        }
+        else
+        {
+          if (err==ZIP_OK) /* compressed size, unknown */
+              err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
 
-        if (err==ZIP_OK) /* uncompressed size, unknown */
-            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
+          if (err==ZIP_OK) /* uncompressed size, unknown */
+              err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
+        }
 
-        if (ZSEEK(zi->z_filefunc,zi->filestream,
-                  cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
             err = ZIP_ERRNO;
     }
 
@@ -1124,24 +1747,150 @@ extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32)
     return err;
 }
 
-extern int ZEXPORT zipCloseFileInZip (file)
-    zipFile file;
+extern int ZEXPORT zipCloseFileInZip (zipFile file)
 {
     return zipCloseFileInZipRaw (file,0,0);
 }
 
-extern int ZEXPORT zipClose (file, global_comment)
-    zipFile file;
-    const char* global_comment;
+int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip)
 {
-    zip_internal* zi;
+  int err = ZIP_OK;
+  ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset;
+
+  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4);
+
+  /*num disks*/
+    if (err==ZIP_OK) /* number of the disk with the start of the central directory */
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
+
+  /*relative offset*/
+    if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8);
+
+  /*total disks*/ /* Do not support spawning of disk so always say 1 here*/
+    if (err==ZIP_OK) /* number of the disk with the start of the central directory */
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4);
+
+    return err;
+}
+
+int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
+{
+  int err = ZIP_OK;
+
+  uLong Zip64DataSize = 44;
+
+  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4);
+
+  if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ?
+
+  if (err==ZIP_OK) /* version made by */
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);
+
+  if (err==ZIP_OK) /* version needed */
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);
+
+  if (err==ZIP_OK) /* number of this disk */
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
+
+  if (err==ZIP_OK) /* number of the disk with the start of the central directory */
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
+
+  if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
+    err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
+
+  if (err==ZIP_OK) /* total number of entries in the central dir */
+    err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
+
+  if (err==ZIP_OK) /* size of the central directory */
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8);
+
+  if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
+  {
+    ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset;
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8);
+  }
+  return err;
+}
+int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
+{
+  int err = ZIP_OK;
+
+  /*signature*/
+  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
+
+  if (err==ZIP_OK) /* number of this disk */
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
+
+  if (err==ZIP_OK) /* number of the disk with the start of the central directory */
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
+
+  if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
+  {
+    {
+      if(zi->number_entry >= 0xFFFF)
+        err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record
+      else
+        err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
+    }
+  }
+
+  if (err==ZIP_OK) /* total number of entries in the central dir */
+  {
+    if(zi->number_entry >= 0xFFFF)
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record
+    else
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
+  }
+
+  if (err==ZIP_OK) /* size of the central directory */
+    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
+
+  if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
+  {
+    ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset;
+    if(pos >= 0xffffffff)
+    {
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4);
+    }
+    else
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
+  }
+
+   return err;
+}
+
+int Write_GlobalComment(zip64_internal* zi, const char* global_comment)
+{
+  int err = ZIP_OK;
+  uInt size_global_comment = 0;
+
+  if(global_comment != NULL)
+    size_global_comment = (uInt)strlen(global_comment);
+
+  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
+
+  if (err == ZIP_OK && size_global_comment > 0)
+  {
+    if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment)
+      err = ZIP_ERRNO;
+  }
+  return err;
+}
+
+extern int ZEXPORT zipClose (zipFile file, const char* global_comment)
+{
+    zip64_internal* zi;
     int err = 0;
     uLong size_centraldir = 0;
-    uLong centraldir_pos_inzip;
-    uInt size_global_comment;
+    ZPOS64_T centraldir_pos_inzip;
+    ZPOS64_T pos;
+
     if (file == NULL)
         return ZIP_PARAMERROR;
-    zi = (zip_internal*)file;
+
+    zi = (zip64_internal*)file;
 
     if (zi->in_opened_file_inzip == 1)
     {
@@ -1152,61 +1901,42 @@ extern int ZEXPORT zipClose (file, global_comment)
     if (global_comment==NULL)
         global_comment = zi->globalcomment;
 #endif
-    if (global_comment==NULL)
-        size_global_comment = 0;
-    else
-        size_global_comment = (uInt)strlen(global_comment);
 
-    centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
+    centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream);
+
     if (err==ZIP_OK)
     {
-        linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
+        linkedlist_datablock_internal* ldi = zi->central_dir.first_block;
         while (ldi!=NULL)
         {
             if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
-                if (ZWRITE(zi->z_filefunc,zi->filestream,
-                           ldi->data,ldi->filled_in_this_block)
-                              !=ldi->filled_in_this_block )
+            {
+                if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block)
                     err = ZIP_ERRNO;
+            }
 
             size_centraldir += ldi->filled_in_this_block;
             ldi = ldi->next_datablock;
         }
     }
-    free_datablock(zi->central_dir.first_block);
-
-    if (err==ZIP_OK) /* Magic End */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
-
-    if (err==ZIP_OK) /* number of this disk */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
-
-    if (err==ZIP_OK) /* number of the disk with the start of the central directory */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
-
-    if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
+    free_linkedlist(&(zi->central_dir));
 
-    if (err==ZIP_OK) /* total number of entries in the central dir */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
+    pos = centraldir_pos_inzip - zi->add_position_when_writting_offset;
+    if(pos >= 0xffffffff || zi->number_entry > 0xFFFF)
+    {
+      ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
+      Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
 
-    if (err==ZIP_OK) /* size of the central directory */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
+      Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos);
+    }
 
-    if (err==ZIP_OK) /* offset of start of central directory with respect to the
-                            starting disk number */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,
-                                (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
+    if (err==ZIP_OK)
+      err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
 
-    if (err==ZIP_OK) /* zipfile comment length */
-        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
+    if(err == ZIP_OK)
+      err = Write_GlobalComment(zi, global_comment);
 
-    if ((err==ZIP_OK) && (size_global_comment>0))
-        if (ZWRITE(zi->z_filefunc,zi->filestream,
-                   global_comment,size_global_comment) != size_global_comment)
-                err = ZIP_ERRNO;
-
-    if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0)
+    if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0)
         if (err == ZIP_OK)
             err = ZIP_ERRNO;
 
@@ -1217,3 +1947,61 @@ extern int ZEXPORT zipClose (file, global_comment)
 
     return err;
 }
+
+extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader)
+{
+  char* p = pData;
+  int size = 0;
+  char* pNewHeader;
+  char* pTmp;
+  short header;
+  short dataSize;
+
+  int retVal = ZIP_OK;
+
+  if(pData == NULL || *dataLen < 4)
+    return ZIP_PARAMERROR;
+
+  pNewHeader = (char*)ALLOC(*dataLen);
+  pTmp = pNewHeader;
+
+  while(p < (pData + *dataLen))
+  {
+    header = *(short*)p;
+    dataSize = *(((short*)p)+1);
+
+    if( header == sHeader ) // Header found.
+    {
+      p += dataSize + 4; // skip it. do not copy to temp buffer
+    }
+    else
+    {
+      // Extra Info block should not be removed, So copy it to the temp buffer.
+      memcpy(pTmp, p, dataSize + 4);
+      p += dataSize + 4;
+      size += dataSize + 4;
+    }
+
+  }
+
+  if(size < *dataLen)
+  {
+    // clean old extra info block.
+    memset(pData,0, *dataLen);
+
+    // copy the new extra info block over the old
+    if(size > 0)
+      memcpy(pData, pNewHeader, size);
+
+    // set the new extra info size
+    *dataLen = size;
+
+    retVal = ZIP_OK;
+  }
+  else
+    retVal = ZIP_ERRNO;
+
+  TRYFREE(pNewHeader);
+
+  return retVal;
+}
diff --git a/third_party/zlib/contrib/minizip/zip.h b/third_party/zlib/contrib/minizip/zip.h
index acacce8..8aaebb6 100644
--- a/third_party/zlib/contrib/minizip/zip.h
+++ b/third_party/zlib/contrib/minizip/zip.h
@@ -1,19 +1,15 @@
-/* zip.h -- IO for compress .zip files using zlib
-   Version 1.01e, February 12th, 2005
+/* zip.h -- IO on .zip files using zlib
+   Version 1.1, February 14h, 2010
+   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
 
-   Copyright (C) 1998-2005 Gilles Vollant
+         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
 
-   This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
-     WinZip, InfoZip tools and compatible.
-   Multi volume ZipFile (span) are not supported.
-   Encryption compatible with pkzip 2.04g only supported
-   Old compressions used by old PKZip 1.x are not supported
+         Modifications for Zip64 support
+         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
 
-  For uncompress .zip file, look at unzip.h
+         For more info read MiniZip_info.txt
 
-
-   I WAIT FEEDBACK at mail info at winimage.com
-   Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
+         ---------------------------------------------------------------------------
 
    Condition of use and distribution are the same than zlib :
 
@@ -33,23 +29,23 @@
      misrepresented as being the original software.
   3. This notice may not be removed or altered from any source distribution.
 
+        ---------------------------------------------------------------------------
 
-*/
+        Changes
+
+        See header of zip.h
 
-/* for more info about .ZIP format, see
-      http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
-      http://www.info-zip.org/pub/infozip/doc/
-   PkWare has also a specification at :
-      ftp://ftp.pkware.com/probdesc.zip
 */
 
-#ifndef _zip_H
-#define _zip_H
+#ifndef _zip12_H
+#define _zip12_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+//#define HAVE_BZIP2
+
 #ifndef _ZLIB_H
 #include "zlib.h"
 #endif
@@ -58,6 +54,12 @@ extern "C" {
 #include "ioapi.h"
 #endif
 
+#ifdef HAVE_BZIP2
+#include "bzlib.h"
+#endif
+
+#define Z_BZIP2ED 12
+
 #if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
 /* like the STRICT of WIN32, we define a pointer that cannot be converted
     from (void*) without cast */
@@ -112,6 +114,7 @@ typedef const char* zipcharpc;
 #define APPEND_STATUS_ADDINZIP      (2)
 
 extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
+extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append));
 /*
   Create a zipfile.
      pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
@@ -136,6 +139,11 @@ extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
                                    zipcharpc* globalcomment,
                                    zlib_filefunc_def* pzlib_filefunc_def));
 
+extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname,
+                                   int append,
+                                   zipcharpc* globalcomment,
+                                   zlib_filefunc64_def* pzlib_filefunc_def));
+
 extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
                        const char* filename,
                        const zip_fileinfo* zipfi,
@@ -146,6 +154,19 @@ extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
                        const char* comment,
                        int method,
                        int level));
+
+extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file,
+                       const char* filename,
+                       const zip_fileinfo* zipfi,
+                       const void* extrafield_local,
+                       uInt size_extrafield_local,
+                       const void* extrafield_global,
+                       uInt size_extrafield_global,
+                       const char* comment,
+                       int method,
+                       int level,
+                       int zip64));
+
 /*
   Open a file in the ZIP for writing.
   filename : the filename in zip (if NULL, '-' without quote will be used
@@ -157,6 +178,9 @@ extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
   if comment != NULL, comment contain the comment string
   method contain the compression method (0 for store, Z_DEFLATED for deflate)
   level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
+  zip64 is set to 1 if a zip64 extended information block should be added to the local file header.
+                    this MUST be '1' if the uncompressed size is >= 0xffffffff.
+
 */
 
 
@@ -172,6 +196,19 @@ extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
                                             int level,
                                             int raw));
 
+
+extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file,
+                                            const char* filename,
+                                            const zip_fileinfo* zipfi,
+                                            const void* extrafield_local,
+                                            uInt size_extrafield_local,
+                                            const void* extrafield_global,
+                                            uInt size_extrafield_global,
+                                            const char* comment,
+                                            int method,
+                                            int level,
+                                            int raw,
+                                            int zip64));
 /*
   Same than zipOpenNewFileInZip, except if raw=1, we write raw file
  */
@@ -191,13 +228,79 @@ extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
                                             int memLevel,
                                             int strategy,
                                             const char* password,
-                                            uLong crcForCtypting));
+                                            uLong crcForCrypting));
+
+extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file,
+                                            const char* filename,
+                                            const zip_fileinfo* zipfi,
+                                            const void* extrafield_local,
+                                            uInt size_extrafield_local,
+                                            const void* extrafield_global,
+                                            uInt size_extrafield_global,
+                                            const char* comment,
+                                            int method,
+                                            int level,
+                                            int raw,
+                                            int windowBits,
+                                            int memLevel,
+                                            int strategy,
+                                            const char* password,
+                                            uLong crcForCrypting,
+                                            int zip64
+                                            ));
 
 /*
   Same than zipOpenNewFileInZip2, except
     windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
     password : crypting password (NULL for no crypting)
-    crcForCtypting : crc of file to compress (needed for crypting)
+    crcForCrypting : crc of file to compress (needed for crypting)
+ */
+
+extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file,
+                                            const char* filename,
+                                            const zip_fileinfo* zipfi,
+                                            const void* extrafield_local,
+                                            uInt size_extrafield_local,
+                                            const void* extrafield_global,
+                                            uInt size_extrafield_global,
+                                            const char* comment,
+                                            int method,
+                                            int level,
+                                            int raw,
+                                            int windowBits,
+                                            int memLevel,
+                                            int strategy,
+                                            const char* password,
+                                            uLong crcForCrypting,
+                                            uLong versionMadeBy,
+                                            uLong flagBase
+                                            ));
+
+
+extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file,
+                                            const char* filename,
+                                            const zip_fileinfo* zipfi,
+                                            const void* extrafield_local,
+                                            uInt size_extrafield_local,
+                                            const void* extrafield_global,
+                                            uInt size_extrafield_global,
+                                            const char* comment,
+                                            int method,
+                                            int level,
+                                            int raw,
+                                            int windowBits,
+                                            int memLevel,
+                                            int strategy,
+                                            const char* password,
+                                            uLong crcForCrypting,
+                                            uLong versionMadeBy,
+                                            uLong flagBase,
+                                            int zip64
+                                            ));
+/*
+  Same than zipOpenNewFileInZip4, except
+    versionMadeBy : value for Version made by field
+    flag : value for flag field (compression level info will be added)
  */
 
 
@@ -216,8 +319,13 @@ extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
 extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
                                             uLong uncompressed_size,
                                             uLong crc32));
+
+extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file,
+                                            ZPOS64_T uncompressed_size,
+                                            uLong crc32));
+
 /*
-  Close the current file in the zipfile, for fiel opened with
+  Close the current file in the zipfile, for file opened with
     parameter raw=1 in zipOpenNewFileInZip2
   uncompressed_size and crc32 are value for the uncompressed size
 */
@@ -228,8 +336,27 @@ extern int ZEXPORT zipClose OF((zipFile file,
   Close the zipfile
 */
 
+
+extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader));
+/*
+  zipRemoveExtraInfoBlock -  Added by Mathias Svensson
+
+  Remove extra information block from a extra information data for the local file header or central directory header
+
+  It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode.
+
+  0x0001 is the signature header for the ZIP64 extra information blocks
+
+  usage.
+                        Remove ZIP64 Extra information from a central director extra field data
+              zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001);
+
+                        Remove ZIP64 Extra information from a Local File Header extra field data
+        zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001);
+*/
+
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* _zip_H */
+#endif /* _zip64_H */
diff --git a/third_party/zlib/contrib/pascal/zlibd32.mak b/third_party/zlib/contrib/pascal/zlibd32.mak
index 88fafa0..9bb00b7 100644
--- a/third_party/zlib/contrib/pascal/zlibd32.mak
+++ b/third_party/zlib/contrib/pascal/zlibd32.mak
@@ -18,10 +18,10 @@ LDFLAGS =
 # variables
 ZLIB_LIB = zlib.lib
 
-OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
-OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
-OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
-OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj
+OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj
+OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
 
 
 # targets
@@ -38,7 +38,13 @@ crc32.obj: crc32.c zlib.h zconf.h crc32.h
 
 deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
 
-gzio.obj: gzio.c zutil.h zlib.h zconf.h
+gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h
+
+gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h
+
+gzread.obj: gzread.c zlib.h zconf.h gzguts.h
+
+gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h
 
 infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
  inffast.h inffixed.h
@@ -57,9 +63,9 @@ uncompr.obj: uncompr.c zlib.h zconf.h
 
 zutil.obj: zutil.c zutil.h zlib.h zconf.h
 
-example.obj: example.c zlib.h zconf.h
+example.obj: test/example.c zlib.h zconf.h
 
-minigzip.obj: minigzip.c zlib.h zconf.h
+minigzip.obj: test/minigzip.c zlib.h zconf.h
 
 
 # For the sake of the old Borland make,
diff --git a/third_party/zlib/contrib/pascal/zlibpas.pas b/third_party/zlib/contrib/pascal/zlibpas.pas
index 836848c..e6a0782 100644
--- a/third_party/zlib/contrib/pascal/zlibpas.pas
+++ b/third_party/zlib/contrib/pascal/zlibpas.pas
@@ -10,7 +10,8 @@ unit zlibpas;
 interface
 
 const
-  ZLIB_VERSION = '1.2.3';
+  ZLIB_VERSION = '1.2.8';
+  ZLIB_VERNUM  = $1280;
 
 type
   alloc_func = function(opaque: Pointer; items, size: Integer): Pointer;
@@ -45,6 +46,23 @@ type
     reserved: LongInt;    (* reserved for future use *)
   end;
 
+  gz_headerp = ^gz_header;
+  gz_header = packed record
+    text: Integer;        (* true if compressed data believed to be text *)
+    time: LongInt;        (* modification time *)
+    xflags: Integer;      (* extra flags (not used when writing a gzip file) *)
+    os: Integer;          (* operating system *)
+    extra: PChar;         (* pointer to extra field or Z_NULL if none *)
+    extra_len: Integer;   (* extra field length (valid if extra != Z_NULL) *)
+    extra_max: Integer;   (* space at extra (only when reading header) *)
+    name: PChar;          (* pointer to zero-terminated file name or Z_NULL *)
+    name_max: Integer;    (* space at name (only when reading header) *)
+    comment: PChar;       (* pointer to zero-terminated comment or Z_NULL *)
+    comm_max: Integer;    (* space at comment (only when reading header) *)
+    hcrc: Integer;        (* true if there was or will be a header crc *)
+    done: Integer;        (* true when done reading gzip header *)
+  end;
+
 (* constants *)
 const
   Z_NO_FLUSH      = 0;
@@ -52,6 +70,8 @@ const
   Z_SYNC_FLUSH    = 2;
   Z_FULL_FLUSH    = 3;
   Z_FINISH        = 4;
+  Z_BLOCK         = 5;
+  Z_TREES         = 6;
 
   Z_OK            =  0;
   Z_STREAM_END    =  1;
@@ -71,9 +91,11 @@ const
   Z_FILTERED            = 1;
   Z_HUFFMAN_ONLY        = 2;
   Z_RLE                 = 3;
+  Z_FIXED               = 4;
   Z_DEFAULT_STRATEGY    = 0;
 
   Z_BINARY   = 0;
+  Z_TEXT     = 1;
   Z_ASCII    = 1;
   Z_UNKNOWN  = 2;
 
@@ -96,14 +118,21 @@ function deflateSetDictionary(var strm: z_stream; const dictionary: PChar;
 function deflateCopy(var dest, source: z_stream): Integer;
 function deflateReset(var strm: z_stream): Integer;
 function deflateParams(var strm: z_stream; level, strategy: Integer): Integer;
+function deflateTune(var strm: z_stream; good_length, max_lazy, nice_length, max_chain: Integer): Integer;
 function deflateBound(var strm: z_stream; sourceLen: LongInt): LongInt;
+function deflatePending(var strm: z_stream; var pending: Integer; var bits: Integer): Integer;
 function deflatePrime(var strm: z_stream; bits, value: Integer): Integer;
+function deflateSetHeader(var strm: z_stream; head: gz_header): Integer;
 function inflateInit2(var strm: z_stream; windowBits: Integer): Integer;
 function inflateSetDictionary(var strm: z_stream; const dictionary: PChar;
                               dictLength: Integer): Integer;
 function inflateSync(var strm: z_stream): Integer;
 function inflateCopy(var dest, source: z_stream): Integer;
 function inflateReset(var strm: z_stream): Integer;
+function inflateReset2(var strm: z_stream; windowBits: Integer): Integer;
+function inflatePrime(var strm: z_stream; bits, value: Integer): Integer;
+function inflateMark(var strm: z_stream): LongInt;
+function inflateGetHeader(var strm: z_stream; var head: gz_header): Integer;
 function inflateBackInit(var strm: z_stream;
                          windowBits: Integer; window: PChar): Integer;
 function inflateBack(var strm: z_stream; in_fn: in_func; in_desc: Pointer;
@@ -123,7 +152,9 @@ function uncompress(dest: PChar; var destLen: LongInt;
 
 (* checksum functions *)
 function adler32(adler: LongInt; const buf: PChar; len: Integer): LongInt;
+function adler32_combine(adler1, adler2, len2: LongInt): LongInt;
 function crc32(crc: LongInt; const buf: PChar; len: Integer): LongInt;
+function crc32_combine(crc1, crc2, len2: LongInt): LongInt;
 
 (* various hacks, don't look :) *)
 function deflateInit_(var strm: z_stream; level: Integer;
@@ -155,10 +186,12 @@ implementation
 {$L zutil.obj}
 
 function adler32; external;
+function adler32_combine; external;
 function compress; external;
 function compress2; external;
 function compressBound; external;
 function crc32; external;
+function crc32_combine; external;
 function deflate; external;
 function deflateBound; external;
 function deflateCopy; external;
@@ -166,18 +199,25 @@ function deflateEnd; external;
 function deflateInit_; external;
 function deflateInit2_; external;
 function deflateParams; external;
+function deflatePending; external;
 function deflatePrime; external;
 function deflateReset; external;
 function deflateSetDictionary; external;
+function deflateSetHeader; external;
+function deflateTune; external;
 function inflate; external;
 function inflateBack; external;
 function inflateBackEnd; external;
 function inflateBackInit_; external;
 function inflateCopy; external;
 function inflateEnd; external;
+function inflateGetHeader; external;
 function inflateInit_; external;
 function inflateInit2_; external;
+function inflateMark; external;
+function inflatePrime; external;
 function inflateReset; external;
+function inflateReset2; external;
 function inflateSetDictionary; external;
 function inflateSync; external;
 function uncompress; external;
diff --git a/third_party/zlib/contrib/puff/Makefile b/third_party/zlib/contrib/puff/Makefile
index b6b6940..0e2594c 100644
--- a/third_party/zlib/contrib/puff/Makefile
+++ b/third_party/zlib/contrib/puff/Makefile
@@ -1,8 +1,42 @@
-puff: puff.c puff.h
-	cc -DTEST -o puff puff.c
+CFLAGS=-O
+
+puff: puff.o pufftest.o
+
+puff.o: puff.h
+
+pufftest.o: puff.h
 
 test: puff
 	puff zeros.raw
 
+puft: puff.c puff.h pufftest.o
+	cc -fprofile-arcs -ftest-coverage -o puft puff.c pufftest.o
+
+# puff full coverage test (should say 100%)
+cov: puft
+	@rm -f *.gcov *.gcda
+	@puft -w zeros.raw 2>&1 | cat > /dev/null
+	@echo '04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2
+	@echo '00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2
+	@echo '00 00 00 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 254
+	@echo '00 01 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2
+	@echo '01 01 00 fe ff 0a' | xxd -r -p | puft -f 2>&1 | cat > /dev/null
+	@echo '02 7e ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246
+	@echo '02' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2
+	@echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2
+	@echo '04 80 49 92 24 49 92 24 71 ff ff 93 11 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 249
+	@echo '04 c0 81 08 00 00 00 00 20 7f eb 0b 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246
+	@echo '0b 00 00' | xxd -r -p | puft -f 2>&1 | cat > /dev/null
+	@echo '1a 07' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246
+	@echo '0c c0 81 00 00 00 00 00 90 ff 6b 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 245
+	@puft -f zeros.raw 2>&1 | cat > /dev/null
+	@echo 'fc 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 253
+	@echo '04 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 252
+	@echo '04 00 24 49' | xxd -r -p | puft 2> /dev/null || test $$? -eq 251
+	@echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 84' | xxd -r -p | puft 2> /dev/null || test $$? -eq 248
+	@echo '04 00 24 e9 ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 250
+	@echo '04 00 24 e9 ff 6d' | xxd -r -p | puft 2> /dev/null || test $$? -eq 247
+	@gcov -n puff.c
+
 clean:
-	rm -f puff puff.o
+	rm -f puff puft *.o *.gc*
diff --git a/third_party/zlib/contrib/puff/puff.c b/third_party/zlib/contrib/puff/puff.c
index 1fbcc18..ba58483 100644
--- a/third_party/zlib/contrib/puff/puff.c
+++ b/third_party/zlib/contrib/puff/puff.c
@@ -1,8 +1,8 @@
 /*
  * puff.c
- * Copyright (C) 2002-2004 Mark Adler
+ * Copyright (C) 2002-2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in puff.h
- * version 1.8, 9 Jan 2004
+ * version 2.3, 21 Jan 2013
  *
  * puff.c is a simple inflate written to be an unambiguous way to specify the
  * deflate format.  It is not written for speed but rather simplicity.  As a
@@ -49,9 +49,9 @@
  *                      - Fix fixed codes table error
  *                      - Provide a scanning mode for determining size of
  *                        uncompressed data
- * 1.3  20 Mar 2002     - Go back to lengths for puff() parameters [Jean-loup]
+ * 1.3  20 Mar 2002     - Go back to lengths for puff() parameters [Gailly]
  *                      - Add a puff.h file for the interface
- *                      - Add braces in puff() for else do [Jean-loup]
+ *                      - Add braces in puff() for else do [Gailly]
  *                      - Use indexes instead of pointers for readability
  * 1.4  31 Mar 2002     - Simplify construct() code set check
  *                      - Fix some comments
@@ -61,13 +61,28 @@
  * 1.7   3 Mar 2003     - Added test code for distribution
  *                      - Added zlib-like license
  * 1.8   9 Jan 2004     - Added some comments on no distance codes case
+ * 1.9  21 Feb 2008     - Fix bug on 16-bit integer architectures [Pohland]
+ *                      - Catch missing end-of-block symbol error
+ * 2.0  25 Jul 2008     - Add #define to permit distance too far back
+ *                      - Add option in TEST code for puff to write the data
+ *                      - Add option in TEST code to skip input bytes
+ *                      - Allow TEST code to read from piped stdin
+ * 2.1   4 Apr 2010     - Avoid variable initialization for happier compilers
+ *                      - Avoid unsigned comparisons for even happier compilers
+ * 2.2  25 Apr 2010     - Fix bug in variable initializations [Oberhumer]
+ *                      - Add const where appropriate [Oberhumer]
+ *                      - Split if's and ?'s for coverage testing
+ *                      - Break out test code to separate file
+ *                      - Move NIL to puff.h
+ *                      - Allow incomplete code only if single code length is 1
+ *                      - Add full code coverage test to Makefile
+ * 2.3  21 Jan 2013     - Check for invalid code length codes in dynamic blocks
  */
 
 #include <setjmp.h>             /* for setjmp(), longjmp(), and jmp_buf */
 #include "puff.h"               /* prototype for puff() */
 
 #define local static            /* for local function definitions */
-#define NIL ((unsigned char *)0)        /* for no output option */
 
 /*
  * Maximums for allocations and loops.  It is not useful to change these --
@@ -87,7 +102,7 @@ struct state {
     unsigned long outcnt;       /* bytes written to out so far */
 
     /* input state */
-    unsigned char *in;          /* input buffer */
+    const unsigned char *in;    /* input buffer */
     unsigned long inlen;        /* available input at in */
     unsigned long incnt;        /* bytes read so far */
     int bitbuf;                 /* bit buffer */
@@ -115,7 +130,8 @@ local int bits(struct state *s, int need)
     /* load at least need bits into val */
     val = s->bitbuf;
     while (s->bitcnt < need) {
-        if (s->incnt == s->inlen) longjmp(s->env, 1);   /* out of input */
+        if (s->incnt == s->inlen)
+            longjmp(s->env, 1);         /* out of input */
         val |= (long)(s->in[s->incnt++]) << s->bitcnt;  /* load eight bits */
         s->bitcnt += 8;
     }
@@ -154,7 +170,8 @@ local int stored(struct state *s)
     s->bitcnt = 0;
 
     /* get length and check against its one's complement */
-    if (s->incnt + 4 > s->inlen) return 2;      /* not enough input */
+    if (s->incnt + 4 > s->inlen)
+        return 2;                               /* not enough input */
     len = s->in[s->incnt++];
     len |= s->in[s->incnt++] << 8;
     if (s->in[s->incnt++] != (~len & 0xff) ||
@@ -162,7 +179,8 @@ local int stored(struct state *s)
         return -2;                              /* didn't match complement! */
 
     /* copy len bytes from in to out */
-    if (s->incnt + len > s->inlen) return 2;    /* not enough input */
+    if (s->incnt + len > s->inlen)
+        return 2;                               /* not enough input */
     if (s->out != NIL) {
         if (s->outcnt + len > s->outlen)
             return 1;                           /* not enough output space */
@@ -194,7 +212,7 @@ struct huffman {
  * Decode a code from the stream s using huffman table h.  Return the symbol or
  * a negative value if there is an error.  If all of the lengths are zero, i.e.
  * an empty code, or if the code is incomplete and an invalid code is received,
- * then -9 is returned after reading MAXBITS bits.
+ * then -10 is returned after reading MAXBITS bits.
  *
  * Format notes:
  *
@@ -214,7 +232,7 @@ struct huffman {
  *   in the deflate format.  See the format notes for fixed() and dynamic().
  */
 #ifdef SLOW
-local int decode(struct state *s, struct huffman *h)
+local int decode(struct state *s, const struct huffman *h)
 {
     int len;            /* current number of bits in code */
     int code;           /* len bits being decoded */
@@ -226,14 +244,14 @@ local int decode(struct state *s, struct huffman *h)
     for (len = 1; len <= MAXBITS; len++) {
         code |= bits(s, 1);             /* get next bit */
         count = h->count[len];
-        if (code < first + count)       /* if length len, return symbol */
+        if (code - count < first)       /* if length len, return symbol */
             return h->symbol[index + (code - first)];
         index += count;                 /* else update for next length */
         first += count;
         first <<= 1;
         code <<= 1;
     }
-    return -9;                          /* ran out of codes */
+    return -10;                         /* ran out of codes */
 }
 
 /*
@@ -242,7 +260,7 @@ local int decode(struct state *s, struct huffman *h)
  * a few percent larger.
  */
 #else /* !SLOW */
-local int decode(struct state *s, struct huffman *h)
+local int decode(struct state *s, const struct huffman *h)
 {
     int len;            /* current number of bits in code */
     int code;           /* len bits being decoded */
@@ -263,7 +281,7 @@ local int decode(struct state *s, struct huffman *h)
             code |= bitbuf & 1;
             bitbuf >>= 1;
             count = *next++;
-            if (code < first + count) { /* if length len, return symbol */
+            if (code - count < first) { /* if length len, return symbol */
                 s->bitbuf = bitbuf;
                 s->bitcnt = (s->bitcnt - len) & 7;
                 return h->symbol[index + (code - first)];
@@ -275,12 +293,15 @@ local int decode(struct state *s, struct huffman *h)
             len++;
         }
         left = (MAXBITS+1) - len;
-        if (left == 0) break;
-        if (s->incnt == s->inlen) longjmp(s->env, 1);   /* out of input */
+        if (left == 0)
+            break;
+        if (s->incnt == s->inlen)
+            longjmp(s->env, 1);         /* out of input */
         bitbuf = s->in[s->incnt++];
-        if (left > 8) left = 8;
+        if (left > 8)
+            left = 8;
     }
-    return -9;                          /* ran out of codes */
+    return -10;                         /* ran out of codes */
 }
 #endif /* SLOW */
 
@@ -316,7 +337,7 @@ local int decode(struct state *s, struct huffman *h)
  * - Within a given code length, the symbols are kept in ascending order for
  *   the code bits definition.
  */
-local int construct(struct huffman *h, short *length, int n)
+local int construct(struct huffman *h, const short *length, int n)
 {
     int symbol;         /* current symbol when stepping through length[] */
     int len;            /* current length when stepping through h->count[] */
@@ -336,7 +357,8 @@ local int construct(struct huffman *h, short *length, int n)
     for (len = 1; len <= MAXBITS; len++) {
         left <<= 1;                     /* one more bit, double codes left */
         left -= h->count[len];          /* deduct count from possible codes */
-        if (left < 0) return left;      /* over-subscribed--return negative */
+        if (left < 0)
+            return left;                /* over-subscribed--return negative */
     }                                   /* left > 0 means incomplete */
 
     /* generate offsets into symbol table for each length for sorting */
@@ -412,8 +434,8 @@ local int construct(struct huffman *h, short *length, int n)
  *   defined to do the wrong thing in this case.
  */
 local int codes(struct state *s,
-                struct huffman *lencode,
-                struct huffman *distcode)
+                const struct huffman *lencode,
+                const struct huffman *distcode)
 {
     int symbol;         /* decoded symbol */
     int len;            /* length for copy */
@@ -436,11 +458,13 @@ local int codes(struct state *s,
     /* decode literals and length/distance pairs */
     do {
         symbol = decode(s, lencode);
-        if (symbol < 0) return symbol;  /* invalid symbol */
+        if (symbol < 0)
+            return symbol;              /* invalid symbol */
         if (symbol < 256) {             /* literal: symbol is the byte */
             /* write out the literal */
             if (s->out != NIL) {
-                if (s->outcnt == s->outlen) return 1;
+                if (s->outcnt == s->outlen)
+                    return 1;
                 s->out[s->outcnt] = symbol;
             }
             s->outcnt++;
@@ -448,21 +472,31 @@ local int codes(struct state *s,
         else if (symbol > 256) {        /* length */
             /* get and compute length */
             symbol -= 257;
-            if (symbol >= 29) return -9;        /* invalid fixed code */
+            if (symbol >= 29)
+                return -10;             /* invalid fixed code */
             len = lens[symbol] + bits(s, lext[symbol]);
 
             /* get and check distance */
             symbol = decode(s, distcode);
-            if (symbol < 0) return symbol;      /* invalid symbol */
+            if (symbol < 0)
+                return symbol;          /* invalid symbol */
             dist = dists[symbol] + bits(s, dext[symbol]);
+#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
             if (dist > s->outcnt)
-                return -10;     /* distance too far back */
+                return -11;     /* distance too far back */
+#endif
 
             /* copy length bytes from distance bytes back */
             if (s->out != NIL) {
-                if (s->outcnt + len > s->outlen) return 1;
+                if (s->outcnt + len > s->outlen)
+                    return 1;
                 while (len--) {
-                    s->out[s->outcnt] = s->out[s->outcnt - dist];
+                    s->out[s->outcnt] =
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                        dist > s->outcnt ?
+                            0 :
+#endif
+                            s->out[s->outcnt - dist];
                     s->outcnt++;
                 }
             }
@@ -504,14 +538,19 @@ local int fixed(struct state *s)
     static int virgin = 1;
     static short lencnt[MAXBITS+1], lensym[FIXLCODES];
     static short distcnt[MAXBITS+1], distsym[MAXDCODES];
-    static struct huffman lencode = {lencnt, lensym};
-    static struct huffman distcode = {distcnt, distsym};
+    static struct huffman lencode, distcode;
 
     /* build fixed huffman tables if first call (may not be thread safe) */
     if (virgin) {
         int symbol;
         short lengths[FIXLCODES];
 
+        /* construct lencode and distcode */
+        lencode.count = lencnt;
+        lencode.symbol = lensym;
+        distcode.count = distcnt;
+        distcode.symbol = distsym;
+
         /* literal/length table */
         for (symbol = 0; symbol < 144; symbol++)
             lengths[symbol] = 8;
@@ -585,7 +624,7 @@ local int fixed(struct state *s)
  *   are themselves compressed using Huffman codes and run-length encoding.  In
  *   the list of code lengths, a 0 symbol means no code, a 1..15 symbol means
  *   that length, and the symbols 16, 17, and 18 are run-length instructions.
- *   Each of 16, 17, and 18 are followed by extra bits to define the length of
+ *   Each of 16, 17, and 18 are follwed by extra bits to define the length of
  *   the run.  16 copies the last length 3 to 6 times.  17 represents 3 to 10
  *   zero lengths, and 18 represents 11 to 138 zero lengths.  Unused symbols
  *   are common, hence the special coding for zero lengths.
@@ -631,11 +670,16 @@ local int dynamic(struct state *s)
     short lengths[MAXCODES];            /* descriptor code lengths */
     short lencnt[MAXBITS+1], lensym[MAXLCODES];         /* lencode memory */
     short distcnt[MAXBITS+1], distsym[MAXDCODES];       /* distcode memory */
-    struct huffman lencode = {lencnt, lensym};          /* length code */
-    struct huffman distcode = {distcnt, distsym};       /* distance code */
+    struct huffman lencode, distcode;   /* length and distance codes */
     static const short order[19] =      /* permutation of code length codes */
         {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
 
+    /* construct lencode and distcode */
+    lencode.count = lencnt;
+    lencode.symbol = lensym;
+    distcode.count = distcnt;
+    distcode.symbol = distsym;
+
     /* get number of lengths in each table, check lengths */
     nlen = bits(s, 5) + 257;
     ndist = bits(s, 5) + 1;
@@ -651,7 +695,8 @@ local int dynamic(struct state *s)
 
     /* build huffman table for code lengths codes (use lencode temporarily) */
     err = construct(&lencode, lengths, 19);
-    if (err != 0) return -4;            /* require complete code set here */
+    if (err != 0)               /* require complete code set here */
+        return -4;
 
     /* read length/literal and distance code length tables */
     index = 0;
@@ -660,12 +705,15 @@ local int dynamic(struct state *s)
         int len;                /* last length to repeat */
 
         symbol = decode(s, &lencode);
+        if (symbol < 0)
+            return symbol;          /* invalid symbol */
         if (symbol < 16)                /* length in 0..15 */
             lengths[index++] = symbol;
         else {                          /* repeat instruction */
             len = 0;                    /* assume repeating zeros */
             if (symbol == 16) {         /* repeat last length 3..6 times */
-                if (index == 0) return -5;      /* no last length! */
+                if (index == 0)
+                    return -5;          /* no last length! */
                 len = lengths[index - 1];       /* last length */
                 symbol = 3 + bits(s, 2);
             }
@@ -680,15 +728,19 @@ local int dynamic(struct state *s)
         }
     }
 
+    /* check for end-of-block code -- there better be one! */
+    if (lengths[256] == 0)
+        return -9;
+
     /* build huffman table for literal/length codes */
     err = construct(&lencode, lengths, nlen);
-    if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))
-        return -7;      /* only allow incomplete codes if just one code */
+    if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))
+        return -7;      /* incomplete code ok only for single length 1 code */
 
     /* build huffman table for distance codes */
     err = construct(&distcode, lengths + nlen, ndist);
-    if (err < 0 || (err > 0 && ndist - distcode.count[0] != 1))
-        return -8;      /* only allow incomplete codes if just one code */
+    if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))
+        return -8;      /* incomplete code ok only for single length 1 code */
 
     /* decode data until end-of-block code */
     return codes(s, &lencode, &distcode);
@@ -724,8 +776,9 @@ local int dynamic(struct state *s)
  *  -6:  dynamic block code description: repeat more than specified lengths
  *  -7:  dynamic block code description: invalid literal/length code lengths
  *  -8:  dynamic block code description: invalid distance code lengths
- *  -9:  invalid literal/length or distance code in fixed or dynamic block
- * -10:  distance is too far back in fixed or dynamic block
+ *  -9:  dynamic block code description: missing end-of-block code
+ * -10:  invalid literal/length or distance code in fixed or dynamic block
+ * -11:  distance is too far back in fixed or dynamic block
  *
  * Format notes:
  *
@@ -739,7 +792,7 @@ local int dynamic(struct state *s)
  */
 int puff(unsigned char *dest,           /* pointer to destination pointer */
          unsigned long *destlen,        /* amount of output space */
-         unsigned char *source,         /* pointer to source data pointer */
+         const unsigned char *source,   /* pointer to source data pointer */
          unsigned long *sourcelen)      /* amount of input available */
 {
     struct state s;             /* input/output state */
@@ -766,11 +819,15 @@ int puff(unsigned char *dest,           /* pointer to destination pointer */
         do {
             last = bits(&s, 1);         /* one if last block */
             type = bits(&s, 2);         /* block type 0..3 */
-            err = type == 0 ? stored(&s) :
-                  (type == 1 ? fixed(&s) :
-                   (type == 2 ? dynamic(&s) :
-                    -1));               /* type == 3, invalid */
-            if (err != 0) break;        /* return with error */
+            err = type == 0 ?
+                    stored(&s) :
+                    (type == 1 ?
+                        fixed(&s) :
+                        (type == 2 ?
+                            dynamic(&s) :
+                            -1));       /* type == 3, invalid */
+            if (err != 0)
+                break;                  /* return with error */
         } while (!last);
     }
 
@@ -781,57 +838,3 @@ int puff(unsigned char *dest,           /* pointer to destination pointer */
     }
     return err;
 }
-
-#ifdef TEST
-/* Example of how to use puff() */
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-local unsigned char *yank(char *name, unsigned long *len)
-{
-    unsigned long size;
-    unsigned char *buf;
-    FILE *in;
-    struct stat s;
-
-    *len = 0;
-    if (stat(name, &s)) return NULL;
-    if ((s.st_mode & S_IFMT) != S_IFREG) return NULL;
-    size = (unsigned long)(s.st_size);
-    if (size == 0 || (off_t)size != s.st_size) return NULL;
-    in = fopen(name, "r");
-    if (in == NULL) return NULL;
-    buf = malloc(size);
-    if (buf != NULL && fread(buf, 1, size, in) != size) {
-        free(buf);
-        buf = NULL;
-    }
-    fclose(in);
-    *len = size;
-    return buf;
-}
-
-int main(int argc, char **argv)
-{
-    int ret;
-    unsigned char *source;
-    unsigned long len, sourcelen, destlen;
-
-    if (argc < 2) return 2;
-    source = yank(argv[1], &len);
-    if (source == NULL) return 2;
-    sourcelen = len;
-    ret = puff(NIL, &destlen, source, &sourcelen);
-    if (ret)
-        printf("puff() failed with return code %d\n", ret);
-    else {
-        printf("puff() succeeded uncompressing %lu bytes\n", destlen);
-        if (sourcelen < len) printf("%lu compressed bytes unused\n",
-                                    len - sourcelen);
-    }
-    free(source);
-    return ret;
-}
-#endif
diff --git a/third_party/zlib/contrib/puff/puff.h b/third_party/zlib/contrib/puff/puff.h
index ef61252..e23a245 100644
--- a/third_party/zlib/contrib/puff/puff.h
+++ b/third_party/zlib/contrib/puff/puff.h
@@ -1,6 +1,6 @@
 /* puff.h
-  Copyright (C) 2002, 2003 Mark Adler, all rights reserved
-  version 1.7, 3 Mar 2002
+  Copyright (C) 2002-2013 Mark Adler, all rights reserved
+  version 2.3, 21 Jan 2013
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the author be held liable for any damages
@@ -25,7 +25,11 @@
 /*
  * See puff.c for purpose and usage.
  */
+#ifndef NIL
+#  define NIL ((unsigned char *)0)      /* for no output option */
+#endif
+
 int puff(unsigned char *dest,           /* pointer to destination pointer */
          unsigned long *destlen,        /* amount of output space */
-         unsigned char *source,         /* pointer to source data pointer */
+         const unsigned char *source,   /* pointer to source data pointer */
          unsigned long *sourcelen);     /* amount of input available */
diff --git a/third_party/zlib/contrib/puff/zeros.raw b/third_party/zlib/contrib/puff/zeros.raw
index 637b7be6f5bfd577cec5537aaad160cc5fc0a7c7..0a90e76b300205a44a0ecbf613e64aaaef2e51e7 100644
GIT binary patch
literal 2517
zcmYdFkYHV$AkxzmXu#!mP=i#?5{3o^3jqcYc(h*%Opg+yAut*OqaiT#LSPd+y9&tF
zP5<`ixi4UXdB8xJfs^6ee;AkH?VUytyFsD;HLIJ(gg5bUnNh}Q2#kinXb22!2pr%5
E0JRq+;s5{u

delta 28
icmcaAyq8np?ZHL{AUM3>XK?&OhET?hfvZ`V3M2rd9SUv$

diff --git a/third_party/zlib/contrib/testzlib/testzlib.c b/third_party/zlib/contrib/testzlib/testzlib.c
index e5574f4..5f659de 100644
--- a/third_party/zlib/contrib/testzlib/testzlib.c
+++ b/third_party/zlib/contrib/testzlib/testzlib.c
@@ -103,12 +103,12 @@ DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPe
         MyDoMinus64(&ticks,endTime64,beginTime64);
         QueryPerformanceFrequency(&ticksPerSecond);
 
-    
+
         {
             ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog);
             tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog);
-        
-        } 
+
+        }
 
         dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted));
         dwRet *=1;
@@ -116,10 +116,10 @@ DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPe
     return dwRet;
 }
 
-int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)
+int ReadFileMemory(const char* filename,long* plFileSize,unsigned char** pFilePtr)
 {
     FILE* stream;
-    void* ptr;
+    unsigned char* ptr;
     int retVal=1;
     stream=fopen(filename, "rb");
     if (stream==NULL)
diff --git a/third_party/zlib/contrib/vstudio/readme.txt b/third_party/zlib/contrib/vstudio/readme.txt
index 16159f9..bfdcd9d 100644
--- a/third_party/zlib/contrib/vstudio/readme.txt
+++ b/third_party/zlib/contrib/vstudio/readme.txt
@@ -1,8 +1,8 @@
-Building instructions for the DLL versions of Zlib 1.2.3
+Building instructions for the DLL versions of Zlib 1.2.8
 ========================================================
 
 This directory contains projects that build zlib and minizip using
-Microsoft Visual C++ 7.0/7.1, and Visual C++ .
+Microsoft Visual C++ 9.0/10.0.
 
 You don't need to build these projects yourself. You can download the
 binaries from:
@@ -11,35 +11,27 @@ binaries from:
 More information can be found at this site.
 
 
-Build instructions for Visual Studio 7.x (32 bits)
---------------------------------------------------
+
+
+
+Build instructions for Visual Studio 2008 (32 bits or 64 bits)
+--------------------------------------------------------------
 - Uncompress current zlib, including all contrib/* files
-- Download the crtdll library from
-    http://www.winimage.com/zLibDll/crtdll.zip
-  Unzip crtdll.zip to extract crtdll.lib on contrib\vstudio\vc7.
-- Open contrib\vstudio\vc7\zlibvc.sln with Microsoft Visual C++ 7.x
-  (Visual Studio .Net 2002 or 2003).
+- Compile assembly code (with Visual Studio Command Prompt) by running:
+   bld_ml64.bat (in contrib\masmx64)
+   bld_ml32.bat (in contrib\masmx86)
+- Open contrib\vstudio\vc9\zlibvc.sln with Microsoft Visual C++ 2008
+- Or run: vcbuild /rebuild contrib\vstudio\vc9\zlibvc.sln "Release|Win32"
 
-Build instructions for Visual Studio 2005 (32 bits or 64 bits)
+Build instructions for Visual Studio 2010 (32 bits or 64 bits)
 --------------------------------------------------------------
 - Uncompress current zlib, including all contrib/* files
-- For 32 bits only: download the crtdll library from
-    http://www.winimage.com/zLibDll/crtdll.zip
-  Unzip crtdll.zip to extract crtdll.lib on contrib\vstudio\vc8.
-- Open contrib\vstudio\vc8\zlibvc.sln with Microsoft Visual C++ 8.0
-
-Build instructions for Visual Studio 2005 64 bits, PSDK compiler
-----------------------------------------------------------------
-at the time of writing this text file, Visual Studio 2005 (and 
-  Microsoft Visual C++ 8.0) is on the beta 2 stage.
-Using you can get the free 64 bits compiler from Platform SDK, 
-  which is NOT a beta, and compile using the Visual studio 2005 IDE
-see http://www.winimage.com/misc/sdk64onvs2005/ for instruction
+- Open contrib\vstudio\vc10\zlibvc.sln with Microsoft Visual C++ 2010
 
+Build instructions for Visual Studio 2012 (32 bits or 64 bits)
+--------------------------------------------------------------
 - Uncompress current zlib, including all contrib/* files
-- start Visual Studio 2005 from a platform SDK command prompt, using
-  the /useenv switch
-- Open contrib\vstudio\vc8\zlibvc.sln with Microsoft Visual C++ 8.0
+- Open contrib\vstudio\vc11\zlibvc.sln with Microsoft Visual C++ 2012
 
 
 Important
diff --git a/third_party/zlib/contrib/vstudio/vc7/miniunz.vcproj b/third_party/zlib/contrib/vstudio/vc7/miniunz.vcproj
deleted file mode 100644
index ad5117c..0000000
--- a/third_party/zlib/contrib/vstudio/vc7/miniunz.vcproj
+++ /dev/null
@@ -1,126 +0,0 @@
-<?xml version="1.0" encoding = "Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="7.00"
-	Name="miniunz"
-	ProjectGUID="{C52F9E7B-498A-42BE-8DB4-85A15694382A}"
-	Keyword="Win32Proj">
-	<Platforms>
-		<Platform
-			Name="Win32"/>
-	</Platforms>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="Debug"
-			IntermediateDirectory="Debug"
-			ConfigurationType="1"
-			CharacterSet="2">
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE"
-				MinimalRebuild="TRUE"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="5"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="TRUE"
-				DebugInformationFormat="4"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)/miniunz.exe"
-				LinkIncremental="2"
-				GenerateDebugInformation="TRUE"
-				ProgramDatabaseFile="$(OutDir)/miniunz.pdb"
-				SubSystem="1"
-				TargetMachine="1"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCWebDeploymentTool"/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="Release"
-			IntermediateDirectory="Release"
-			ConfigurationType="1"
-			CharacterSet="2">
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="TRUE"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE"
-				StringPooling="TRUE"
-				RuntimeLibrary="4"
-				EnableFunctionLevelLinking="TRUE"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="TRUE"
-				DebugInformationFormat="3"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)/miniunz.exe"
-				LinkIncremental="1"
-				GenerateDebugInformation="TRUE"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="1"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCWebDeploymentTool"/>
-		</Configuration>
-	</Configurations>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
-			<File
-				RelativePath="..\..\minizip\miniunz.c">
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;inc">
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
-		</Filter>
-		<File
-			RelativePath="ReleaseDll\zlibwapi.lib">
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/third_party/zlib/contrib/vstudio/vc7/minizip.vcproj b/third_party/zlib/contrib/vstudio/vc7/minizip.vcproj
deleted file mode 100644
index fb5b632..0000000
--- a/third_party/zlib/contrib/vstudio/vc7/minizip.vcproj
+++ /dev/null
@@ -1,126 +0,0 @@
-<?xml version="1.0" encoding = "Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="7.00"
-	Name="minizip"
-	ProjectGUID="{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}"
-	Keyword="Win32Proj">
-	<Platforms>
-		<Platform
-			Name="Win32"/>
-	</Platforms>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="Debug"
-			IntermediateDirectory="Debug"
-			ConfigurationType="1"
-			CharacterSet="2">
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE"
-				MinimalRebuild="TRUE"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="5"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="TRUE"
-				DebugInformationFormat="4"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)/minizip.exe"
-				LinkIncremental="2"
-				GenerateDebugInformation="TRUE"
-				ProgramDatabaseFile="$(OutDir)/minizip.pdb"
-				SubSystem="1"
-				TargetMachine="1"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCWebDeploymentTool"/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="Release"
-			IntermediateDirectory="Release"
-			ConfigurationType="1"
-			CharacterSet="2">
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="TRUE"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE"
-				StringPooling="TRUE"
-				RuntimeLibrary="4"
-				EnableFunctionLevelLinking="TRUE"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="TRUE"
-				DebugInformationFormat="3"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)/minizip.exe"
-				LinkIncremental="1"
-				GenerateDebugInformation="TRUE"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="1"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCWebDeploymentTool"/>
-		</Configuration>
-	</Configurations>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
-			<File
-				RelativePath="..\..\minizip\minizip.c">
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;inc">
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
-		</Filter>
-		<File
-			RelativePath="ReleaseDll\zlibwapi.lib">
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/third_party/zlib/contrib/vstudio/vc7/testzlib.vcproj b/third_party/zlib/contrib/vstudio/vc7/testzlib.vcproj
deleted file mode 100644
index 97bc3e8..0000000
--- a/third_party/zlib/contrib/vstudio/vc7/testzlib.vcproj
+++ /dev/null
@@ -1,126 +0,0 @@
-<?xml version="1.0" encoding = "Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="7.00"
-	Name="testZlibDll"
-	ProjectGUID="{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}"
-	Keyword="Win32Proj">
-	<Platforms>
-		<Platform
-			Name="Win32"/>
-	</Platforms>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="Debug"
-			IntermediateDirectory="Debug"
-			ConfigurationType="1"
-			CharacterSet="2">
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\.."
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE"
-				MinimalRebuild="TRUE"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="5"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="TRUE"
-				DebugInformationFormat="4"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="2"
-				GenerateDebugInformation="TRUE"
-				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
-				SubSystem="1"
-				TargetMachine="1"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCWebDeploymentTool"/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="Release"
-			IntermediateDirectory="Release"
-			ConfigurationType="1"
-			CharacterSet="2">
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="TRUE"
-				AdditionalIncludeDirectories="..\..\.."
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE"
-				StringPooling="TRUE"
-				RuntimeLibrary="4"
-				EnableFunctionLevelLinking="TRUE"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="TRUE"
-				DebugInformationFormat="3"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="1"
-				GenerateDebugInformation="TRUE"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="1"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCWebDeploymentTool"/>
-		</Configuration>
-	</Configurations>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
-			<File
-				RelativePath="..\..\testzlib\testzlib.c">
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;inc">
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
-		</Filter>
-		<File
-			RelativePath="ReleaseDll\zlibwapi.lib">
-		</File>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/third_party/zlib/contrib/vstudio/vc7/zlib.rc b/third_party/zlib/contrib/vstudio/vc7/zlib.rc
deleted file mode 100644
index 72cb8b4..0000000
--- a/third_party/zlib/contrib/vstudio/vc7/zlib.rc
+++ /dev/null
@@ -1,32 +0,0 @@
-#include <windows.h>
-
-#define IDR_VERSION1  1
-IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
-  FILEVERSION	 1,2,3,0
-  PRODUCTVERSION 1,2,3,0
-  FILEFLAGSMASK	VS_FFI_FILEFLAGSMASK
-  FILEFLAGS	0
-  FILEOS	VOS_DOS_WINDOWS32
-  FILETYPE	VFT_DLL
-  FILESUBTYPE	0	// not used
-BEGIN
-  BLOCK "StringFileInfo"
-  BEGIN
-    BLOCK "040904E4"
-    //language ID = U.S. English, char set = Windows, Multilingual
-
-    BEGIN
-      VALUE "FileDescription", "zlib data compression library\0"
-      VALUE "FileVersion",	"1.2.3.0\0"
-      VALUE "InternalName",	"zlib\0"
-      VALUE "OriginalFilename",	"zlib.dll\0"
-      VALUE "ProductName",	"ZLib.DLL\0"
-      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
-      VALUE "LegalCopyright", "(C) 1995-2003 Jean-loup Gailly & Mark Adler\0"
-    END
-  END
-  BLOCK "VarFileInfo"
-  BEGIN
-    VALUE "Translation", 0x0409, 1252
-  END
-END
diff --git a/third_party/zlib/contrib/vstudio/vc7/zlibstat.vcproj b/third_party/zlib/contrib/vstudio/vc7/zlibstat.vcproj
deleted file mode 100644
index 766d7a4..0000000
--- a/third_party/zlib/contrib/vstudio/vc7/zlibstat.vcproj
+++ /dev/null
@@ -1,246 +0,0 @@
-<?xml version="1.0" encoding = "Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="7.00"
-	Name="zlibstat"
-	SccProjectName=""
-	SccLocalPath="">
-	<Platforms>
-		<Platform
-			Name="Win32"/>
-	</Platforms>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory=".\zlibstatDebug"
-			IntermediateDirectory=".\zlibstatDebug"
-			ConfigurationType="4"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE">
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI"
-				ExceptionHandling="FALSE"
-				RuntimeLibrary="5"
-				PrecompiledHeaderFile=".\zlibstatDebug/zlibstat.pch"
-				AssemblerListingLocation=".\zlibstatDebug/"
-				ObjectFile=".\zlibstatDebug/"
-				ProgramDataBaseFileName=".\zlibstatDebug/"
-				WarningLevel="3"
-				SuppressStartupBanner="TRUE"
-				DebugInformationFormat="1"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLibrarianTool"
-				AdditionalOptions="/NODEFAULTLIB "
-				OutputFile=".\zlibstatDebug\zlibstat.lib"
-				SuppressStartupBanner="TRUE"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				Culture="1036"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseAxp|Win32"
-			OutputDirectory=".\zlibsta0"
-			IntermediateDirectory=".\zlibsta0"
-			ConfigurationType="4"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE">
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI"
-				StringPooling="TRUE"
-				ExceptionHandling="FALSE"
-				RuntimeLibrary="4"
-				EnableFunctionLevelLinking="TRUE"
-				PrecompiledHeaderFile=".\zlibsta0/zlibstat.pch"
-				AssemblerListingLocation=".\zlibsta0/"
-				ObjectFile=".\zlibsta0/"
-				ProgramDataBaseFileName=".\zlibsta0/"
-				WarningLevel="3"
-				SuppressStartupBanner="TRUE"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLibrarianTool"
-				AdditionalOptions="/NODEFAULTLIB "
-				OutputFile=".\zlibsta0\zlibstat.lib"
-				SuppressStartupBanner="TRUE"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory=".\zlibstat"
-			IntermediateDirectory=".\zlibstat"
-			ConfigurationType="4"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE">
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;ASMV;ASMINF"
-				StringPooling="TRUE"
-				ExceptionHandling="FALSE"
-				RuntimeLibrary="4"
-				EnableFunctionLevelLinking="TRUE"
-				PrecompiledHeaderFile=".\zlibstat/zlibstat.pch"
-				AssemblerListingLocation=".\zlibstat/"
-				ObjectFile=".\zlibstat/"
-				ProgramDataBaseFileName=".\zlibstat/"
-				WarningLevel="3"
-				SuppressStartupBanner="TRUE"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLibrarianTool"
-				AdditionalOptions="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj /NODEFAULTLIB "
-				OutputFile=".\zlibstat\zlibstat.lib"
-				SuppressStartupBanner="TRUE"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				Culture="1036"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseWithoutAsm|Win32"
-			OutputDirectory="zlibstatWithoutAsm"
-			IntermediateDirectory="zlibstatWithoutAsm"
-			ConfigurationType="4"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE">
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI"
-				StringPooling="TRUE"
-				ExceptionHandling="FALSE"
-				RuntimeLibrary="4"
-				EnableFunctionLevelLinking="TRUE"
-				PrecompiledHeaderFile=".\zlibstat/zlibstat.pch"
-				AssemblerListingLocation=".\zlibstatWithoutAsm/"
-				ObjectFile=".\zlibstatWithoutAsm/"
-				ProgramDataBaseFileName=".\zlibstatWithoutAsm/"
-				WarningLevel="3"
-				SuppressStartupBanner="TRUE"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLibrarianTool"
-				AdditionalOptions=" /NODEFAULTLIB "
-				OutputFile=".\zlibstatWithoutAsm\zlibstat.lib"
-				SuppressStartupBanner="TRUE"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				Culture="1036"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-		</Configuration>
-	</Configurations>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="">
-			<File
-				RelativePath="..\..\..\adler32.c">
-			</File>
-			<File
-				RelativePath="..\..\..\compress.c">
-			</File>
-			<File
-				RelativePath="..\..\..\crc32.c">
-			</File>
-			<File
-				RelativePath="..\..\..\deflate.c">
-			</File>
-			<File
-				RelativePath="..\..\masmx86\gvmat32c.c">
-			</File>
-			<File
-				RelativePath="..\..\..\gzio.c">
-			</File>
-			<File
-				RelativePath="..\..\..\infback.c">
-			</File>
-			<File
-				RelativePath="..\..\..\inffast.c">
-			</File>
-			<File
-				RelativePath="..\..\..\inflate.c">
-			</File>
-			<File
-				RelativePath="..\..\..\inftrees.c">
-			</File>
-			<File
-				RelativePath="..\..\minizip\ioapi.c">
-			</File>
-			<File
-				RelativePath="..\..\..\trees.c">
-			</File>
-			<File
-				RelativePath="..\..\..\uncompr.c">
-			</File>
-			<File
-				RelativePath="..\..\minizip\unzip.c">
-			</File>
-			<File
-				RelativePath="..\..\minizip\zip.c">
-			</File>
-			<File
-				RelativePath=".\zlib.rc">
-			</File>
-			<File
-				RelativePath=".\zlibvc.def">
-			</File>
-			<File
-				RelativePath="..\..\..\zutil.c">
-			</File>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/third_party/zlib/contrib/vstudio/vc7/zlibvc.def b/third_party/zlib/contrib/vstudio/vc7/zlibvc.def
deleted file mode 100644
index a40e715..0000000
--- a/third_party/zlib/contrib/vstudio/vc7/zlibvc.def
+++ /dev/null
@@ -1,92 +0,0 @@
-
-VERSION		1.23
-
-HEAPSIZE	1048576,8192
-
-EXPORTS
-        adler32                                  @1
-        compress                                 @2
-        crc32                                    @3
-        deflate                                  @4
-        deflateCopy                              @5
-        deflateEnd                               @6
-        deflateInit2_                            @7
-        deflateInit_                             @8
-        deflateParams                            @9
-        deflateReset                             @10
-        deflateSetDictionary                     @11
-        gzclose                                  @12
-        gzdopen                                  @13
-        gzerror                                  @14
-        gzflush                                  @15
-        gzopen                                   @16
-        gzread                                   @17
-        gzwrite                                  @18
-        inflate                                  @19
-        inflateEnd                               @20
-        inflateInit2_                            @21
-        inflateInit_                             @22
-        inflateReset                             @23
-        inflateSetDictionary                     @24
-        inflateSync                              @25
-        uncompress                               @26
-        zlibVersion                              @27
-        gzprintf                                 @28
-        gzputc                                   @29
-        gzgetc                                   @30
-        gzseek                                   @31
-        gzrewind                                 @32
-        gztell                                   @33
-        gzeof                                    @34
-        gzsetparams                              @35
-        zError                                   @36
-        inflateSyncPoint                         @37
-        get_crc_table                            @38
-        compress2                                @39
-        gzputs                                   @40
-        gzgets                                   @41
-        inflateCopy                              @42
-        inflateBackInit_                         @43
-        inflateBack                              @44
-        inflateBackEnd                           @45
-        compressBound                            @46
-        deflateBound                             @47
-        gzclearerr                               @48
-        gzungetc                                 @49
-        zlibCompileFlags                         @50
-        deflatePrime                             @51
-
-        unzOpen                                  @61
-        unzClose                                 @62
-        unzGetGlobalInfo                         @63
-        unzGetCurrentFileInfo                    @64
-        unzGoToFirstFile                         @65
-        unzGoToNextFile                          @66
-        unzOpenCurrentFile                       @67
-        unzReadCurrentFile                       @68
-        unzOpenCurrentFile3                      @69
-        unztell                                  @70
-        unzeof                                   @71
-        unzCloseCurrentFile                      @72
-        unzGetGlobalComment                      @73
-        unzStringFileNameCompare                 @74
-        unzLocateFile                            @75
-        unzGetLocalExtrafield                    @76
-        unzOpen2                                 @77
-        unzOpenCurrentFile2                      @78
-        unzOpenCurrentFilePassword               @79
-
-        zipOpen                                  @80
-        zipOpenNewFileInZip                      @81
-        zipWriteInFileInZip                      @82
-        zipCloseFileInZip                        @83
-        zipClose                                 @84
-        zipOpenNewFileInZip2                     @86
-        zipCloseFileInZipRaw                     @87
-        zipOpen2                                 @88
-        zipOpenNewFileInZip3                     @89
-
-        unzGetFilePos                            @100
-        unzGoToFilePos                           @101
-
-        fill_win32_filefunc                      @110
diff --git a/third_party/zlib/contrib/vstudio/vc7/zlibvc.sln b/third_party/zlib/contrib/vstudio/vc7/zlibvc.sln
deleted file mode 100644
index 927b42b..0000000
--- a/third_party/zlib/contrib/vstudio/vc7/zlibvc.sln
+++ /dev/null
@@ -1,78 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 7.00
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testZlibDll", "testzlib.vcproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}"
-EndProject
-Global
-	GlobalSection(SolutionConfiguration) = preSolution
-		ConfigName.0 = Debug
-		ConfigName.1 = Release
-		ConfigName.2 = ReleaseAxp
-		ConfigName.3 = ReleaseWithoutAsm
-		ConfigName.4 = ReleaseWithoutCrtdll
-	EndGlobalSection
-	GlobalSection(ProjectDependencies) = postSolution
-	EndGlobalSection
-	GlobalSection(ProjectConfiguration) = postSolution
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug.ActiveCfg = Debug|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug.Build.0 = Debug|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release.ActiveCfg = Release|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release.Build.0 = Release|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseAxp.ActiveCfg = ReleaseAxp|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseAxp.Build.0 = ReleaseAxp|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm.ActiveCfg = ReleaseWithoutAsm|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm.Build.0 = ReleaseWithoutAsm|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutCrtdll.ActiveCfg = ReleaseAxp|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutCrtdll.Build.0 = ReleaseAxp|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug.ActiveCfg = Debug|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug.Build.0 = Debug|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release.ActiveCfg = Release|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release.Build.0 = Release|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseAxp.ActiveCfg = ReleaseAxp|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseAxp.Build.0 = ReleaseAxp|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm.ActiveCfg = ReleaseWithoutAsm|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm.Build.0 = ReleaseWithoutAsm|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutCrtdll.ActiveCfg = ReleaseWithoutCrtdll|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutCrtdll.Build.0 = ReleaseWithoutCrtdll|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug.ActiveCfg = Debug|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug.Build.0 = Debug|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release.ActiveCfg = Release|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release.Build.0 = Release|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAxp.ActiveCfg = Release|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAxp.Build.0 = Release|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm.ActiveCfg = Release|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm.Build.0 = Release|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutCrtdll.ActiveCfg = Release|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutCrtdll.Build.0 = Release|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug.ActiveCfg = Debug|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug.Build.0 = Debug|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release.ActiveCfg = Release|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release.Build.0 = Release|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseAxp.ActiveCfg = Release|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseAxp.Build.0 = Release|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm.ActiveCfg = Release|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm.Build.0 = Release|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutCrtdll.ActiveCfg = Release|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutCrtdll.Build.0 = Release|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.Debug.ActiveCfg = Debug|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.Debug.Build.0 = Debug|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.Release.ActiveCfg = Release|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.Release.Build.0 = Release|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.ReleaseAxp.ActiveCfg = Release|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.ReleaseAxp.Build.0 = Release|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.ReleaseWithoutAsm.ActiveCfg = Release|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.ReleaseWithoutAsm.Build.0 = Release|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.ReleaseWithoutCrtdll.ActiveCfg = Release|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654C}.ReleaseWithoutCrtdll.Build.0 = Release|Win32
-	EndGlobalSection
-	GlobalSection(ExtensibilityGlobals) = postSolution
-	EndGlobalSection
-	GlobalSection(ExtensibilityAddIns) = postSolution
-	EndGlobalSection
-EndGlobal
diff --git a/third_party/zlib/contrib/vstudio/vc7/zlibvc.vcproj b/third_party/zlib/contrib/vstudio/vc7/zlibvc.vcproj
deleted file mode 100644
index 8533b49..0000000
--- a/third_party/zlib/contrib/vstudio/vc7/zlibvc.vcproj
+++ /dev/null
@@ -1,445 +0,0 @@
-<?xml version="1.0" encoding = "Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="7.00"
-	Name="zlibvc"
-	SccProjectName=""
-	SccLocalPath="">
-	<Platforms>
-		<Platform
-			Name="Win32"/>
-	</Platforms>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory=".\DebugDll"
-			IntermediateDirectory=".\DebugDll"
-			ConfigurationType="2"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE">
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32,ZLIB_WINAPI,ASMV,ASMINF"
-				ExceptionHandling="FALSE"
-				RuntimeLibrary="1"
-				PrecompiledHeaderFile=".\DebugDll/zlibvc.pch"
-				AssemblerListingLocation=".\DebugDll/"
-				ObjectFile=".\DebugDll/"
-				ProgramDataBaseFileName=".\DebugDll/"
-				WarningLevel="3"
-				SuppressStartupBanner="TRUE"
-				DebugInformationFormat="4"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj"
-				OutputFile=".\DebugDll\zlibwapi.dll"
-				LinkIncremental="2"
-				SuppressStartupBanner="TRUE"
-				ModuleDefinitionFile=".\zlibvc.def"
-				GenerateDebugInformation="TRUE"
-				ProgramDatabaseFile=".\DebugDll/zlibwapi.pdb"
-				SubSystem="2"
-				ImportLibrary=".\DebugDll/zlibwapi.lib"/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="_DEBUG"
-				MkTypLibCompatible="TRUE"
-				SuppressStartupBanner="TRUE"
-				TargetEnvironment="1"
-				TypeLibraryName=".\DebugDll/zlibvc.tlb"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="_DEBUG"
-				Culture="1036"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCWebDeploymentTool"/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseWithoutAsm|Win32"
-			OutputDirectory=".\zlibDllWithoutAsm"
-			IntermediateDirectory=".\zlibDllWithoutAsm"
-			ConfigurationType="2"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE"
-			WholeProgramOptimization="TRUE">
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32,ZLIB_WINAPI"
-				StringPooling="TRUE"
-				ExceptionHandling="FALSE"
-				RuntimeLibrary="0"
-				EnableFunctionLevelLinking="TRUE"
-				PrecompiledHeaderFile=".\zlibDllWithoutAsm/zlibvc.pch"
-				AssemblerOutput="2"
-				AssemblerListingLocation=".\zlibDllWithoutAsm/"
-				ObjectFile=".\zlibDllWithoutAsm/"
-				ProgramDataBaseFileName=".\zlibDllWithoutAsm/"
-				BrowseInformation="1"
-				WarningLevel="3"
-				SuppressStartupBanner="TRUE"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="crtdll.lib"
-				OutputFile=".\zlibDllWithoutAsm\zlibwapi.dll"
-				LinkIncremental="1"
-				SuppressStartupBanner="TRUE"
-				IgnoreAllDefaultLibraries="TRUE"
-				ModuleDefinitionFile=".\zlibvc.def"
-				ProgramDatabaseFile=".\zlibDllWithoutAsm/zlibwapi.pdb"
-				GenerateMapFile="TRUE"
-				MapFileName=".\zlibDllWithoutAsm/zlibwapi.map"
-				SubSystem="2"
-				OptimizeForWindows98="1"
-				ImportLibrary=".\zlibDllWithoutAsm/zlibwapi.lib"/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="NDEBUG"
-				MkTypLibCompatible="TRUE"
-				SuppressStartupBanner="TRUE"
-				TargetEnvironment="1"
-				TypeLibraryName=".\zlibDllWithoutAsm/zlibvc.tlb"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1036"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCWebDeploymentTool"/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseWithoutCrtdll|Win32"
-			OutputDirectory=".\zlibDllWithoutCrtDll"
-			IntermediateDirectory=".\zlibDllWithoutCrtDll"
-			ConfigurationType="2"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE"
-			WholeProgramOptimization="TRUE">
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32,ZLIB_WINAPI,ASMV,ASMINF"
-				StringPooling="TRUE"
-				ExceptionHandling="FALSE"
-				RuntimeLibrary="0"
-				EnableFunctionLevelLinking="TRUE"
-				PrecompiledHeaderFile=".\zlibDllWithoutCrtDll/zlibvc.pch"
-				AssemblerOutput="2"
-				AssemblerListingLocation=".\zlibDllWithoutCrtDll/"
-				ObjectFile=".\zlibDllWithoutCrtDll/"
-				ProgramDataBaseFileName=".\zlibDllWithoutCrtDll/"
-				BrowseInformation="1"
-				WarningLevel="3"
-				SuppressStartupBanner="TRUE"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj "
-				OutputFile=".\zlibDllWithoutCrtDll\zlibwapi.dll"
-				LinkIncremental="1"
-				SuppressStartupBanner="TRUE"
-				IgnoreAllDefaultLibraries="FALSE"
-				ModuleDefinitionFile=".\zlibvc.def"
-				ProgramDatabaseFile=".\zlibDllWithoutCrtDll/zlibwapi.pdb"
-				GenerateMapFile="TRUE"
-				MapFileName=".\zlibDllWithoutCrtDll/zlibwapi.map"
-				SubSystem="2"
-				OptimizeForWindows98="1"
-				ImportLibrary=".\zlibDllWithoutCrtDll/zlibwapi.lib"/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="NDEBUG"
-				MkTypLibCompatible="TRUE"
-				SuppressStartupBanner="TRUE"
-				TargetEnvironment="1"
-				TypeLibraryName=".\zlibDllWithoutCrtDll/zlibvc.tlb"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1036"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCWebDeploymentTool"/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseAxp|Win32"
-			OutputDirectory=".\zlibvc__"
-			IntermediateDirectory=".\zlibvc__"
-			ConfigurationType="2"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE"
-			WholeProgramOptimization="TRUE">
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32,ZLIB_WINAPI"
-				StringPooling="TRUE"
-				ExceptionHandling="FALSE"
-				RuntimeLibrary="0"
-				EnableFunctionLevelLinking="TRUE"
-				PrecompiledHeaderFile=".\zlibvc__/zlibvc.pch"
-				AssemblerOutput="2"
-				AssemblerListingLocation=".\zlibvc__/"
-				ObjectFile=".\zlibvc__/"
-				ProgramDataBaseFileName=".\zlibvc__/"
-				BrowseInformation="1"
-				WarningLevel="3"
-				SuppressStartupBanner="TRUE"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="crtdll.lib"
-				OutputFile="zlibvc__\zlibwapi.dll"
-				LinkIncremental="1"
-				SuppressStartupBanner="TRUE"
-				IgnoreAllDefaultLibraries="TRUE"
-				ModuleDefinitionFile=".\zlibvc.def"
-				ProgramDatabaseFile=".\zlibvc__/zlibwapi.pdb"
-				GenerateMapFile="TRUE"
-				MapFileName=".\zlibvc__/zlibwapi.map"
-				SubSystem="2"
-				ImportLibrary=".\zlibvc__/zlibwapi.lib"/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="NDEBUG"
-				MkTypLibCompatible="TRUE"
-				SuppressStartupBanner="TRUE"
-				TargetEnvironment="1"
-				TypeLibraryName=".\zlibvc__/zlibvc.tlb"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1036"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCWebDeploymentTool"/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory=".\ReleaseDll"
-			IntermediateDirectory=".\ReleaseDll"
-			ConfigurationType="2"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="FALSE"
-			WholeProgramOptimization="TRUE">
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32,ZLIB_WINAPI,ASMV,ASMINF"
-				StringPooling="TRUE"
-				ExceptionHandling="FALSE"
-				RuntimeLibrary="0"
-				EnableFunctionLevelLinking="TRUE"
-				PrecompiledHeaderFile=".\ReleaseDll/zlibvc.pch"
-				AssemblerOutput="2"
-				AssemblerListingLocation=".\ReleaseDll/"
-				ObjectFile=".\ReleaseDll/"
-				ProgramDataBaseFileName=".\ReleaseDll/"
-				BrowseInformation="1"
-				WarningLevel="3"
-				SuppressStartupBanner="TRUE"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj crtdll.lib"
-				OutputFile=".\ReleaseDll\zlibwapi.dll"
-				LinkIncremental="1"
-				SuppressStartupBanner="TRUE"
-				IgnoreAllDefaultLibraries="TRUE"
-				ModuleDefinitionFile=".\zlibvc.def"
-				ProgramDatabaseFile=".\ReleaseDll/zlibwapi.pdb"
-				GenerateMapFile="TRUE"
-				MapFileName=".\ReleaseDll/zlibwapi.map"
-				SubSystem="2"
-				OptimizeForWindows98="1"
-				ImportLibrary=".\ReleaseDll/zlibwapi.lib"/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="NDEBUG"
-				MkTypLibCompatible="TRUE"
-				SuppressStartupBanner="TRUE"
-				TargetEnvironment="1"
-				TypeLibraryName=".\Release/zlibvc.tlb"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1036"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCWebDeploymentTool"/>
-		</Configuration>
-	</Configurations>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90">
-			<File
-				RelativePath="..\..\..\adler32.c">
-			</File>
-			<File
-				RelativePath="..\..\..\compress.c">
-			</File>
-			<File
-				RelativePath="..\..\..\crc32.c">
-			</File>
-			<File
-				RelativePath="..\..\..\deflate.c">
-			</File>
-			<File
-				RelativePath="..\..\masmx86\gvmat32c.c">
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|Win32"
-					ExcludedFromBuild="TRUE">
-					<Tool
-						Name="VCCLCompilerTool"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\..\gzio.c">
-			</File>
-			<File
-				RelativePath="..\..\..\infback.c">
-			</File>
-			<File
-				RelativePath="..\..\..\inffast.c">
-			</File>
-			<File
-				RelativePath="..\..\..\inflate.c">
-			</File>
-			<File
-				RelativePath="..\..\..\inftrees.c">
-			</File>
-			<File
-				RelativePath="..\..\minizip\ioapi.c">
-			</File>
-			<File
-				RelativePath="..\..\minizip\iowin32.c">
-			</File>
-			<File
-				RelativePath="..\..\..\trees.c">
-			</File>
-			<File
-				RelativePath="..\..\..\uncompr.c">
-			</File>
-			<File
-				RelativePath="..\..\minizip\unzip.c">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions="ZLIB_INTERNAL"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\minizip\zip.c">
-				<FileConfiguration
-					Name="Release|Win32">
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions="ZLIB_INTERNAL"/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath=".\zlib.rc">
-			</File>
-			<File
-				RelativePath=".\zlibvc.def">
-			</File>
-			<File
-				RelativePath="..\..\..\zutil.c">
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;fi;fd">
-			<File
-				RelativePath="..\..\..\deflate.h">
-			</File>
-			<File
-				RelativePath="..\..\..\infblock.h">
-			</File>
-			<File
-				RelativePath="..\..\..\infcodes.h">
-			</File>
-			<File
-				RelativePath="..\..\..\inffast.h">
-			</File>
-			<File
-				RelativePath="..\..\..\inftrees.h">
-			</File>
-			<File
-				RelativePath="..\..\..\infutil.h">
-			</File>
-			<File
-				RelativePath="..\..\..\zconf.h">
-			</File>
-			<File
-				RelativePath="..\..\..\zlib.h">
-			</File>
-			<File
-				RelativePath="..\..\..\zutil.h">
-			</File>
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe">
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/third_party/zlib/contrib/vstudio/vc8/miniunz.vcproj b/third_party/zlib/contrib/vstudio/vc8/miniunz.vcproj
deleted file mode 100644
index 4af53e8..0000000
--- a/third_party/zlib/contrib/vstudio/vc8/miniunz.vcproj
+++ /dev/null
@@ -1,566 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8,00"
-	Name="miniunz"
-	ProjectGUID="{C52F9E7B-498A-42BE-8DB4-85A15694382A}"
-	Keyword="Win32Proj"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-		<Platform
-			Name="x64"
-		/>
-		<Platform
-			Name="Itanium"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="x86\MiniUnzip$(ConfigurationName)"
-			IntermediateDirectory="x86\MiniUnzip$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="1"
-				BufferSecurityCheck="false"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="4"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="x86\ZlibDllDebug\zlibwapi.lib"
-				OutputFile="$(OutDir)/miniunz.exe"
-				LinkIncremental="2"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/miniunz.pdb"
-				SubSystem="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|x64"
-			OutputDirectory="x64\MiniUnzip$(ConfigurationName)"
-			IntermediateDirectory="x64\MiniUnzip$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="3"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="false"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="x64\ZlibDllDebug\zlibwapi.lib"
-				OutputFile="$(OutDir)/miniunz.exe"
-				LinkIncremental="2"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/miniunz.pdb"
-				SubSystem="1"
-				TargetMachine="17"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|Itanium"
-			OutputDirectory="ia64\MiniUnzip$(ConfigurationName)"
-			IntermediateDirectory="ia64\MiniUnzip$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="2"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="false"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="ia64\ZlibDllDebug\zlibwapi.lib"
-				OutputFile="$(OutDir)/miniunz.exe"
-				LinkIncremental="2"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/miniunz.pdb"
-				SubSystem="1"
-				TargetMachine="5"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="x86\MiniUnzip$(ConfigurationName)"
-			IntermediateDirectory="x86\MiniUnzip$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE"
-				StringPooling="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="0"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="x86\ZlibDllRelease\zlibwapi.lib"
-				OutputFile="$(OutDir)/miniunz.exe"
-				LinkIncremental="1"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|x64"
-			OutputDirectory="x64\MiniUnzip$(ConfigurationName)"
-			IntermediateDirectory="x64\MiniUnzip$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="3"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64"
-				StringPooling="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="x64\ZlibDllRelease\zlibwapi.lib"
-				OutputFile="$(OutDir)/miniunz.exe"
-				LinkIncremental="1"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="17"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Itanium"
-			OutputDirectory="ia64\MiniUnzip$(ConfigurationName)"
-			IntermediateDirectory="ia64\MiniUnzip$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="2"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64"
-				StringPooling="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="ia64\ZlibDllRelease\zlibwapi.lib"
-				OutputFile="$(OutDir)/miniunz.exe"
-				LinkIncremental="1"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="5"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
-			>
-			<File
-				RelativePath="..\..\minizip\miniunz.c"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;inc"
-			>
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-			>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/third_party/zlib/contrib/vstudio/vc8/minizip.vcproj b/third_party/zlib/contrib/vstudio/vc8/minizip.vcproj
deleted file mode 100644
index 85f64c4..0000000
--- a/third_party/zlib/contrib/vstudio/vc8/minizip.vcproj
+++ /dev/null
@@ -1,563 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8,00"
-	Name="minizip"
-	ProjectGUID="{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}"
-	Keyword="Win32Proj"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-		<Platform
-			Name="x64"
-		/>
-		<Platform
-			Name="Itanium"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="x86\MiniZip$(ConfigurationName)"
-			IntermediateDirectory="x86\MiniZip$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="1"
-				BufferSecurityCheck="false"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="4"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="x86\ZlibDllDebug\zlibwapi.lib"
-				OutputFile="$(OutDir)/minizip.exe"
-				LinkIncremental="2"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/minizip.pdb"
-				SubSystem="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|x64"
-			OutputDirectory="x64\$(ConfigurationName)"
-			IntermediateDirectory="x64\$(ConfigurationName)"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="3"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="false"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="x64\ZlibDllDebug\zlibwapi.lib"
-				OutputFile="$(OutDir)/minizip.exe"
-				LinkIncremental="2"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/minizip.pdb"
-				SubSystem="1"
-				TargetMachine="17"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|Itanium"
-			OutputDirectory="ia64\$(ConfigurationName)"
-			IntermediateDirectory="ia64\$(ConfigurationName)"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="2"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="false"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="ia64\ZlibDllDebug\zlibwapi.lib"
-				OutputFile="$(OutDir)/minizip.exe"
-				LinkIncremental="2"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/minizip.pdb"
-				SubSystem="1"
-				TargetMachine="5"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="x86\MiniZip$(ConfigurationName)"
-			IntermediateDirectory="x86\MiniZip$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE"
-				StringPooling="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="0"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="x86\ZlibDllRelease\zlibwapi.lib"
-				OutputFile="$(OutDir)/minizip.exe"
-				LinkIncremental="1"
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|x64"
-			OutputDirectory="x64\$(ConfigurationName)"
-			IntermediateDirectory="x64\$(ConfigurationName)"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="3"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64"
-				StringPooling="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="x64\ZlibDllRelease\zlibwapi.lib"
-				OutputFile="$(OutDir)/minizip.exe"
-				LinkIncremental="1"
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="17"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Itanium"
-			OutputDirectory="ia64\$(ConfigurationName)"
-			IntermediateDirectory="ia64\$(ConfigurationName)"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="2"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64"
-				StringPooling="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="ia64\ZlibDllRelease\zlibwapi.lib"
-				OutputFile="$(OutDir)/minizip.exe"
-				LinkIncremental="1"
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="5"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
-			>
-			<File
-				RelativePath="..\..\minizip\minizip.c"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;inc"
-			>
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-			>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/third_party/zlib/contrib/vstudio/vc8/testzlib.vcproj b/third_party/zlib/contrib/vstudio/vc8/testzlib.vcproj
deleted file mode 100644
index 68c3539..0000000
--- a/third_party/zlib/contrib/vstudio/vc8/testzlib.vcproj
+++ /dev/null
@@ -1,948 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8,00"
-	Name="testzlib"
-	ProjectGUID="{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"
-	RootNamespace="testzlib"
-	Keyword="Win32Proj"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-		<Platform
-			Name="x64"
-		/>
-		<Platform
-			Name="Itanium"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="x86\TestZlib$(ConfigurationName)"
-			IntermediateDirectory="x86\TestZlib$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\.."
-				PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="1"
-				BufferSecurityCheck="false"
-				UsePrecompiledHeader="0"
-				AssemblerOutput="4"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="4"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="2"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
-				SubSystem="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|x64"
-			OutputDirectory="x64\TestZlib$(ConfigurationName)"
-			IntermediateDirectory="x64\TestZlib$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalIncludeDirectories="..\..\.."
-				PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="false"
-				AssemblerListingLocation="$(IntDir)\"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj"
-				GenerateManifest="false"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|Itanium"
-			OutputDirectory="ia64\TestZlib$(ConfigurationName)"
-			IntermediateDirectory="ia64\TestZlib$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="2"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\.."
-				PreprocessorDefinitions="ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="false"
-				UsePrecompiledHeader="0"
-				AssemblerOutput="4"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="2"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
-				SubSystem="1"
-				TargetMachine="5"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseWithoutAsm|Win32"
-			OutputDirectory="x86\TestZlib$(ConfigurationName)"
-			IntermediateDirectory="x86\TestZlib$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			CharacterSet="2"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\.."
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
-				StringPooling="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="0"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="1"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseWithoutAsm|x64"
-			OutputDirectory="x64\TestZlib$(ConfigurationName)"
-			IntermediateDirectory="x64\TestZlib$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalIncludeDirectories="..\..\.."
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				AssemblerListingLocation="$(IntDir)\"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies=""
-				GenerateManifest="false"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseWithoutAsm|Itanium"
-			OutputDirectory="ia64\TestZlib$(ConfigurationName)"
-			IntermediateDirectory="ia64\TestZlib$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			CharacterSet="2"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="2"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\.."
-				PreprocessorDefinitions="ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
-				StringPooling="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="1"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="5"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="x86\TestZlib$(ConfigurationName)"
-			IntermediateDirectory="x86\TestZlib$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			CharacterSet="2"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\.."
-				PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
-				StringPooling="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="0"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="1"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|x64"
-			OutputDirectory="x64\TestZlib$(ConfigurationName)"
-			IntermediateDirectory="x64\TestZlib$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalIncludeDirectories="..\..\.."
-				PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				AssemblerListingLocation="$(IntDir)\"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj"
-				GenerateManifest="false"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Itanium"
-			OutputDirectory="ia64\TestZlib$(ConfigurationName)"
-			IntermediateDirectory="ia64\TestZlib$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			CharacterSet="2"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="2"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\.."
-				PreprocessorDefinitions="ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
-				StringPooling="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="1"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="5"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
-			>
-			<File
-				RelativePath="..\..\..\adler32.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\compress.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\crc32.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\deflate.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\masmx86\gvmat32c.c"
-				>
-				<FileConfiguration
-					Name="Debug|x64"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|x64"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|x64"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win64 (AMD64)"
-					ExcludedFromBuild="TRUE"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Win64 (AMD64)"
-					ExcludedFromBuild="TRUE"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseAsm|Win64 (AMD64)"
-					ExcludedFromBuild="TRUE"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\..\infback.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\masmx64\inffas8664.c"
-				>
-				<FileConfiguration
-					Name="Debug|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\..\inffast.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\inflate.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\inftrees.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\testzlib\testzlib.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\trees.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\uncompr.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\zutil.c"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;inc"
-			>
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-			>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/third_party/zlib/contrib/vstudio/vc8/testzlibdll.vcproj b/third_party/zlib/contrib/vstudio/vc8/testzlibdll.vcproj
deleted file mode 100644
index f38ab5e..0000000
--- a/third_party/zlib/contrib/vstudio/vc8/testzlibdll.vcproj
+++ /dev/null
@@ -1,567 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8,00"
-	Name="TestZlibDll"
-	ProjectGUID="{C52F9E7B-498A-42BE-8DB4-85A15694366A}"
-	Keyword="Win32Proj"
-	SignManifests="true"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-		<Platform
-			Name="x64"
-		/>
-		<Platform
-			Name="Itanium"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="x86\TestZlibDll$(ConfigurationName)"
-			IntermediateDirectory="x86\TestZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="1"
-				BufferSecurityCheck="false"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="4"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="x86\ZlibDllDebug\zlibwapi.lib"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="2"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
-				SubSystem="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|x64"
-			OutputDirectory="x64\TestZlibDll$(ConfigurationName)"
-			IntermediateDirectory="x64\TestZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="3"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="false"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="x64\ZlibDllDebug\zlibwapi.lib"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="2"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
-				SubSystem="1"
-				TargetMachine="17"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|Itanium"
-			OutputDirectory="ia64\TestZlibDll$(ConfigurationName)"
-			IntermediateDirectory="ia64\TestZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="2"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="false"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="ia64\ZlibDllDebug\zlibwapi.lib"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="2"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
-				SubSystem="1"
-				TargetMachine="5"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="x86\TestZlibDll$(ConfigurationName)"
-			IntermediateDirectory="x86\TestZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE"
-				StringPooling="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="0"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="x86\ZlibDllRelease\zlibwapi.lib"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="1"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|x64"
-			OutputDirectory="x64\TestZlibDll$(ConfigurationName)"
-			IntermediateDirectory="x64\TestZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="3"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64"
-				StringPooling="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="x64\ZlibDllRelease\zlibwapi.lib"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="1"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="17"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Itanium"
-			OutputDirectory="ia64\TestZlibDll$(ConfigurationName)"
-			IntermediateDirectory="ia64\TestZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="1"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="2"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="2"
-				InlineFunctionExpansion="1"
-				OmitFramePointers="true"
-				AdditionalIncludeDirectories="..\..\..;..\..\minizip"
-				PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64"
-				StringPooling="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				UsePrecompiledHeader="0"
-				AssemblerListingLocation="$(IntDir)\"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="ia64\ZlibDllRelease\zlibwapi.lib"
-				OutputFile="$(OutDir)/testzlib.exe"
-				LinkIncremental="1"
-				GenerateManifest="false"
-				GenerateDebugInformation="true"
-				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				OptimizeForWindows98="1"
-				TargetMachine="5"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
-			>
-			<File
-				RelativePath="..\..\testzlib\testzlib.c"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;inc"
-			>
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-			>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/third_party/zlib/contrib/vstudio/vc8/zlib.rc b/third_party/zlib/contrib/vstudio/vc8/zlib.rc
deleted file mode 100644
index 72cb8b4..0000000
--- a/third_party/zlib/contrib/vstudio/vc8/zlib.rc
+++ /dev/null
@@ -1,32 +0,0 @@
-#include <windows.h>
-
-#define IDR_VERSION1  1
-IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
-  FILEVERSION	 1,2,3,0
-  PRODUCTVERSION 1,2,3,0
-  FILEFLAGSMASK	VS_FFI_FILEFLAGSMASK
-  FILEFLAGS	0
-  FILEOS	VOS_DOS_WINDOWS32
-  FILETYPE	VFT_DLL
-  FILESUBTYPE	0	// not used
-BEGIN
-  BLOCK "StringFileInfo"
-  BEGIN
-    BLOCK "040904E4"
-    //language ID = U.S. English, char set = Windows, Multilingual
-
-    BEGIN
-      VALUE "FileDescription", "zlib data compression library\0"
-      VALUE "FileVersion",	"1.2.3.0\0"
-      VALUE "InternalName",	"zlib\0"
-      VALUE "OriginalFilename",	"zlib.dll\0"
-      VALUE "ProductName",	"ZLib.DLL\0"
-      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
-      VALUE "LegalCopyright", "(C) 1995-2003 Jean-loup Gailly & Mark Adler\0"
-    END
-  END
-  BLOCK "VarFileInfo"
-  BEGIN
-    VALUE "Translation", 0x0409, 1252
-  END
-END
diff --git a/third_party/zlib/contrib/vstudio/vc8/zlibstat.vcproj b/third_party/zlib/contrib/vstudio/vc8/zlibstat.vcproj
deleted file mode 100644
index fb97037..0000000
--- a/third_party/zlib/contrib/vstudio/vc8/zlibstat.vcproj
+++ /dev/null
@@ -1,870 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8,00"
-	Name="zlibstat"
-	ProjectGUID="{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-		<Platform
-			Name="x64"
-		/>
-		<Platform
-			Name="Itanium"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="x86\ZlibStat$(ConfigurationName)"
-			IntermediateDirectory="x86\ZlibStat$(ConfigurationName)\Tmp"
-			ConfigurationType="4"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
-				ExceptionHandling="0"
-				RuntimeLibrary="1"
-				BufferSecurityCheck="false"
-				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="1"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLibrarianTool"
-				AdditionalOptions="/MACHINE:X86 /NODEFAULTLIB"
-				OutputFile="$(OutDir)\zlibstat.lib"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|x64"
-			OutputDirectory="x64\ZlibStat$(ConfigurationName)"
-			IntermediateDirectory="x64\ZlibStat$(ConfigurationName)\Tmp"
-			ConfigurationType="4"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="3"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
-				ExceptionHandling="0"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="false"
-				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="1"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLibrarianTool"
-				AdditionalOptions="/MACHINE:AMD64 /NODEFAULTLIB"
-				OutputFile="$(OutDir)\zlibstat.lib"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|Itanium"
-			OutputDirectory="ia64\ZlibStat$(ConfigurationName)"
-			IntermediateDirectory="ia64\ZlibStat$(ConfigurationName)\Tmp"
-			ConfigurationType="4"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="2"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
-				ExceptionHandling="0"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="false"
-				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-				Detect64BitPortabilityProblems="true"
-				DebugInformationFormat="1"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLibrarianTool"
-				AdditionalOptions="/MACHINE:IA64 /NODEFAULTLIB"
-				OutputFile="$(OutDir)\zlibstat.lib"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="x86\ZlibStat$(ConfigurationName)"
-			IntermediateDirectory="x86\ZlibStat$(ConfigurationName)\Tmp"
-			ConfigurationType="4"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ASMV;ASMINF"
-				StringPooling="true"
-				ExceptionHandling="0"
-				RuntimeLibrary="0"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLibrarianTool"
-				AdditionalOptions="/MACHINE:X86 /NODEFAULTLIB"
-				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj "
-				OutputFile="$(OutDir)\zlibstat.lib"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|x64"
-			OutputDirectory="x64\ZlibStat$(ConfigurationName)"
-			IntermediateDirectory="x64\ZlibStat$(ConfigurationName)\Tmp"
-			ConfigurationType="4"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="3"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ASMV;ASMINF;WIN64"
-				StringPooling="true"
-				ExceptionHandling="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLibrarianTool"
-				AdditionalOptions="/MACHINE:AMD64 /NODEFAULTLIB"
-				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj "
-				OutputFile="$(OutDir)\zlibstat.lib"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Itanium"
-			OutputDirectory="ia64\ZlibStat$(ConfigurationName)"
-			IntermediateDirectory="ia64\ZlibStat$(ConfigurationName)\Tmp"
-			ConfigurationType="4"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="2"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
-				StringPooling="true"
-				ExceptionHandling="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLibrarianTool"
-				AdditionalOptions="/MACHINE:IA64 /NODEFAULTLIB"
-				OutputFile="$(OutDir)\zlibstat.lib"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseWithoutAsm|Win32"
-			OutputDirectory="x86\ZlibStat$(ConfigurationName)"
-			IntermediateDirectory="x86\ZlibStat$(ConfigurationName)\Tmp"
-			ConfigurationType="4"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE"
-				StringPooling="true"
-				ExceptionHandling="0"
-				RuntimeLibrary="0"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLibrarianTool"
-				AdditionalOptions="/MACHINE:X86 /NODEFAULTLIB"
-				OutputFile="$(OutDir)\zlibstat.lib"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseWithoutAsm|x64"
-			OutputDirectory="x64\ZlibStat$(ConfigurationName)"
-			IntermediateDirectory="x64\ZlibStat$(ConfigurationName)\Tmp"
-			ConfigurationType="4"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="3"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
-				StringPooling="true"
-				ExceptionHandling="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLibrarianTool"
-				AdditionalOptions="/MACHINE:AMD64 /NODEFAULTLIB"
-				OutputFile="$(OutDir)\zlibstat.lib"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseWithoutAsm|Itanium"
-			OutputDirectory="ia64\ZlibStat$(ConfigurationName)"
-			IntermediateDirectory="ia64\ZlibStat$(ConfigurationName)\Tmp"
-			ConfigurationType="4"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="2"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN64"
-				StringPooling="true"
-				ExceptionHandling="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLibrarianTool"
-				AdditionalOptions="/MACHINE:IA64 /NODEFAULTLIB"
-				OutputFile="$(OutDir)\zlibstat.lib"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			>
-			<File
-				RelativePath="..\..\..\adler32.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\compress.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\crc32.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\deflate.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\masmx86\gvmat32c.c"
-				>
-				<FileConfiguration
-					Name="Debug|x64"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|x64"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|x64"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\..\gzio.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\infback.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\masmx64\inffas8664.c"
-				>
-				<FileConfiguration
-					Name="Debug|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\..\inffast.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\inflate.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\inftrees.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\minizip\ioapi.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\trees.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\uncompr.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\minizip\unzip.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\minizip\zip.c"
-				>
-			</File>
-			<File
-				RelativePath=".\zlib.rc"
-				>
-			</File>
-			<File
-				RelativePath=".\zlibvc.def"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\zutil.c"
-				>
-			</File>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/third_party/zlib/contrib/vstudio/vc8/zlibvc.def b/third_party/zlib/contrib/vstudio/vc8/zlibvc.def
deleted file mode 100644
index a40e715..0000000
--- a/third_party/zlib/contrib/vstudio/vc8/zlibvc.def
+++ /dev/null
@@ -1,92 +0,0 @@
-
-VERSION		1.23
-
-HEAPSIZE	1048576,8192
-
-EXPORTS
-        adler32                                  @1
-        compress                                 @2
-        crc32                                    @3
-        deflate                                  @4
-        deflateCopy                              @5
-        deflateEnd                               @6
-        deflateInit2_                            @7
-        deflateInit_                             @8
-        deflateParams                            @9
-        deflateReset                             @10
-        deflateSetDictionary                     @11
-        gzclose                                  @12
-        gzdopen                                  @13
-        gzerror                                  @14
-        gzflush                                  @15
-        gzopen                                   @16
-        gzread                                   @17
-        gzwrite                                  @18
-        inflate                                  @19
-        inflateEnd                               @20
-        inflateInit2_                            @21
-        inflateInit_                             @22
-        inflateReset                             @23
-        inflateSetDictionary                     @24
-        inflateSync                              @25
-        uncompress                               @26
-        zlibVersion                              @27
-        gzprintf                                 @28
-        gzputc                                   @29
-        gzgetc                                   @30
-        gzseek                                   @31
-        gzrewind                                 @32
-        gztell                                   @33
-        gzeof                                    @34
-        gzsetparams                              @35
-        zError                                   @36
-        inflateSyncPoint                         @37
-        get_crc_table                            @38
-        compress2                                @39
-        gzputs                                   @40
-        gzgets                                   @41
-        inflateCopy                              @42
-        inflateBackInit_                         @43
-        inflateBack                              @44
-        inflateBackEnd                           @45
-        compressBound                            @46
-        deflateBound                             @47
-        gzclearerr                               @48
-        gzungetc                                 @49
-        zlibCompileFlags                         @50
-        deflatePrime                             @51
-
-        unzOpen                                  @61
-        unzClose                                 @62
-        unzGetGlobalInfo                         @63
-        unzGetCurrentFileInfo                    @64
-        unzGoToFirstFile                         @65
-        unzGoToNextFile                          @66
-        unzOpenCurrentFile                       @67
-        unzReadCurrentFile                       @68
-        unzOpenCurrentFile3                      @69
-        unztell                                  @70
-        unzeof                                   @71
-        unzCloseCurrentFile                      @72
-        unzGetGlobalComment                      @73
-        unzStringFileNameCompare                 @74
-        unzLocateFile                            @75
-        unzGetLocalExtrafield                    @76
-        unzOpen2                                 @77
-        unzOpenCurrentFile2                      @78
-        unzOpenCurrentFilePassword               @79
-
-        zipOpen                                  @80
-        zipOpenNewFileInZip                      @81
-        zipWriteInFileInZip                      @82
-        zipCloseFileInZip                        @83
-        zipClose                                 @84
-        zipOpenNewFileInZip2                     @86
-        zipCloseFileInZipRaw                     @87
-        zipOpen2                                 @88
-        zipOpenNewFileInZip3                     @89
-
-        unzGetFilePos                            @100
-        unzGoToFilePos                           @101
-
-        fill_win32_filefunc                      @110
diff --git a/third_party/zlib/contrib/vstudio/vc8/zlibvc.sln b/third_party/zlib/contrib/vstudio/vc8/zlibvc.sln
deleted file mode 100644
index a815a55..0000000
--- a/third_party/zlib/contrib/vstudio/vc8/zlibvc.sln
+++ /dev/null
@@ -1,144 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual Studio 2005
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestZlibDll", "testzlibdll.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}"
-	ProjectSection(ProjectDependencies) = postProject
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}"
-	ProjectSection(ProjectDependencies) = postProject
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}"
-	ProjectSection(ProjectDependencies) = postProject
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D}
-	EndProjectSection
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Itanium = Debug|Itanium
-		Debug|Win32 = Debug|Win32
-		Debug|x64 = Debug|x64
-		Release|Itanium = Release|Itanium
-		Release|Win32 = Release|Win32
-		Release|x64 = Release|x64
-		ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium
-		ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32
-		ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Itanium
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.Build.0 = Debug|Itanium
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Itanium
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.Build.0 = Release|Itanium
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = ReleaseWithoutAsm|x64
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = ReleaseWithoutAsm|x64
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64
-		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Itanium
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.Build.0 = Debug|Itanium
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Itanium
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.Build.0 = Release|Itanium
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64
-		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64
-		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.Build.0 = Debug|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.Build.0 = Release|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|Itanium
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Itanium
-		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.Build.0 = Debug|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.Build.0 = Release|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Itanium
-		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|Itanium
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal
diff --git a/third_party/zlib/contrib/vstudio/vc8/zlibvc.vcproj b/third_party/zlib/contrib/vstudio/vc8/zlibvc.vcproj
deleted file mode 100644
index e717011..0000000
--- a/third_party/zlib/contrib/vstudio/vc8/zlibvc.vcproj
+++ /dev/null
@@ -1,1219 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="8,00"
-	Name="zlibvc"
-	ProjectGUID="{8FD826F8-3739-44E6-8CC8-997122E53B8D}"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-		<Platform
-			Name="x64"
-		/>
-		<Platform
-			Name="Itanium"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="x86\ZlibDll$(ConfigurationName)"
-			IntermediateDirectory="x86\ZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="2"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="_DEBUG"
-				MkTypLibCompatible="true"
-				SuppressStartupBanner="true"
-				TargetEnvironment="1"
-				TypeLibraryName="$(OutDir)/zlibvc.tlb"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32,_CRT_SECURE_NO_DEPRECATE,ZLIB_WINAPI,ASMV,ASMINF"
-				ExceptionHandling="0"
-				RuntimeLibrary="1"
-				BufferSecurityCheck="false"
-				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				BrowseInformation="0"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-				DebugInformationFormat="4"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="_DEBUG"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj"
-				OutputFile="$(OutDir)\zlibwapi.dll"
-				LinkIncremental="2"
-				SuppressStartupBanner="true"
-				GenerateManifest="false"
-				ModuleDefinitionFile=".\zlibvc.def"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
-				GenerateMapFile="true"
-				MapFileName="$(OutDir)/zlibwapi.map"
-				SubSystem="2"
-				ImportLibrary="$(OutDir)/zlibwapi.lib"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|x64"
-			OutputDirectory="x64\ZlibDll$(ConfigurationName)"
-			IntermediateDirectory="x64\ZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="2"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="_DEBUG"
-				MkTypLibCompatible="true"
-				SuppressStartupBanner="true"
-				TargetEnvironment="3"
-				TypeLibraryName="$(OutDir)/zlibvc.tlb"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32,_CRT_SECURE_NO_DEPRECATE,ZLIB_WINAPI,ASMV,ASMINF;WIN64"
-				ExceptionHandling="0"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="false"
-				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				BrowseInformation="0"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="_DEBUG"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj "
-				OutputFile="$(OutDir)\zlibwapi.dll"
-				LinkIncremental="2"
-				SuppressStartupBanner="true"
-				GenerateManifest="false"
-				ModuleDefinitionFile=".\zlibvc.def"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
-				GenerateMapFile="true"
-				MapFileName="$(OutDir)/zlibwapi.map"
-				SubSystem="2"
-				ImportLibrary="$(OutDir)/zlibwapi.lib"
-				TargetMachine="17"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|Itanium"
-			OutputDirectory="ia64\ZlibDll$(ConfigurationName)"
-			IntermediateDirectory="ia64\ZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="2"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="_DEBUG"
-				MkTypLibCompatible="true"
-				SuppressStartupBanner="true"
-				TargetEnvironment="2"
-				TypeLibraryName="$(OutDir)/zlibvc.tlb"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;WIN64"
-				ExceptionHandling="0"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="false"
-				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				BrowseInformation="0"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-				DebugInformationFormat="3"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="_DEBUG"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\zlibwapi.dll"
-				LinkIncremental="2"
-				SuppressStartupBanner="true"
-				GenerateManifest="false"
-				ModuleDefinitionFile=".\zlibvc.def"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
-				GenerateMapFile="true"
-				MapFileName="$(OutDir)/zlibwapi.map"
-				SubSystem="2"
-				ImportLibrary="$(OutDir)/zlibwapi.lib"
-				TargetMachine="5"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseWithoutAsm|Win32"
-			OutputDirectory="x86\ZlibDll$(ConfigurationName)"
-			IntermediateDirectory="x86\ZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="2"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="NDEBUG"
-				MkTypLibCompatible="true"
-				SuppressStartupBanner="true"
-				TargetEnvironment="1"
-				TypeLibraryName="$(OutDir)/zlibvc.tlb"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32,_CRT_SECURE_NO_DEPRECATE,ZLIB_WINAPI"
-				StringPooling="true"
-				ExceptionHandling="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
-				AssemblerOutput="2"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				BrowseInformation="0"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/MACHINE:I386"
-				OutputFile="$(OutDir)\zlibwapi.dll"
-				LinkIncremental="1"
-				SuppressStartupBanner="true"
-				GenerateManifest="false"
-				IgnoreAllDefaultLibraries="false"
-				ModuleDefinitionFile=".\zlibvc.def"
-				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
-				GenerateMapFile="true"
-				MapFileName="$(OutDir)/zlibwapi.map"
-				SubSystem="2"
-				OptimizeForWindows98="1"
-				ImportLibrary="$(OutDir)/zlibwapi.lib"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseWithoutAsm|x64"
-			OutputDirectory="x64\ZlibDll$(ConfigurationName)"
-			IntermediateDirectory="x64\ZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="2"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="NDEBUG"
-				MkTypLibCompatible="true"
-				SuppressStartupBanner="true"
-				TargetEnvironment="3"
-				TypeLibraryName="$(OutDir)/zlibvc.tlb"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32,_CRT_SECURE_NO_DEPRECATE,ZLIB_WINAPI;WIN64"
-				StringPooling="true"
-				ExceptionHandling="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
-				AssemblerOutput="2"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				BrowseInformation="0"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\zlibwapi.dll"
-				LinkIncremental="1"
-				SuppressStartupBanner="true"
-				GenerateManifest="false"
-				IgnoreAllDefaultLibraries="false"
-				ModuleDefinitionFile=".\zlibvc.def"
-				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
-				GenerateMapFile="true"
-				MapFileName="$(OutDir)/zlibwapi.map"
-				SubSystem="2"
-				OptimizeForWindows98="1"
-				ImportLibrary="$(OutDir)/zlibwapi.lib"
-				TargetMachine="17"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="ReleaseWithoutAsm|Itanium"
-			OutputDirectory="ia64\ZlibDll$(ConfigurationName)"
-			IntermediateDirectory="ia64\ZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="2"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="NDEBUG"
-				MkTypLibCompatible="true"
-				SuppressStartupBanner="true"
-				TargetEnvironment="2"
-				TypeLibraryName="$(OutDir)/zlibvc.tlb"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32,_CRT_SECURE_NO_DEPRECATE,ZLIB_WINAPI;WIN64"
-				StringPooling="true"
-				ExceptionHandling="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
-				AssemblerOutput="2"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				BrowseInformation="0"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\zlibwapi.dll"
-				LinkIncremental="1"
-				SuppressStartupBanner="true"
-				GenerateManifest="false"
-				IgnoreAllDefaultLibraries="false"
-				ModuleDefinitionFile=".\zlibvc.def"
-				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
-				GenerateMapFile="true"
-				MapFileName="$(OutDir)/zlibwapi.map"
-				SubSystem="2"
-				OptimizeForWindows98="1"
-				ImportLibrary="$(OutDir)/zlibwapi.lib"
-				TargetMachine="5"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="x86\ZlibDll$(ConfigurationName)"
-			IntermediateDirectory="x86\ZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="2"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="NDEBUG"
-				MkTypLibCompatible="true"
-				SuppressStartupBanner="true"
-				TargetEnvironment="1"
-				TypeLibraryName="$(OutDir)/zlibvc.tlb"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;ASMV;ASMINF"
-				StringPooling="true"
-				ExceptionHandling="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
-				AssemblerOutput="2"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				BrowseInformation="0"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="..\..\masmx86\gvmat32.obj ..\..\masmx86\inffas32.obj "
-				OutputFile="$(OutDir)\zlibwapi.dll"
-				LinkIncremental="1"
-				SuppressStartupBanner="true"
-				GenerateManifest="false"
-				IgnoreAllDefaultLibraries="false"
-				ModuleDefinitionFile=".\zlibvc.def"
-				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
-				GenerateMapFile="true"
-				MapFileName="$(OutDir)/zlibwapi.map"
-				SubSystem="2"
-				OptimizeForWindows98="1"
-				ImportLibrary="$(OutDir)/zlibwapi.lib"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|x64"
-			OutputDirectory="x64\ZlibDll$(ConfigurationName)"
-			IntermediateDirectory="x64\ZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="2"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="NDEBUG"
-				MkTypLibCompatible="true"
-				SuppressStartupBanner="true"
-				TargetEnvironment="3"
-				TypeLibraryName="$(OutDir)/zlibvc.tlb"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;ASMV;ASMINF;WIN64"
-				StringPooling="true"
-				ExceptionHandling="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
-				AssemblerOutput="2"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				BrowseInformation="0"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="..\..\masmx64\gvmat64.obj ..\..\masmx64\inffasx64.obj "
-				OutputFile="$(OutDir)\zlibwapi.dll"
-				LinkIncremental="1"
-				SuppressStartupBanner="true"
-				GenerateManifest="false"
-				IgnoreAllDefaultLibraries="false"
-				ModuleDefinitionFile=".\zlibvc.def"
-				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
-				GenerateMapFile="true"
-				MapFileName="$(OutDir)/zlibwapi.map"
-				SubSystem="2"
-				OptimizeForWindows98="1"
-				ImportLibrary="$(OutDir)/zlibwapi.lib"
-				TargetMachine="17"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|Itanium"
-			OutputDirectory="ia64\ZlibDll$(ConfigurationName)"
-			IntermediateDirectory="ia64\ZlibDll$(ConfigurationName)\Tmp"
-			ConfigurationType="2"
-			InheritedPropertySheets="UpgradeFromVC70.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			WholeProgramOptimization="1"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				PreprocessorDefinitions="NDEBUG"
-				MkTypLibCompatible="true"
-				SuppressStartupBanner="true"
-				TargetEnvironment="2"
-				TypeLibraryName="$(OutDir)/zlibvc.tlb"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
-				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;WIN64"
-				StringPooling="true"
-				ExceptionHandling="0"
-				RuntimeLibrary="2"
-				BufferSecurityCheck="false"
-				EnableFunctionLevelLinking="true"
-				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
-				AssemblerOutput="2"
-				AssemblerListingLocation="$(IntDir)\"
-				ObjectFile="$(IntDir)\"
-				ProgramDataBaseFileName="$(OutDir)\"
-				BrowseInformation="0"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1036"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\zlibwapi.dll"
-				LinkIncremental="1"
-				SuppressStartupBanner="true"
-				GenerateManifest="false"
-				IgnoreAllDefaultLibraries="false"
-				ModuleDefinitionFile=".\zlibvc.def"
-				ProgramDatabaseFile="$(OutDir)/zlibwapi.pdb"
-				GenerateMapFile="true"
-				MapFileName="$(OutDir)/zlibwapi.map"
-				SubSystem="2"
-				OptimizeForWindows98="1"
-				ImportLibrary="$(OutDir)/zlibwapi.lib"
-				TargetMachine="5"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
-			>
-			<File
-				RelativePath="..\..\..\adler32.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\compress.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\crc32.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\deflate.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\masmx86\gvmat32c.c"
-				>
-				<FileConfiguration
-					Name="Debug|x64"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|x64"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|x64"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\..\gzio.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\infback.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\masmx64\inffas8664.c"
-				>
-				<FileConfiguration
-					Name="Debug|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="ReleaseWithoutAsm|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Win32"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Itanium"
-					ExcludedFromBuild="true"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\..\inffast.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\inflate.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\inftrees.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\minizip\ioapi.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\minizip\iowin32.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\trees.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\uncompr.c"
-				>
-			</File>
-			<File
-				RelativePath="..\..\minizip\unzip.c"
-				>
-				<FileConfiguration
-					Name="Release|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions="ZLIB_INTERNAL"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|x64"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions="ZLIB_INTERNAL"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Itanium"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions="ZLIB_INTERNAL"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath="..\..\minizip\zip.c"
-				>
-				<FileConfiguration
-					Name="Release|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions="ZLIB_INTERNAL"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|x64"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions="ZLIB_INTERNAL"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Itanium"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						AdditionalIncludeDirectories=""
-						PreprocessorDefinitions="ZLIB_INTERNAL"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath=".\zlib.rc"
-				>
-			</File>
-			<File
-				RelativePath=".\zlibvc.def"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\zutil.c"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;fi;fd"
-			>
-			<File
-				RelativePath="..\..\..\deflate.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\infblock.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\infcodes.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\inffast.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\inftrees.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\infutil.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\zconf.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\zlib.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\zutil.h"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
-			>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
diff --git a/third_party/zlib/crc32.c b/third_party/zlib/crc32.c
index 4d6e699..979a719 100644
--- a/third_party/zlib/crc32.c
+++ b/third_party/zlib/crc32.c
@@ -1,5 +1,5 @@
 /* crc32.c -- compute the CRC-32 of a data stream
- * Copyright (C) 1995-2005 Mark Adler
+ * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  *
  * Thanks to Rodney Brown <rbrown64 at csc.com.au> for his contribution of faster
@@ -11,14 +11,14 @@
 
 /* @(#) $Id$ */
 
-#include "zutil.h"      /* for STDC and FAR definitions */
-
 /*
   Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
   protection on the static variables used to control the first-use generation
   of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
   first call get_crc_table() to initialize the tables before allowing more than
   one thread to use crc32().
+
+  DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
  */
 
 #ifdef MAKECRCH
@@ -28,33 +28,15 @@
 #  endif /* !DYNAMIC_CRC_TABLE */
 #endif /* MAKECRCH */
 
-#define local static
+#include "zutil.h"      /* for STDC and FAR definitions */
 
-/* Find a four-byte integer type for crc32_little() and crc32_big(). */
-#ifndef NOBYFOUR
-#  ifdef STDC           /* need ANSI C limits.h to determine sizes */
-#    include <limits.h>
-#    define BYFOUR
-#    if (UINT_MAX == 0xffffffffUL)
-       typedef unsigned int u4;
-#    else
-#      if (ULONG_MAX == 0xffffffffUL)
-         typedef unsigned long u4;
-#      else
-#        if (USHRT_MAX == 0xffffffffUL)
-           typedef unsigned short u4;
-#        else
-#          undef BYFOUR     /* can't find a four-byte integer type! */
-#        endif
-#      endif
-#    endif
-#  endif /* STDC */
-#endif /* !NOBYFOUR */
+#define local static
 
 /* Definitions for doing the crc four data bytes at a time. */
+#if !defined(NOBYFOUR) && defined(Z_U4)
+#  define BYFOUR
+#endif
 #ifdef BYFOUR
-#  define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
-                (((w)&0xff00)<<8)+(((w)&0xff)<<24))
    local unsigned long crc32_little OF((unsigned long,
                         const unsigned char FAR *, unsigned));
    local unsigned long crc32_big OF((unsigned long,
@@ -68,14 +50,16 @@
 local unsigned long gf2_matrix_times OF((unsigned long *mat,
                                          unsigned long vec));
 local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
+local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
+
 
 #ifdef DYNAMIC_CRC_TABLE
 
 local volatile int crc_table_empty = 1;
-local unsigned long FAR crc_table[TBLS][256];
+local z_crc_t FAR crc_table[TBLS][256];
 local void make_crc_table OF((void));
 #ifdef MAKECRCH
-   local void write_table OF((FILE *, const unsigned long FAR *));
+   local void write_table OF((FILE *, const z_crc_t FAR *));
 #endif /* MAKECRCH */
 /*
   Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
@@ -105,9 +89,9 @@ local void make_crc_table OF((void));
 */
 local void make_crc_table()
 {
-    unsigned long c;
+    z_crc_t c;
     int n, k;
-    unsigned long poly;                 /* polynomial exclusive-or pattern */
+    z_crc_t poly;                       /* polynomial exclusive-or pattern */
     /* terms of polynomial defining this crc (except x^32): */
     static volatile int first = 1;      /* flag to limit concurrent making */
     static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
@@ -119,13 +103,13 @@ local void make_crc_table()
         first = 0;
 
         /* make exclusive-or pattern from polynomial (0xedb88320UL) */
-        poly = 0UL;
-        for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
-            poly |= 1UL << (31 - p[n]);
+        poly = 0;
+        for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
+            poly |= (z_crc_t)1 << (31 - p[n]);
 
         /* generate a crc for every 8-bit value */
         for (n = 0; n < 256; n++) {
-            c = (unsigned long)n;
+            c = (z_crc_t)n;
             for (k = 0; k < 8; k++)
                 c = c & 1 ? poly ^ (c >> 1) : c >> 1;
             crc_table[0][n] = c;
@@ -136,11 +120,11 @@ local void make_crc_table()
            and then the byte reversal of those as well as the first table */
         for (n = 0; n < 256; n++) {
             c = crc_table[0][n];
-            crc_table[4][n] = REV(c);
+            crc_table[4][n] = ZSWAP32(c);
             for (k = 1; k < 4; k++) {
                 c = crc_table[0][c & 0xff] ^ (c >> 8);
                 crc_table[k][n] = c;
-                crc_table[k + 4][n] = REV(c);
+                crc_table[k + 4][n] = ZSWAP32(c);
             }
         }
 #endif /* BYFOUR */
@@ -162,7 +146,7 @@ local void make_crc_table()
         if (out == NULL) return;
         fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
         fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
-        fprintf(out, "local const unsigned long FAR ");
+        fprintf(out, "local const z_crc_t FAR ");
         fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
         write_table(out, crc_table[0]);
 #  ifdef BYFOUR
@@ -182,12 +166,13 @@ local void make_crc_table()
 #ifdef MAKECRCH
 local void write_table(out, table)
     FILE *out;
-    const unsigned long FAR *table;
+    const z_crc_t FAR *table;
 {
     int n;
 
     for (n = 0; n < 256; n++)
-        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ", table[n],
+        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ",
+                (unsigned long)(table[n]),
                 n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
 }
 #endif /* MAKECRCH */
@@ -202,13 +187,13 @@ local void write_table(out, table)
 /* =========================================================================
  * This function can be used by asm versions of crc32()
  */
-const unsigned long FAR * ZEXPORT get_crc_table()
+const z_crc_t FAR * ZEXPORT get_crc_table()
 {
 #ifdef DYNAMIC_CRC_TABLE
     if (crc_table_empty)
         make_crc_table();
 #endif /* DYNAMIC_CRC_TABLE */
-    return (const unsigned long FAR *)crc_table;
+    return (const z_crc_t FAR *)crc_table;
 }
 
 /* ========================================================================= */
@@ -219,7 +204,7 @@ const unsigned long FAR * ZEXPORT get_crc_table()
 unsigned long ZEXPORT crc32(crc, buf, len)
     unsigned long crc;
     const unsigned char FAR *buf;
-    unsigned len;
+    uInt len;
 {
     if (buf == Z_NULL) return 0UL;
 
@@ -230,7 +215,7 @@ unsigned long ZEXPORT crc32(crc, buf, len)
 
 #ifdef BYFOUR
     if (sizeof(void *) == sizeof(ptrdiff_t)) {
-        u4 endian;
+        z_crc_t endian;
 
         endian = 1;
         if (*((unsigned char *)(&endian)))
@@ -264,17 +249,17 @@ local unsigned long crc32_little(crc, buf, len)
     const unsigned char FAR *buf;
     unsigned len;
 {
-    register u4 c;
-    register const u4 FAR *buf4;
+    register z_crc_t c;
+    register const z_crc_t FAR *buf4;
 
-    c = (u4)crc;
+    c = (z_crc_t)crc;
     c = ~c;
     while (len && ((ptrdiff_t)buf & 3)) {
         c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
         len--;
     }
 
-    buf4 = (const u4 FAR *)(const void FAR *)buf;
+    buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
     while (len >= 32) {
         DOLIT32;
         len -= 32;
@@ -304,17 +289,17 @@ local unsigned long crc32_big(crc, buf, len)
     const unsigned char FAR *buf;
     unsigned len;
 {
-    register u4 c;
-    register const u4 FAR *buf4;
+    register z_crc_t c;
+    register const z_crc_t FAR *buf4;
 
-    c = REV((u4)crc);
+    c = ZSWAP32((z_crc_t)crc);
     c = ~c;
     while (len && ((ptrdiff_t)buf & 3)) {
         c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
         len--;
     }
 
-    buf4 = (const u4 FAR *)(const void FAR *)buf;
+    buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
     buf4--;
     while (len >= 32) {
         DOBIG32;
@@ -331,7 +316,7 @@ local unsigned long crc32_big(crc, buf, len)
         c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
     } while (--len);
     c = ~c;
-    return (unsigned long)(REV(c));
+    return (unsigned long)(ZSWAP32(c));
 }
 
 #endif /* BYFOUR */
@@ -367,22 +352,22 @@ local void gf2_matrix_square(square, mat)
 }
 
 /* ========================================================================= */
-uLong ZEXPORT crc32_combine(crc1, crc2, len2)
+local uLong crc32_combine_(crc1, crc2, len2)
     uLong crc1;
     uLong crc2;
-    z_off_t len2;
+    z_off64_t len2;
 {
     int n;
     unsigned long row;
     unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
     unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */
 
-    /* degenerate case */
-    if (len2 == 0)
+    /* degenerate case (also disallow negative lengths) */
+    if (len2 <= 0)
         return crc1;
 
     /* put operator for one zero bit in odd */
-    odd[0] = 0xedb88320L;           /* CRC-32 polynomial */
+    odd[0] = 0xedb88320UL;          /* CRC-32 polynomial */
     row = 1;
     for (n = 1; n < GF2_DIM; n++) {
         odd[n] = row;
@@ -421,3 +406,20 @@ uLong ZEXPORT crc32_combine(crc1, crc2, len2)
     crc1 ^= crc2;
     return crc1;
 }
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(crc1, crc2, len2)
+    uLong crc1;
+    uLong crc2;
+    z_off_t len2;
+{
+    return crc32_combine_(crc1, crc2, len2);
+}
+
+uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
+    uLong crc1;
+    uLong crc2;
+    z_off64_t len2;
+{
+    return crc32_combine_(crc1, crc2, len2);
+}
diff --git a/third_party/zlib/crc32.h b/third_party/zlib/crc32.h
index 8053b61..9e0c778 100644
--- a/third_party/zlib/crc32.h
+++ b/third_party/zlib/crc32.h
@@ -2,7 +2,7 @@
  * Generated automatically by crc32.c
  */
 
-local const unsigned long FAR crc_table[TBLS][256] =
+local const z_crc_t FAR crc_table[TBLS][256] =
 {
   {
     0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
diff --git a/third_party/zlib/deflate.c b/third_party/zlib/deflate.c
index 2720aab..6969577 100644
--- a/third_party/zlib/deflate.c
+++ b/third_party/zlib/deflate.c
@@ -1,5 +1,5 @@
 /* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -37,7 +37,7 @@
  *  REFERENCES
  *
  *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
- *      Available in http://www.ietf.org/rfc/rfc1951.txt
+ *      Available in http://tools.ietf.org/html/rfc1951
  *
  *      A description of the Rabin and Karp algorithm is given in the book
  *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
@@ -52,7 +52,7 @@
 #include "deflate.h"
 
 const char deflate_copyright[] =
-   " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly ";
+   " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -79,19 +79,18 @@ local block_state deflate_fast   OF((deflate_state *s, int flush));
 #ifndef FASTEST
 local block_state deflate_slow   OF((deflate_state *s, int flush));
 #endif
+local block_state deflate_rle    OF((deflate_state *s, int flush));
+local block_state deflate_huff   OF((deflate_state *s, int flush));
 local void lm_init        OF((deflate_state *s));
 local void putShortMSB    OF((deflate_state *s, uInt b));
 local void flush_pending  OF((z_streamp strm));
 local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
-#ifndef FASTEST
 #ifdef ASMV
       void match_init OF((void)); /* asm code initialization */
       uInt longest_match  OF((deflate_state *s, IPos cur_match));
 #else
 local uInt longest_match  OF((deflate_state *s, IPos cur_match));
 #endif
-#endif
-local uInt longest_match_fast OF((deflate_state *s, IPos cur_match));
 
 #ifdef DEBUG
 local  void check_match OF((deflate_state *s, IPos start, IPos match,
@@ -110,11 +109,6 @@ local  void check_match OF((deflate_state *s, IPos start, IPos match,
 #endif
 /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
 
-#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
-/* Minimum amount of lookahead, except at the end of the input file.
- * See deflate.c for comments about the MIN_MATCH+1.
- */
-
 /* Values for max_lazy_match, good_match and max_chain_length, depending on
  * the desired pack level (0..9). The values given below have been tuned to
  * exclude worst case performance for pathological files. Better values may be
@@ -154,10 +148,16 @@ local const config configuration_table[10] = {
  * meaning.
  */
 
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
 #ifndef NO_DUMMY_DECL
 struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
 #endif
 
+/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */
+#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0))
+
 /* ===========================================================================
  * Update a hash value with the given input byte
  * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
@@ -238,10 +238,19 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
 
     strm->msg = Z_NULL;
     if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
         strm->zalloc = zcalloc;
         strm->opaque = (voidpf)0;
+#endif
     }
-    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zfree = zcfree;
+#endif
 
 #ifdef FASTEST
     if (level != 0) level = 1;
@@ -285,6 +294,8 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
     s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
     s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
 
+    s->high_water = 0;      /* nothing written to s->window yet */
+
     s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
 
     overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
@@ -315,43 +326,70 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
     uInt  dictLength;
 {
     deflate_state *s;
-    uInt length = dictLength;
-    uInt n;
-    IPos hash_head = 0;
+    uInt str, n;
+    int wrap;
+    unsigned avail;
+    z_const unsigned char *next;
 
-    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
-        strm->state->wrap == 2 ||
-        (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
+    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL)
         return Z_STREAM_ERROR;
-
     s = strm->state;
-    if (s->wrap)
-        strm->adler = adler32(strm->adler, dictionary, dictLength);
+    wrap = s->wrap;
+    if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)
+        return Z_STREAM_ERROR;
 
-    if (length < MIN_MATCH) return Z_OK;
-    if (length > MAX_DIST(s)) {
-        length = MAX_DIST(s);
-        dictionary += dictLength - length; /* use the tail of the dictionary */
+    /* when using zlib wrappers, compute Adler-32 for provided dictionary */
+    if (wrap == 1)
+        strm->adler = adler32(strm->adler, dictionary, dictLength);
+    s->wrap = 0;                    /* avoid computing Adler-32 in read_buf */
+
+    /* if dictionary would fill window, just replace the history */
+    if (dictLength >= s->w_size) {
+        if (wrap == 0) {            /* already empty otherwise */
+            CLEAR_HASH(s);
+            s->strstart = 0;
+            s->block_start = 0L;
+            s->insert = 0;
+        }
+        dictionary += dictLength - s->w_size;  /* use the tail */
+        dictLength = s->w_size;
     }
-    zmemcpy(s->window, dictionary, length);
-    s->strstart = length;
-    s->block_start = (long)length;
 
-    /* Insert all strings in the hash table (except for the last two bytes).
-     * s->lookahead stays null, so s->ins_h will be recomputed at the next
-     * call of fill_window.
-     */
-    s->ins_h = s->window[0];
-    UPDATE_HASH(s, s->ins_h, s->window[1]);
-    for (n = 0; n <= length - MIN_MATCH; n++) {
-        INSERT_STRING(s, n, hash_head);
+    /* insert dictionary into window and hash */
+    avail = strm->avail_in;
+    next = strm->next_in;
+    strm->avail_in = dictLength;
+    strm->next_in = (z_const Bytef *)dictionary;
+    fill_window(s);
+    while (s->lookahead >= MIN_MATCH) {
+        str = s->strstart;
+        n = s->lookahead - (MIN_MATCH-1);
+        do {
+            UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+#ifndef FASTEST
+            s->prev[str & s->w_mask] = s->head[s->ins_h];
+#endif
+            s->head[s->ins_h] = (Pos)str;
+            str++;
+        } while (--n);
+        s->strstart = str;
+        s->lookahead = MIN_MATCH-1;
+        fill_window(s);
     }
-    if (hash_head) hash_head = 0;  /* to make compiler happy */
+    s->strstart += s->lookahead;
+    s->block_start = (long)s->strstart;
+    s->insert = s->lookahead;
+    s->lookahead = 0;
+    s->match_length = s->prev_length = MIN_MATCH-1;
+    s->match_available = 0;
+    strm->next_in = next;
+    strm->avail_in = avail;
+    s->wrap = wrap;
     return Z_OK;
 }
 
 /* ========================================================================= */
-int ZEXPORT deflateReset (strm)
+int ZEXPORT deflateResetKeep (strm)
     z_streamp strm;
 {
     deflate_state *s;
@@ -381,12 +419,23 @@ int ZEXPORT deflateReset (strm)
     s->last_flush = Z_NO_FLUSH;
 
     _tr_init(s);
-    lm_init(s);
 
     return Z_OK;
 }
 
 /* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+    z_streamp strm;
+{
+    int ret;
+
+    ret = deflateResetKeep(strm);
+    if (ret == Z_OK)
+        lm_init(strm->state);
+    return ret;
+}
+
+/* ========================================================================= */
 int ZEXPORT deflateSetHeader (strm, head)
     z_streamp strm;
     gz_headerp head;
@@ -398,14 +447,42 @@ int ZEXPORT deflateSetHeader (strm, head)
 }
 
 /* ========================================================================= */
+int ZEXPORT deflatePending (strm, pending, bits)
+    unsigned *pending;
+    int *bits;
+    z_streamp strm;
+{
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    if (pending != Z_NULL)
+        *pending = strm->state->pending;
+    if (bits != Z_NULL)
+        *bits = strm->state->bi_valid;
+    return Z_OK;
+}
+
+/* ========================================================================= */
 int ZEXPORT deflatePrime (strm, bits, value)
     z_streamp strm;
     int bits;
     int value;
 {
+    deflate_state *s;
+    int put;
+
     if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    strm->state->bi_valid = bits;
-    strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
+    s = strm->state;
+    if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
+        return Z_BUF_ERROR;
+    do {
+        put = Buf_size - s->bi_valid;
+        if (put > bits)
+            put = bits;
+        s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
+        s->bi_valid += put;
+        _tr_flush_bits(s);
+        value >>= put;
+        bits -= put;
+    } while (bits);
     return Z_OK;
 }
 
@@ -432,9 +509,12 @@ int ZEXPORT deflateParams(strm, level, strategy)
     }
     func = configuration_table[s->level].func;
 
-    if (func != configuration_table[level].func && strm->total_in != 0) {
+    if ((strategy != s->strategy || func != configuration_table[level].func) &&
+        strm->total_in != 0) {
         /* Flush the last buffer: */
-        err = deflate(strm, Z_PARTIAL_FLUSH);
+        err = deflate(strm, Z_BLOCK);
+        if (err == Z_BUF_ERROR && s->pending == 0)
+            err = Z_OK;
     }
     if (s->level != level) {
         s->level = level;
@@ -478,33 +558,66 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
  * resulting from using fixed blocks instead of stored blocks, which deflate
  * can emit on compressed data for some combinations of the parameters.
  *
- * This function could be more sophisticated to provide closer upper bounds
- * for every combination of windowBits and memLevel, as well as wrap.
- * But even the conservative upper bound of about 14% expansion does not
- * seem onerous for output buffer allocation.
+ * This function could be more sophisticated to provide closer upper bounds for
+ * every combination of windowBits and memLevel.  But even the conservative
+ * upper bound of about 14% expansion does not seem onerous for output buffer
+ * allocation.
  */
 uLong ZEXPORT deflateBound(strm, sourceLen)
     z_streamp strm;
     uLong sourceLen;
 {
     deflate_state *s;
-    uLong destLen;
+    uLong complen, wraplen;
+    Bytef *str;
 
-    /* conservative upper bound */
-    destLen = sourceLen +
-              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11;
+    /* conservative upper bound for compressed data */
+    complen = sourceLen +
+              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
 
-    /* if can't get parameters, return conservative bound */
+    /* if can't get parameters, return conservative bound plus zlib wrapper */
     if (strm == Z_NULL || strm->state == Z_NULL)
-        return destLen;
+        return complen + 6;
 
-    /* if not default parameters, return conservative bound */
+    /* compute wrapper length */
     s = strm->state;
+    switch (s->wrap) {
+    case 0:                                 /* raw deflate */
+        wraplen = 0;
+        break;
+    case 1:                                 /* zlib wrapper */
+        wraplen = 6 + (s->strstart ? 4 : 0);
+        break;
+    case 2:                                 /* gzip wrapper */
+        wraplen = 18;
+        if (s->gzhead != Z_NULL) {          /* user-supplied gzip header */
+            if (s->gzhead->extra != Z_NULL)
+                wraplen += 2 + s->gzhead->extra_len;
+            str = s->gzhead->name;
+            if (str != Z_NULL)
+                do {
+                    wraplen++;
+                } while (*str++);
+            str = s->gzhead->comment;
+            if (str != Z_NULL)
+                do {
+                    wraplen++;
+                } while (*str++);
+            if (s->gzhead->hcrc)
+                wraplen += 2;
+        }
+        break;
+    default:                                /* for compiler happiness */
+        wraplen = 6;
+    }
+
+    /* if not default parameters, return conservative bound */
     if (s->w_bits != 15 || s->hash_bits != 8 + 7)
-        return destLen;
+        return complen + wraplen;
 
     /* default settings: return tight bound for that case */
-    return compressBound(sourceLen);
+    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+           (sourceLen >> 25) + 13 - 6 + wraplen;
 }
 
 /* =========================================================================
@@ -529,19 +642,22 @@ local void putShortMSB (s, b)
 local void flush_pending(strm)
     z_streamp strm;
 {
-    unsigned len = strm->state->pending;
+    unsigned len;
+    deflate_state *s = strm->state;
 
+    _tr_flush_bits(s);
+    len = s->pending;
     if (len > strm->avail_out) len = strm->avail_out;
     if (len == 0) return;
 
-    zmemcpy(strm->next_out, strm->state->pending_out, len);
+    zmemcpy(strm->next_out, s->pending_out, len);
     strm->next_out  += len;
-    strm->state->pending_out  += len;
+    s->pending_out  += len;
     strm->total_out += len;
     strm->avail_out  -= len;
-    strm->state->pending -= len;
-    if (strm->state->pending == 0) {
-        strm->state->pending_out = strm->state->pending_buf;
+    s->pending -= len;
+    if (s->pending == 0) {
+        s->pending_out = s->pending_buf;
     }
 }
 
@@ -554,7 +670,7 @@ int ZEXPORT deflate (strm, flush)
     deflate_state *s;
 
     if (strm == Z_NULL || strm->state == Z_NULL ||
-        flush > Z_FINISH || flush < 0) {
+        flush > Z_BLOCK || flush < 0) {
         return Z_STREAM_ERROR;
     }
     s = strm->state;
@@ -578,7 +694,7 @@ int ZEXPORT deflate (strm, flush)
             put_byte(s, 31);
             put_byte(s, 139);
             put_byte(s, 8);
-            if (s->gzhead == NULL) {
+            if (s->gzhead == Z_NULL) {
                 put_byte(s, 0);
                 put_byte(s, 0);
                 put_byte(s, 0);
@@ -605,7 +721,7 @@ int ZEXPORT deflate (strm, flush)
                             (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
                              4 : 0));
                 put_byte(s, s->gzhead->os & 0xff);
-                if (s->gzhead->extra != NULL) {
+                if (s->gzhead->extra != Z_NULL) {
                     put_byte(s, s->gzhead->extra_len & 0xff);
                     put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
                 }
@@ -647,7 +763,7 @@ int ZEXPORT deflate (strm, flush)
     }
 #ifdef GZIP
     if (s->status == EXTRA_STATE) {
-        if (s->gzhead->extra != NULL) {
+        if (s->gzhead->extra != Z_NULL) {
             uInt beg = s->pending;  /* start of bytes to update crc */
 
             while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
@@ -675,7 +791,7 @@ int ZEXPORT deflate (strm, flush)
             s->status = NAME_STATE;
     }
     if (s->status == NAME_STATE) {
-        if (s->gzhead->name != NULL) {
+        if (s->gzhead->name != Z_NULL) {
             uInt beg = s->pending;  /* start of bytes to update crc */
             int val;
 
@@ -706,7 +822,7 @@ int ZEXPORT deflate (strm, flush)
             s->status = COMMENT_STATE;
     }
     if (s->status == COMMENT_STATE) {
-        if (s->gzhead->comment != NULL) {
+        if (s->gzhead->comment != Z_NULL) {
             uInt beg = s->pending;  /* start of bytes to update crc */
             int val;
 
@@ -768,7 +884,7 @@ int ZEXPORT deflate (strm, flush)
      * flushes. For repeated and useless calls with Z_FINISH, we keep
      * returning Z_STREAM_END instead of Z_BUF_ERROR.
      */
-    } else if (strm->avail_in == 0 && flush <= old_flush &&
+    } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&
                flush != Z_FINISH) {
         ERR_RETURN(strm, Z_BUF_ERROR);
     }
@@ -784,7 +900,9 @@ int ZEXPORT deflate (strm, flush)
         (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
         block_state bstate;
 
-        bstate = (*(configuration_table[s->level].func))(s, flush);
+        bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
+                    (s->strategy == Z_RLE ? deflate_rle(s, flush) :
+                        (*(configuration_table[s->level].func))(s, flush));
 
         if (bstate == finish_started || bstate == finish_done) {
             s->status = FINISH_STATE;
@@ -805,13 +923,18 @@ int ZEXPORT deflate (strm, flush)
         if (bstate == block_done) {
             if (flush == Z_PARTIAL_FLUSH) {
                 _tr_align(s);
-            } else { /* FULL_FLUSH or SYNC_FLUSH */
+            } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
                 _tr_stored_block(s, (char*)0, 0L, 0);
                 /* For a full flush, this empty block will be recognized
                  * as a special marker by inflate_sync().
                  */
                 if (flush == Z_FULL_FLUSH) {
                     CLEAR_HASH(s);             /* forget history */
+                    if (s->lookahead == 0) {
+                        s->strstart = 0;
+                        s->block_start = 0L;
+                        s->insert = 0;
+                    }
                 }
             }
             flush_pending(strm);
@@ -906,12 +1029,12 @@ int ZEXPORT deflateCopy (dest, source)
 
     ss = source->state;
 
-    zmemcpy(dest, source, sizeof(z_stream));
+    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
 
     ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
     if (ds == Z_NULL) return Z_MEM_ERROR;
     dest->state = (struct internal_state FAR *) ds;
-    zmemcpy(ds, ss, sizeof(deflate_state));
+    zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
     ds->strm = dest;
 
     ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
@@ -927,8 +1050,8 @@ int ZEXPORT deflateCopy (dest, source)
     }
     /* following zmemcpy do not work for 16-bit MSDOS */
     zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
-    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
-    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+    zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
+    zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
     zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
 
     ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
@@ -962,15 +1085,15 @@ local int read_buf(strm, buf, size)
 
     strm->avail_in  -= len;
 
+    zmemcpy(buf, strm->next_in, len);
     if (strm->state->wrap == 1) {
-        strm->adler = adler32(strm->adler, strm->next_in, len);
+        strm->adler = adler32(strm->adler, buf, len);
     }
 #ifdef GZIP
     else if (strm->state->wrap == 2) {
-        strm->adler = crc32(strm->adler, strm->next_in, len);
+        strm->adler = crc32(strm->adler, buf, len);
     }
 #endif
-    zmemcpy(buf, strm->next_in, len);
     strm->next_in  += len;
     strm->total_in += len;
 
@@ -997,6 +1120,7 @@ local void lm_init (s)
     s->strstart = 0;
     s->block_start = 0L;
     s->lookahead = 0;
+    s->insert = 0;
     s->match_length = s->prev_length = MIN_MATCH-1;
     s->match_available = 0;
     s->ins_h = 0;
@@ -1164,12 +1288,13 @@ local uInt longest_match(s, cur_match)
     return s->lookahead;
 }
 #endif /* ASMV */
-#endif /* FASTEST */
+
+#else /* FASTEST */
 
 /* ---------------------------------------------------------------------------
- * Optimized version for level == 1 or strategy == Z_RLE only
+ * Optimized version for FASTEST only
  */
-local uInt longest_match_fast(s, cur_match)
+local uInt longest_match(s, cur_match)
     deflate_state *s;
     IPos cur_match;                             /* current match */
 {
@@ -1222,10 +1347,9 @@ local uInt longest_match_fast(s, cur_match)
     return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
 }
 
-#ifdef DEBUG
-#define EQUAL 0
-/* result of memcmp for equal strings */
+#endif /* FASTEST */
 
+#ifdef DEBUG
 /* ===========================================================================
  * Check that the match at match_start is indeed a match.
  */
@@ -1271,6 +1395,8 @@ local void fill_window(s)
     unsigned more;    /* Amount of free space at the end of the window. */
     uInt wsize = s->w_size;
 
+    Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
+
     do {
         more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
 
@@ -1303,7 +1429,6 @@ local void fill_window(s)
                later. (Using level 0 permanently is not an optimal usage of
                zlib, so we don't care about this pathological case.)
              */
-            /* %%% avoid this when Z_RLE */
             n = s->hash_size;
             p = &s->head[n];
             do {
@@ -1324,7 +1449,7 @@ local void fill_window(s)
 #endif
             more += wsize;
         }
-        if (s->strm->avail_in == 0) return;
+        if (s->strm->avail_in == 0) break;
 
         /* If there was no sliding:
          *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
@@ -1343,39 +1468,88 @@ local void fill_window(s)
         s->lookahead += n;
 
         /* Initialize the hash value now that we have some input: */
-        if (s->lookahead >= MIN_MATCH) {
-            s->ins_h = s->window[s->strstart];
-            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+        if (s->lookahead + s->insert >= MIN_MATCH) {
+            uInt str = s->strstart - s->insert;
+            s->ins_h = s->window[str];
+            UPDATE_HASH(s, s->ins_h, s->window[str + 1]);
 #if MIN_MATCH != 3
             Call UPDATE_HASH() MIN_MATCH-3 more times
 #endif
+            while (s->insert) {
+                UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+#ifndef FASTEST
+                s->prev[str & s->w_mask] = s->head[s->ins_h];
+#endif
+                s->head[s->ins_h] = (Pos)str;
+                str++;
+                s->insert--;
+                if (s->lookahead + s->insert < MIN_MATCH)
+                    break;
+            }
         }
         /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
          * but this is not important since only literal bytes will be emitted.
          */
 
     } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+
+    /* If the WIN_INIT bytes after the end of the current data have never been
+     * written, then zero those bytes in order to avoid memory check reports of
+     * the use of uninitialized (or uninitialised as Julian writes) bytes by
+     * the longest match routines.  Update the high water mark for the next
+     * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
+     * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
+     */
+    if (s->high_water < s->window_size) {
+        ulg curr = s->strstart + (ulg)(s->lookahead);
+        ulg init;
+
+        if (s->high_water < curr) {
+            /* Previous high water mark below current data -- zero WIN_INIT
+             * bytes or up to end of window, whichever is less.
+             */
+            init = s->window_size - curr;
+            if (init > WIN_INIT)
+                init = WIN_INIT;
+            zmemzero(s->window + curr, (unsigned)init);
+            s->high_water = curr + init;
+        }
+        else if (s->high_water < (ulg)curr + WIN_INIT) {
+            /* High water mark at or above current data, but below current data
+             * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
+             * to end of window, whichever is less.
+             */
+            init = (ulg)curr + WIN_INIT - s->high_water;
+            if (init > s->window_size - s->high_water)
+                init = s->window_size - s->high_water;
+            zmemzero(s->window + s->high_water, (unsigned)init);
+            s->high_water += init;
+        }
+    }
+
+    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+           "not enough room for search");
 }
 
 /* ===========================================================================
  * Flush the current block, with given end-of-file flag.
  * IN assertion: strstart is set to the end of the current match.
  */
-#define FLUSH_BLOCK_ONLY(s, eof) { \
+#define FLUSH_BLOCK_ONLY(s, last) { \
    _tr_flush_block(s, (s->block_start >= 0L ? \
                    (charf *)&s->window[(unsigned)s->block_start] : \
                    (charf *)Z_NULL), \
                 (ulg)((long)s->strstart - s->block_start), \
-                (eof)); \
+                (last)); \
    s->block_start = s->strstart; \
    flush_pending(s->strm); \
    Tracev((stderr,"[FLUSH]")); \
 }
 
 /* Same but force premature exit if necessary. */
-#define FLUSH_BLOCK(s, eof) { \
-   FLUSH_BLOCK_ONLY(s, eof); \
-   if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+#define FLUSH_BLOCK(s, last) { \
+   FLUSH_BLOCK_ONLY(s, last); \
+   if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
 }
 
 /* ===========================================================================
@@ -1434,8 +1608,14 @@ local block_state deflate_stored(s, flush)
             FLUSH_BLOCK(s, 0);
         }
     }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
+    s->insert = 0;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if ((long)s->strstart > s->block_start)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
 }
 
 /* ===========================================================================
@@ -1449,7 +1629,7 @@ local block_state deflate_fast(s, flush)
     deflate_state *s;
     int flush;
 {
-    IPos hash_head = NIL; /* head of the hash chain */
+    IPos hash_head;       /* head of the hash chain */
     int bflush;           /* set if current block must be flushed */
 
     for (;;) {
@@ -1469,6 +1649,7 @@ local block_state deflate_fast(s, flush)
         /* Insert the string window[strstart .. strstart+2] in the
          * dictionary, and set hash_head to the head of the hash chain:
          */
+        hash_head = NIL;
         if (s->lookahead >= MIN_MATCH) {
             INSERT_STRING(s, s->strstart, hash_head);
         }
@@ -1481,19 +1662,8 @@ local block_state deflate_fast(s, flush)
              * of window index 0 (in particular we have to avoid a match
              * of the string with itself at the start of the input file).
              */
-#ifdef FASTEST
-            if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) ||
-                (s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
-                s->match_length = longest_match_fast (s, hash_head);
-            }
-#else
-            if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
-                s->match_length = longest_match (s, hash_head);
-            } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
-                s->match_length = longest_match_fast (s, hash_head);
-            }
-#endif
-            /* longest_match() or longest_match_fast() sets match_start */
+            s->match_length = longest_match (s, hash_head);
+            /* longest_match() sets match_start */
         }
         if (s->match_length >= MIN_MATCH) {
             check_match(s, s->strstart, s->match_start, s->match_length);
@@ -1541,8 +1711,14 @@ local block_state deflate_fast(s, flush)
         }
         if (bflush) FLUSH_BLOCK(s, 0);
     }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
+    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if (s->last_lit)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
 }
 
 #ifndef FASTEST
@@ -1555,7 +1731,7 @@ local block_state deflate_slow(s, flush)
     deflate_state *s;
     int flush;
 {
-    IPos hash_head = NIL;    /* head of hash chain */
+    IPos hash_head;          /* head of hash chain */
     int bflush;              /* set if current block must be flushed */
 
     /* Process the input block. */
@@ -1576,6 +1752,7 @@ local block_state deflate_slow(s, flush)
         /* Insert the string window[strstart .. strstart+2] in the
          * dictionary, and set hash_head to the head of the hash chain:
          */
+        hash_head = NIL;
         if (s->lookahead >= MIN_MATCH) {
             INSERT_STRING(s, s->strstart, hash_head);
         }
@@ -1591,12 +1768,8 @@ local block_state deflate_slow(s, flush)
              * of window index 0 (in particular we have to avoid a match
              * of the string with itself at the start of the input file).
              */
-            if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
-                s->match_length = longest_match (s, hash_head);
-            } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
-                s->match_length = longest_match_fast (s, hash_head);
-            }
-            /* longest_match() or longest_match_fast() sets match_start */
+            s->match_length = longest_match (s, hash_head);
+            /* longest_match() sets match_start */
 
             if (s->match_length <= 5 && (s->strategy == Z_FILTERED
 #if TOO_FAR <= 32767
@@ -1669,12 +1842,17 @@ local block_state deflate_slow(s, flush)
         _tr_tally_lit(s, s->window[s->strstart-1], bflush);
         s->match_available = 0;
     }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
+    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if (s->last_lit)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
 }
 #endif /* FASTEST */
 
-#if 0
 /* ===========================================================================
  * For Z_RLE, simply look for runs of bytes, generate matches only of distance
  * one.  Do not maintain a hash table.  (It will be regenerated if this run of
@@ -1684,43 +1862,52 @@ local block_state deflate_rle(s, flush)
     deflate_state *s;
     int flush;
 {
-    int bflush;         /* set if current block must be flushed */
-    uInt run;           /* length of run */
-    uInt max;           /* maximum length of run */
-    uInt prev;          /* byte at distance one to match */
-    Bytef *scan;        /* scan for end of run */
+    int bflush;             /* set if current block must be flushed */
+    uInt prev;              /* byte at distance one to match */
+    Bytef *scan, *strend;   /* scan goes up to strend for length of run */
 
     for (;;) {
         /* Make sure that we always have enough lookahead, except
          * at the end of the input file. We need MAX_MATCH bytes
-         * for the longest encodable run.
+         * for the longest run, plus one for the unrolled loop.
          */
-        if (s->lookahead < MAX_MATCH) {
+        if (s->lookahead <= MAX_MATCH) {
             fill_window(s);
-            if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
+            if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {
                 return need_more;
             }
             if (s->lookahead == 0) break; /* flush the current block */
         }
 
         /* See how many times the previous byte repeats */
-        run = 0;
-        if (s->strstart > 0) {      /* if there is a previous byte, that is */
-            max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH;
+        s->match_length = 0;
+        if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
             scan = s->window + s->strstart - 1;
-            prev = *scan++;
-            do {
-                if (*scan++ != prev)
-                    break;
-            } while (++run < max);
+            prev = *scan;
+            if (prev == *++scan && prev == *++scan && prev == *++scan) {
+                strend = s->window + s->strstart + MAX_MATCH;
+                do {
+                } while (prev == *++scan && prev == *++scan &&
+                         prev == *++scan && prev == *++scan &&
+                         prev == *++scan && prev == *++scan &&
+                         prev == *++scan && prev == *++scan &&
+                         scan < strend);
+                s->match_length = MAX_MATCH - (int)(strend - scan);
+                if (s->match_length > s->lookahead)
+                    s->match_length = s->lookahead;
+            }
+            Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
         }
 
         /* Emit match if have run of MIN_MATCH or longer, else emit literal */
-        if (run >= MIN_MATCH) {
-            check_match(s, s->strstart, s->strstart - 1, run);
-            _tr_tally_dist(s, 1, run - MIN_MATCH, bflush);
-            s->lookahead -= run;
-            s->strstart += run;
+        if (s->match_length >= MIN_MATCH) {
+            check_match(s, s->strstart, s->strstart - 1, s->match_length);
+
+            _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
+
+            s->lookahead -= s->match_length;
+            s->strstart += s->match_length;
+            s->match_length = 0;
         } else {
             /* No match, output a literal byte */
             Tracevv((stderr,"%c", s->window[s->strstart]));
@@ -1730,7 +1917,51 @@ local block_state deflate_rle(s, flush)
         }
         if (bflush) FLUSH_BLOCK(s, 0);
     }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
+    s->insert = 0;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if (s->last_lit)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
+}
+
+/* ===========================================================================
+ * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
+ * (It will be regenerated if this run of deflate switches away from Huffman.)
+ */
+local block_state deflate_huff(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    int bflush;             /* set if current block must be flushed */
+
+    for (;;) {
+        /* Make sure that we have a literal to write. */
+        if (s->lookahead == 0) {
+            fill_window(s);
+            if (s->lookahead == 0) {
+                if (flush == Z_NO_FLUSH)
+                    return need_more;
+                break;      /* flush the current block */
+            }
+        }
+
+        /* Output a literal byte */
+        s->match_length = 0;
+        Tracevv((stderr,"%c", s->window[s->strstart]));
+        _tr_tally_lit (s, s->window[s->strstart], bflush);
+        s->lookahead--;
+        s->strstart++;
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    s->insert = 0;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if (s->last_lit)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
 }
-#endif
diff --git a/third_party/zlib/deflate.h b/third_party/zlib/deflate.h
index b16f7a7..ce0299e 100644
--- a/third_party/zlib/deflate.h
+++ b/third_party/zlib/deflate.h
@@ -1,5 +1,5 @@
 /* deflate.h -- internal compression state
- * Copyright (C) 1995-2004 Jean-loup Gailly
+ * Copyright (C) 1995-2012 Jean-loup Gailly
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -48,6 +48,9 @@
 #define MAX_BITS 15
 /* All codes must not exceed MAX_BITS bits */
 
+#define Buf_size 16
+/* size of bit buffer in bi_buf */
+
 #define INIT_STATE    42
 #define EXTRA_STATE   69
 #define NAME_STATE    73
@@ -101,7 +104,7 @@ typedef struct internal_state {
     int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */
     gz_headerp  gzhead;  /* gzip header information to write */
     uInt   gzindex;      /* where in extra, name, or comment */
-    Byte  method;        /* STORED (for zip only) or DEFLATED */
+    Byte  method;        /* can only be DEFLATED */
     int   last_flush;    /* value of flush param for previous deflate call */
 
                 /* used by deflate.c: */
@@ -244,7 +247,7 @@ typedef struct internal_state {
     ulg opt_len;        /* bit length of current block with optimal trees */
     ulg static_len;     /* bit length of current block with static trees */
     uInt matches;       /* number of string matches in current block */
-    int last_eob_len;   /* bit length of EOB code for last block */
+    uInt insert;        /* bytes at end of window left to insert */
 
 #ifdef DEBUG
     ulg compressed_len; /* total bit length of compressed file mod 2^32 */
@@ -260,6 +263,13 @@ typedef struct internal_state {
      * are always zero.
      */
 
+    ulg high_water;
+    /* High water mark offset in window for initialized bytes -- bytes above
+     * this are set to zero in order to avoid memory check warnings when
+     * longest match routines access bytes past the input.  This is then
+     * updated to the new high water mark.
+     */
+
 } FAR deflate_state;
 
 /* Output a byte on the stream.
@@ -278,14 +288,19 @@ typedef struct internal_state {
  * distances are limited to MAX_DIST instead of WSIZE.
  */
 
+#define WIN_INIT MAX_MATCH
+/* Number of bytes after end of data in window to initialize in order to avoid
+   memory checker errors from longest match routines */
+
         /* in trees.c */
-void _tr_init         OF((deflate_state *s));
-int  _tr_tally        OF((deflate_state *s, unsigned dist, unsigned lc));
-void _tr_flush_block  OF((deflate_state *s, charf *buf, ulg stored_len,
-                          int eof));
-void _tr_align        OF((deflate_state *s));
-void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
-                          int eof));
+void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
+int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
+                        ulg stored_len, int last));
+void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));
+void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
+void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
+                        ulg stored_len, int last));
 
 #define d_code(dist) \
    ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
@@ -298,11 +313,11 @@ void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
 /* Inline versions of _tr_tally for speed: */
 
 #if defined(GEN_TREES_H) || !defined(STDC)
-  extern uch _length_code[];
-  extern uch _dist_code[];
+  extern uch ZLIB_INTERNAL _length_code[];
+  extern uch ZLIB_INTERNAL _dist_code[];
 #else
-  extern const uch _length_code[];
-  extern const uch _dist_code[];
+  extern const uch ZLIB_INTERNAL _length_code[];
+  extern const uch ZLIB_INTERNAL _dist_code[];
 #endif
 
 # define _tr_tally_lit(s, c, flush) \
diff --git a/third_party/zlib/example.c b/third_party/zlib/example.c
deleted file mode 100644
index 6c8a0ee..0000000
--- a/third_party/zlib/example.c
+++ /dev/null
@@ -1,565 +0,0 @@
-/* example.c -- usage example of the zlib compression library
- * Copyright (C) 1995-2004 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* @(#) $Id$ */
-
-#include <stdio.h>
-#include "zlib.h"
-
-#ifdef STDC
-#  include <string.h>
-#  include <stdlib.h>
-#endif
-
-#if defined(VMS) || defined(RISCOS)
-#  define TESTFILE "foo-gz"
-#else
-#  define TESTFILE "foo.gz"
-#endif
-
-#define CHECK_ERR(err, msg) { \
-    if (err != Z_OK) { \
-        fprintf(stderr, "%s error: %d\n", msg, err); \
-        exit(1); \
-    } \
-}
-
-const char hello[] = "hello, hello!";
-/* "hello world" would be more standard, but the repeated "hello"
- * stresses the compression code better, sorry...
- */
-
-const char dictionary[] = "hello";
-uLong dictId; /* Adler32 value of the dictionary */
-
-void test_compress      OF((Byte *compr, uLong comprLen,
-                            Byte *uncompr, uLong uncomprLen));
-void test_gzio          OF((const char *fname,
-                            Byte *uncompr, uLong uncomprLen));
-void test_deflate       OF((Byte *compr, uLong comprLen));
-void test_inflate       OF((Byte *compr, uLong comprLen,
-                            Byte *uncompr, uLong uncomprLen));
-void test_large_deflate OF((Byte *compr, uLong comprLen,
-                            Byte *uncompr, uLong uncomprLen));
-void test_large_inflate OF((Byte *compr, uLong comprLen,
-                            Byte *uncompr, uLong uncomprLen));
-void test_flush         OF((Byte *compr, uLong *comprLen));
-void test_sync          OF((Byte *compr, uLong comprLen,
-                            Byte *uncompr, uLong uncomprLen));
-void test_dict_deflate  OF((Byte *compr, uLong comprLen));
-void test_dict_inflate  OF((Byte *compr, uLong comprLen,
-                            Byte *uncompr, uLong uncomprLen));
-int  main               OF((int argc, char *argv[]));
-
-/* ===========================================================================
- * Test compress() and uncompress()
- */
-void test_compress(compr, comprLen, uncompr, uncomprLen)
-    Byte *compr, *uncompr;
-    uLong comprLen, uncomprLen;
-{
-    int err;
-    uLong len = (uLong)strlen(hello)+1;
-
-    err = compress(compr, &comprLen, (const Bytef*)hello, len);
-    CHECK_ERR(err, "compress");
-
-    strcpy((char*)uncompr, "garbage");
-
-    err = uncompress(uncompr, &uncomprLen, compr, comprLen);
-    CHECK_ERR(err, "uncompress");
-
-    if (strcmp((char*)uncompr, hello)) {
-        fprintf(stderr, "bad uncompress\n");
-        exit(1);
-    } else {
-        printf("uncompress(): %s\n", (char *)uncompr);
-    }
-}
-
-/* ===========================================================================
- * Test read/write of .gz files
- */
-void test_gzio(fname, uncompr, uncomprLen)
-    const char *fname; /* compressed file name */
-    Byte *uncompr;
-    uLong uncomprLen;
-{
-#ifdef NO_GZCOMPRESS
-    fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
-#else
-    int err;
-    int len = (int)strlen(hello)+1;
-    gzFile file;
-    z_off_t pos;
-
-    file = gzopen(fname, "wb");
-    if (file == NULL) {
-        fprintf(stderr, "gzopen error\n");
-        exit(1);
-    }
-    gzputc(file, 'h');
-    if (gzputs(file, "ello") != 4) {
-        fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
-        exit(1);
-    }
-    if (gzprintf(file, ", %s!", "hello") != 8) {
-        fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
-        exit(1);
-    }
-    gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
-    gzclose(file);
-
-    file = gzopen(fname, "rb");
-    if (file == NULL) {
-        fprintf(stderr, "gzopen error\n");
-        exit(1);
-    }
-    strcpy((char*)uncompr, "garbage");
-
-    if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
-        fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
-        exit(1);
-    }
-    if (strcmp((char*)uncompr, hello)) {
-        fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
-        exit(1);
-    } else {
-        printf("gzread(): %s\n", (char*)uncompr);
-    }
-
-    pos = gzseek(file, -8L, SEEK_CUR);
-    if (pos != 6 || gztell(file) != pos) {
-        fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
-                (long)pos, (long)gztell(file));
-        exit(1);
-    }
-
-    if (gzgetc(file) != ' ') {
-        fprintf(stderr, "gzgetc error\n");
-        exit(1);
-    }
-
-    if (gzungetc(' ', file) != ' ') {
-        fprintf(stderr, "gzungetc error\n");
-        exit(1);
-    }
-
-    gzgets(file, (char*)uncompr, (int)uncomprLen);
-    if (strlen((char*)uncompr) != 7) { /* " hello!" */
-        fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
-        exit(1);
-    }
-    if (strcmp((char*)uncompr, hello + 6)) {
-        fprintf(stderr, "bad gzgets after gzseek\n");
-        exit(1);
-    } else {
-        printf("gzgets() after gzseek: %s\n", (char*)uncompr);
-    }
-
-    gzclose(file);
-#endif
-}
-
-/* ===========================================================================
- * Test deflate() with small buffers
- */
-void test_deflate(compr, comprLen)
-    Byte *compr;
-    uLong comprLen;
-{
-    z_stream c_stream; /* compression stream */
-    int err;
-    uLong len = (uLong)strlen(hello)+1;
-
-    c_stream.zalloc = (alloc_func)0;
-    c_stream.zfree = (free_func)0;
-    c_stream.opaque = (voidpf)0;
-
-    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
-    CHECK_ERR(err, "deflateInit");
-
-    c_stream.next_in  = (Bytef*)hello;
-    c_stream.next_out = compr;
-
-    while (c_stream.total_in != len && c_stream.total_out < comprLen) {
-        c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
-        err = deflate(&c_stream, Z_NO_FLUSH);
-        CHECK_ERR(err, "deflate");
-    }
-    /* Finish the stream, still forcing small buffers: */
-    for (;;) {
-        c_stream.avail_out = 1;
-        err = deflate(&c_stream, Z_FINISH);
-        if (err == Z_STREAM_END) break;
-        CHECK_ERR(err, "deflate");
-    }
-
-    err = deflateEnd(&c_stream);
-    CHECK_ERR(err, "deflateEnd");
-}
-
-/* ===========================================================================
- * Test inflate() with small buffers
- */
-void test_inflate(compr, comprLen, uncompr, uncomprLen)
-    Byte *compr, *uncompr;
-    uLong comprLen, uncomprLen;
-{
-    int err;
-    z_stream d_stream; /* decompression stream */
-
-    strcpy((char*)uncompr, "garbage");
-
-    d_stream.zalloc = (alloc_func)0;
-    d_stream.zfree = (free_func)0;
-    d_stream.opaque = (voidpf)0;
-
-    d_stream.next_in  = compr;
-    d_stream.avail_in = 0;
-    d_stream.next_out = uncompr;
-
-    err = inflateInit(&d_stream);
-    CHECK_ERR(err, "inflateInit");
-
-    while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
-        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
-        err = inflate(&d_stream, Z_NO_FLUSH);
-        if (err == Z_STREAM_END) break;
-        CHECK_ERR(err, "inflate");
-    }
-
-    err = inflateEnd(&d_stream);
-    CHECK_ERR(err, "inflateEnd");
-
-    if (strcmp((char*)uncompr, hello)) {
-        fprintf(stderr, "bad inflate\n");
-        exit(1);
-    } else {
-        printf("inflate(): %s\n", (char *)uncompr);
-    }
-}
-
-/* ===========================================================================
- * Test deflate() with large buffers and dynamic change of compression level
- */
-void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
-    Byte *compr, *uncompr;
-    uLong comprLen, uncomprLen;
-{
-    z_stream c_stream; /* compression stream */
-    int err;
-
-    c_stream.zalloc = (alloc_func)0;
-    c_stream.zfree = (free_func)0;
-    c_stream.opaque = (voidpf)0;
-
-    err = deflateInit(&c_stream, Z_BEST_SPEED);
-    CHECK_ERR(err, "deflateInit");
-
-    c_stream.next_out = compr;
-    c_stream.avail_out = (uInt)comprLen;
-
-    /* At this point, uncompr is still mostly zeroes, so it should compress
-     * very well:
-     */
-    c_stream.next_in = uncompr;
-    c_stream.avail_in = (uInt)uncomprLen;
-    err = deflate(&c_stream, Z_NO_FLUSH);
-    CHECK_ERR(err, "deflate");
-    if (c_stream.avail_in != 0) {
-        fprintf(stderr, "deflate not greedy\n");
-        exit(1);
-    }
-
-    /* Feed in already compressed data and switch to no compression: */
-    deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
-    c_stream.next_in = compr;
-    c_stream.avail_in = (uInt)comprLen/2;
-    err = deflate(&c_stream, Z_NO_FLUSH);
-    CHECK_ERR(err, "deflate");
-
-    /* Switch back to compressing mode: */
-    deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
-    c_stream.next_in = uncompr;
-    c_stream.avail_in = (uInt)uncomprLen;
-    err = deflate(&c_stream, Z_NO_FLUSH);
-    CHECK_ERR(err, "deflate");
-
-    err = deflate(&c_stream, Z_FINISH);
-    if (err != Z_STREAM_END) {
-        fprintf(stderr, "deflate should report Z_STREAM_END\n");
-        exit(1);
-    }
-    err = deflateEnd(&c_stream);
-    CHECK_ERR(err, "deflateEnd");
-}
-
-/* ===========================================================================
- * Test inflate() with large buffers
- */
-void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
-    Byte *compr, *uncompr;
-    uLong comprLen, uncomprLen;
-{
-    int err;
-    z_stream d_stream; /* decompression stream */
-
-    strcpy((char*)uncompr, "garbage");
-
-    d_stream.zalloc = (alloc_func)0;
-    d_stream.zfree = (free_func)0;
-    d_stream.opaque = (voidpf)0;
-
-    d_stream.next_in  = compr;
-    d_stream.avail_in = (uInt)comprLen;
-
-    err = inflateInit(&d_stream);
-    CHECK_ERR(err, "inflateInit");
-
-    for (;;) {
-        d_stream.next_out = uncompr;            /* discard the output */
-        d_stream.avail_out = (uInt)uncomprLen;
-        err = inflate(&d_stream, Z_NO_FLUSH);
-        if (err == Z_STREAM_END) break;
-        CHECK_ERR(err, "large inflate");
-    }
-
-    err = inflateEnd(&d_stream);
-    CHECK_ERR(err, "inflateEnd");
-
-    if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
-        fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
-        exit(1);
-    } else {
-        printf("large_inflate(): OK\n");
-    }
-}
-
-/* ===========================================================================
- * Test deflate() with full flush
- */
-void test_flush(compr, comprLen)
-    Byte *compr;
-    uLong *comprLen;
-{
-    z_stream c_stream; /* compression stream */
-    int err;
-    uInt len = (uInt)strlen(hello)+1;
-
-    c_stream.zalloc = (alloc_func)0;
-    c_stream.zfree = (free_func)0;
-    c_stream.opaque = (voidpf)0;
-
-    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
-    CHECK_ERR(err, "deflateInit");
-
-    c_stream.next_in  = (Bytef*)hello;
-    c_stream.next_out = compr;
-    c_stream.avail_in = 3;
-    c_stream.avail_out = (uInt)*comprLen;
-    err = deflate(&c_stream, Z_FULL_FLUSH);
-    CHECK_ERR(err, "deflate");
-
-    compr[3]++; /* force an error in first compressed block */
-    c_stream.avail_in = len - 3;
-
-    err = deflate(&c_stream, Z_FINISH);
-    if (err != Z_STREAM_END) {
-        CHECK_ERR(err, "deflate");
-    }
-    err = deflateEnd(&c_stream);
-    CHECK_ERR(err, "deflateEnd");
-
-    *comprLen = c_stream.total_out;
-}
-
-/* ===========================================================================
- * Test inflateSync()
- */
-void test_sync(compr, comprLen, uncompr, uncomprLen)
-    Byte *compr, *uncompr;
-    uLong comprLen, uncomprLen;
-{
-    int err;
-    z_stream d_stream; /* decompression stream */
-
-    strcpy((char*)uncompr, "garbage");
-
-    d_stream.zalloc = (alloc_func)0;
-    d_stream.zfree = (free_func)0;
-    d_stream.opaque = (voidpf)0;
-
-    d_stream.next_in  = compr;
-    d_stream.avail_in = 2; /* just read the zlib header */
-
-    err = inflateInit(&d_stream);
-    CHECK_ERR(err, "inflateInit");
-
-    d_stream.next_out = uncompr;
-    d_stream.avail_out = (uInt)uncomprLen;
-
-    inflate(&d_stream, Z_NO_FLUSH);
-    CHECK_ERR(err, "inflate");
-
-    d_stream.avail_in = (uInt)comprLen-2;   /* read all compressed data */
-    err = inflateSync(&d_stream);           /* but skip the damaged part */
-    CHECK_ERR(err, "inflateSync");
-
-    err = inflate(&d_stream, Z_FINISH);
-    if (err != Z_DATA_ERROR) {
-        fprintf(stderr, "inflate should report DATA_ERROR\n");
-        /* Because of incorrect adler32 */
-        exit(1);
-    }
-    err = inflateEnd(&d_stream);
-    CHECK_ERR(err, "inflateEnd");
-
-    printf("after inflateSync(): hel%s\n", (char *)uncompr);
-}
-
-/* ===========================================================================
- * Test deflate() with preset dictionary
- */
-void test_dict_deflate(compr, comprLen)
-    Byte *compr;
-    uLong comprLen;
-{
-    z_stream c_stream; /* compression stream */
-    int err;
-
-    c_stream.zalloc = (alloc_func)0;
-    c_stream.zfree = (free_func)0;
-    c_stream.opaque = (voidpf)0;
-
-    err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
-    CHECK_ERR(err, "deflateInit");
-
-    err = deflateSetDictionary(&c_stream,
-                               (const Bytef*)dictionary, sizeof(dictionary));
-    CHECK_ERR(err, "deflateSetDictionary");
-
-    dictId = c_stream.adler;
-    c_stream.next_out = compr;
-    c_stream.avail_out = (uInt)comprLen;
-
-    c_stream.next_in = (Bytef*)hello;
-    c_stream.avail_in = (uInt)strlen(hello)+1;
-
-    err = deflate(&c_stream, Z_FINISH);
-    if (err != Z_STREAM_END) {
-        fprintf(stderr, "deflate should report Z_STREAM_END\n");
-        exit(1);
-    }
-    err = deflateEnd(&c_stream);
-    CHECK_ERR(err, "deflateEnd");
-}
-
-/* ===========================================================================
- * Test inflate() with a preset dictionary
- */
-void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
-    Byte *compr, *uncompr;
-    uLong comprLen, uncomprLen;
-{
-    int err;
-    z_stream d_stream; /* decompression stream */
-
-    strcpy((char*)uncompr, "garbage");
-
-    d_stream.zalloc = (alloc_func)0;
-    d_stream.zfree = (free_func)0;
-    d_stream.opaque = (voidpf)0;
-
-    d_stream.next_in  = compr;
-    d_stream.avail_in = (uInt)comprLen;
-
-    err = inflateInit(&d_stream);
-    CHECK_ERR(err, "inflateInit");
-
-    d_stream.next_out = uncompr;
-    d_stream.avail_out = (uInt)uncomprLen;
-
-    for (;;) {
-        err = inflate(&d_stream, Z_NO_FLUSH);
-        if (err == Z_STREAM_END) break;
-        if (err == Z_NEED_DICT) {
-            if (d_stream.adler != dictId) {
-                fprintf(stderr, "unexpected dictionary");
-                exit(1);
-            }
-            err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
-                                       sizeof(dictionary));
-        }
-        CHECK_ERR(err, "inflate with dict");
-    }
-
-    err = inflateEnd(&d_stream);
-    CHECK_ERR(err, "inflateEnd");
-
-    if (strcmp((char*)uncompr, hello)) {
-        fprintf(stderr, "bad inflate with dict\n");
-        exit(1);
-    } else {
-        printf("inflate with dictionary: %s\n", (char *)uncompr);
-    }
-}
-
-/* ===========================================================================
- * Usage:  example [output.gz  [input.gz]]
- */
-
-int main(argc, argv)
-    int argc;
-    char *argv[];
-{
-    Byte *compr, *uncompr;
-    uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
-    uLong uncomprLen = comprLen;
-    static const char* myVersion = ZLIB_VERSION;
-
-    if (zlibVersion()[0] != myVersion[0]) {
-        fprintf(stderr, "incompatible zlib version\n");
-        exit(1);
-
-    } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
-        fprintf(stderr, "warning: different zlib version\n");
-    }
-
-    printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
-            ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
-
-    compr    = (Byte*)calloc((uInt)comprLen, 1);
-    uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);
-    /* compr and uncompr are cleared to avoid reading uninitialized
-     * data and to ensure that uncompr compresses well.
-     */
-    if (compr == Z_NULL || uncompr == Z_NULL) {
-        printf("out of memory\n");
-        exit(1);
-    }
-    test_compress(compr, comprLen, uncompr, uncomprLen);
-
-    test_gzio((argc > 1 ? argv[1] : TESTFILE),
-              uncompr, uncomprLen);
-
-    test_deflate(compr, comprLen);
-    test_inflate(compr, comprLen, uncompr, uncomprLen);
-
-    test_large_deflate(compr, comprLen, uncompr, uncomprLen);
-    test_large_inflate(compr, comprLen, uncompr, uncomprLen);
-
-    test_flush(compr, &comprLen);
-    test_sync(compr, comprLen, uncompr, uncomprLen);
-    comprLen = uncomprLen;
-
-    test_dict_deflate(compr, comprLen);
-    test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
-
-    free(compr);
-    free(uncompr);
-
-    return 0;
-}
diff --git a/third_party/zlib/examples/README.examples b/third_party/zlib/examples/README.examples
index 5632d7a..56a3171 100644
--- a/third_party/zlib/examples/README.examples
+++ b/third_party/zlib/examples/README.examples
@@ -1,4 +1,10 @@
-This directory contains examples of the use of zlib.
+This directory contains examples of the use of zlib and other relevant
+programs and documentation.
+
+enough.c
+    calculation and justification of ENOUGH parameter in inftrees.h
+    - calculates the maximum table space used in inflate tree
+      construction over all possible Huffman codes
 
 fitblk.c
     compress just enough input to nearly fill a requested output size
@@ -23,9 +29,10 @@ gzjoin.c
 
 gzlog.c
 gzlog.h
-    efficiently maintain a message log file in gzip format
-    - illustrates use of raw deflate and Z_SYNC_FLUSH
-    - illustrates use of gzip header extra field
+    efficiently and robustly maintain a message log file in gzip format
+    - illustrates use of raw deflate, Z_PARTIAL_FLUSH, deflatePrime(),
+      and deflateSetDictionary()
+    - illustrates use of a gzip header extra field
 
 zlib_how.html
     painfully comprehensive description of zpipe.c (see below)
diff --git a/third_party/zlib/examples/fitblk.c b/third_party/zlib/examples/fitblk.c
index 966702d..c61de5c 100644
--- a/third_party/zlib/examples/fitblk.c
+++ b/third_party/zlib/examples/fitblk.c
@@ -17,7 +17,7 @@
    data in order to determine how much of that input will compress to
    nearly the requested output block size.  The first pass generates
    enough deflate blocks to produce output to fill the requested
-   output size plus a specified excess amount (see the EXCESS define
+   output size plus a specfied excess amount (see the EXCESS define
    below).  The last deflate block may go quite a bit past that, but
    is discarded.  The second pass decompresses and recompresses just
    the compressed data that fit in the requested plus excess sized
diff --git a/third_party/zlib/examples/gun.c b/third_party/zlib/examples/gun.c
index dce01ae..89e484f 100644
--- a/third_party/zlib/examples/gun.c
+++ b/third_party/zlib/examples/gun.c
@@ -1,7 +1,7 @@
 /* gun.c -- simple gunzip to give an example of the use of inflateBack()
- * Copyright (C) 2003, 2005 Mark Adler
+ * Copyright (C) 2003, 2005, 2008, 2010, 2012 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
-   Version 1.3  12 June 2005  Mark Adler */
+   Version 1.7  12 August 2012  Mark Adler */
 
 /* Version history:
    1.0  16 Feb 2003  First version for testing of inflateBack()
@@ -15,6 +15,10 @@
    1.2  20 Mar 2005  Add Unix compress (LZW) decompression
                      Copy file attributes from input file to output file
    1.3  12 Jun 2005  Add casts for error messages [Oberhumer]
+   1.4   8 Dec 2006  LZW decompression speed improvements
+   1.5   9 Feb 2008  Avoid warning in latest version of gcc
+   1.6  17 Jan 2010  Avoid signed/unsigned comparison warnings
+   1.7  12 Aug 2012  Update for z_const usage in zlib 1.2.8
  */
 
 /*
@@ -42,7 +46,7 @@
    end-of-file, they cannot be concantenated.  If a Unix compress stream is
    encountered in an input file, it is the last stream in that file.
 
-   Like gunzip and uncompress, the file attributes of the original compressed
+   Like gunzip and uncompress, the file attributes of the orignal compressed
    file are maintained in the final uncompressed file, to the extent that the
    user permissions allow it.
 
@@ -82,7 +86,7 @@ struct ind {
 /* Load input buffer, assumed to be empty, and return bytes loaded and a
    pointer to them.  read() is called until the buffer is full, or until it
    returns end-of-file or error.  Return 0 on error. */
-local unsigned in(void *in_desc, unsigned char **buf)
+local unsigned in(void *in_desc, z_const unsigned char **buf)
 {
     int ret;
     unsigned len;
@@ -193,18 +197,18 @@ unsigned char match[65280 + 2];         /* buffer for reversed match or gzip
    file, read error, or write error (a write error indicated by strm->next_in
    not equal to Z_NULL), or Z_DATA_ERROR for invalid input.
  */
-local int lunpipe(unsigned have, unsigned char *next, struct ind *indp,
+local int lunpipe(unsigned have, z_const unsigned char *next, struct ind *indp,
                   int outfile, z_stream *strm)
 {
     int last;                   /* last byte read by NEXT(), or -1 if EOF */
-    int chunk;                  /* bytes left in current chunk */
+    unsigned chunk;             /* bytes left in current chunk */
     int left;                   /* bits left in rem */
     unsigned rem;               /* unused bits from input */
     int bits;                   /* current bits per code */
     unsigned code;              /* code, table traversal index */
     unsigned mask;              /* mask for current bits codes */
     int max;                    /* maximum bits per code for this stream */
-    int flags;                  /* compress flags, then block compress flag */
+    unsigned flags;             /* compress flags, then block compress flag */
     unsigned end;               /* last valid entry in prefix/suffix tables */
     unsigned temp;              /* current code */
     unsigned prev;              /* previous code */
@@ -212,6 +216,7 @@ local int lunpipe(unsigned have, unsigned char *next, struct ind *indp,
     unsigned stack;             /* next position for reversed string */
     unsigned outcnt;            /* bytes in output buffer */
     struct outd outd;           /* output structure */
+    unsigned char *p;
 
     /* set up output */
     outd.outfile = outfile;
@@ -322,10 +327,12 @@ local int lunpipe(unsigned have, unsigned char *next, struct ind *indp,
         }
 
         /* walk through linked list to generate output in reverse order */
+        p = match + stack;
         while (code >= 256) {
-            match[stack++] = suffix[code];
+            *p++ = suffix[code];
             code = prefix[code];
         }
+        stack = p - match;
         match[stack++] = (unsigned char)code;
         final = code;
 
@@ -349,9 +356,11 @@ local int lunpipe(unsigned have, unsigned char *next, struct ind *indp,
             }
             outcnt = 0;
         }
+        p = match + stack;
         do {
-            outbuf[outcnt++] = match[--stack];
-        } while (stack);
+            outbuf[outcnt++] = *--p;
+        } while (p > match);
+        stack = 0;
 
         /* loop for next code with final and prev as the last match, rem and
            left provide the first 0..7 bits of the next code, end is the last
@@ -375,7 +384,7 @@ local int gunpipe(z_stream *strm, int infile, int outfile)
 {
     int ret, first, last;
     unsigned have, flags, len;
-    unsigned char *next;
+    z_const unsigned char *next = NULL;
     struct ind ind, *indp;
     struct outd outd;
 
@@ -471,10 +480,10 @@ local int gunpipe(z_stream *strm, int infile, int outfile)
 
         /* check trailer */
         ret = Z_BUF_ERROR;
-        if (NEXT() != (outd.crc & 0xff) ||
-            NEXT() != ((outd.crc >> 8) & 0xff) ||
-            NEXT() != ((outd.crc >> 16) & 0xff) ||
-            NEXT() != ((outd.crc >> 24) & 0xff)) {
+        if (NEXT() != (int)(outd.crc & 0xff) ||
+            NEXT() != (int)((outd.crc >> 8) & 0xff) ||
+            NEXT() != (int)((outd.crc >> 16) & 0xff) ||
+            NEXT() != (int)((outd.crc >> 24) & 0xff)) {
             /* crc error */
             if (last != -1) {
                 strm->msg = (char *)"incorrect data check";
@@ -482,10 +491,10 @@ local int gunpipe(z_stream *strm, int infile, int outfile)
             }
             break;
         }
-        if (NEXT() != (outd.total & 0xff) ||
-            NEXT() != ((outd.total >> 8) & 0xff) ||
-            NEXT() != ((outd.total >> 16) & 0xff) ||
-            NEXT() != ((outd.total >> 24) & 0xff)) {
+        if (NEXT() != (int)(outd.total & 0xff) ||
+            NEXT() != (int)((outd.total >> 8) & 0xff) ||
+            NEXT() != (int)((outd.total >> 16) & 0xff) ||
+            NEXT() != (int)((outd.total >> 24) & 0xff)) {
             /* length error */
             if (last != -1) {
                 strm->msg = (char *)"incorrect length check";
@@ -642,8 +651,8 @@ int main(int argc, char **argv)
     argv++;
     test = 0;
     if (argc && strcmp(*argv, "-h") == 0) {
-        fprintf(stderr, "gun 1.3 (12 Jun 2005)\n");
-        fprintf(stderr, "Copyright (c) 2005 Mark Adler\n");
+        fprintf(stderr, "gun 1.6 (17 Jan 2010)\n");
+        fprintf(stderr, "Copyright (C) 2003-2010 Mark Adler\n");
         fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n");
         return 0;
     }
diff --git a/third_party/zlib/examples/gzappend.c b/third_party/zlib/examples/gzappend.c
index e9e878e..662dec3 100644
--- a/third_party/zlib/examples/gzappend.c
+++ b/third_party/zlib/examples/gzappend.c
@@ -1,7 +1,7 @@
 /* gzappend -- command to append to a gzip file
 
-  Copyright (C) 2003 Mark Adler, all rights reserved
-  version 1.1, 4 Nov 2003
+  Copyright (C) 2003, 2012 Mark Adler, all rights reserved
+  version 1.2, 11 Oct 2012
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the author be held liable for any damages
@@ -39,6 +39,8 @@
  *                      - Keep gzip file clean on appended file read errors
  *                      - Use in-place rotate instead of auxiliary buffer
  *                        (Why you ask?  Because it was fun to write!)
+ * 1.2  11 Oct 2012     - Fix for proper z_const usage
+ *                      - Check for input buffer malloc failure
  */
 
 /*
@@ -170,7 +172,7 @@ typedef struct {
     int size;                   /* 1 << size is bytes in buf */
     unsigned left;              /* bytes available at next */
     unsigned char *buf;         /* buffer */
-    unsigned char *next;        /* next byte in buffer */
+    z_const unsigned char *next;    /* next byte in buffer */
     char *name;                 /* file name for error messages */
 } file;
 
@@ -399,14 +401,14 @@ local void gztack(char *name, int gd, z_stream *strm, int last)
     }
 
     /* allocate buffers */
-    in = fd == -1 ? NULL : malloc(CHUNK);
+    in = malloc(CHUNK);
     out = malloc(CHUNK);
-    if (out == NULL) bye("out of memory", "");
+    if (in == NULL || out == NULL) bye("out of memory", "");
 
     /* compress input file and append to gzip file */
     do {
         /* get more input */
-        len = fd == -1 ? 0 : read(fd, in, CHUNK);
+        len = read(fd, in, CHUNK);
         if (len == -1) {
             fprintf(stderr,
                     "gzappend warning: error reading %s, skipping rest ...\n",
@@ -453,7 +455,7 @@ local void gztack(char *name, int gd, z_stream *strm, int last)
 
     /* clean up and return */
     free(out);
-    if (in != NULL) free(in);
+    free(in);
     if (fd > 0) close(fd);
 }
 
@@ -467,11 +469,13 @@ int main(int argc, char **argv)
     z_stream strm;
 
     /* ignore command name */
-    argv++;
+    argc--; argv++;
 
     /* provide usage if no arguments */
     if (*argv == NULL) {
-        printf("gzappend 1.1 (4 Nov 2003) Copyright (C) 2003 Mark Adler\n");
+        printf(
+            "gzappend 1.2 (11 Oct 2012) Copyright (C) 2003, 2012 Mark Adler\n"
+               );
         printf(
             "usage: gzappend [-level] file.gz [ addthis [ andthis ... ]]\n");
         return 0;
diff --git a/third_party/zlib/examples/gzjoin.c b/third_party/zlib/examples/gzjoin.c
index 129347c..89e8098 100644
--- a/third_party/zlib/examples/gzjoin.c
+++ b/third_party/zlib/examples/gzjoin.c
@@ -1,7 +1,7 @@
 /* gzjoin -- command to join gzip files into one gzip file
 
-  Copyright (C) 2004 Mark Adler, all rights reserved
-  version 1.0, 11 Dec 2004
+  Copyright (C) 2004, 2005, 2012 Mark Adler, all rights reserved
+  version 1.2, 14 Aug 2012
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the author be held liable for any damages
@@ -27,6 +27,7 @@
  *
  * 1.0  11 Dec 2004     - First version
  * 1.1  12 Jun 2005     - Changed ssize_t to long for portability
+ * 1.2  14 Aug 2012     - Clean up for z_const usage
  */
 
 /*
@@ -308,7 +309,7 @@ local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot,
     /* inflate and copy compressed data, clear last-block bit if requested */
     len = 0;
     zpull(&strm, in);
-    start = strm.next_in;
+    start = in->next;
     last = start[0] & 1;
     if (last && clr)
         start[0] &= ~1;
@@ -351,7 +352,7 @@ local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot,
                 pos = 0x100 >> pos;
                 last = strm.next_in[-1] & pos;
                 if (last && clr)
-                    strm.next_in[-1] &= ~pos;
+                    in->buf[strm.next_in - in->buf - 1] &= ~pos;
             }
             else {
                 /* next last-block bit is in next unused byte */
@@ -364,14 +365,14 @@ local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot,
                 }
                 last = strm.next_in[0] & 1;
                 if (last && clr)
-                    strm.next_in[0] &= ~1;
+                    in->buf[strm.next_in - in->buf] &= ~1;
             }
         }
     }
 
     /* update buffer with unused input */
     in->left = strm.avail_in;
-    in->next = strm.next_in;
+    in->next = in->buf + (strm.next_in - in->buf);
 
     /* copy used input, write empty blocks to get to byte boundary */
     pos = strm.data_type & 7;
diff --git a/third_party/zlib/examples/gzlog.c b/third_party/zlib/examples/gzlog.c
index f71f817..922f878 100644
--- a/third_party/zlib/examples/gzlog.c
+++ b/third_party/zlib/examples/gzlog.c
@@ -1,413 +1,1059 @@
 /*
  * gzlog.c
- * Copyright (C) 2004 Mark Adler
+ * Copyright (C) 2004, 2008, 2012 Mark Adler, all rights reserved
  * For conditions of distribution and use, see copyright notice in gzlog.h
- * version 1.0, 26 Nov 2004
- *
+ * version 2.2, 14 Aug 2012
  */
 
-#include <string.h>             /* memcmp() */
-#include <stdlib.h>             /* malloc(), free(), NULL */
-#include <sys/types.h>          /* size_t, off_t */
-#include <unistd.h>             /* read(), close(), sleep(), ftruncate(), */
-                                /* lseek() */
-#include <fcntl.h>              /* open() */
-#include <sys/file.h>           /* flock() */
-#include "zlib.h"               /* deflateInit2(), deflate(), deflateEnd() */
+/*
+   gzlog provides a mechanism for frequently appending short strings to a gzip
+   file that is efficient both in execution time and compression ratio.  The
+   strategy is to write the short strings in an uncompressed form to the end of
+   the gzip file, only compressing when the amount of uncompressed data has
+   reached a given threshold.
+
+   gzlog also provides protection against interruptions in the process due to
+   system crashes.  The status of the operation is recorded in an extra field
+   in the gzip file, and is only updated once the gzip file is brought to a
+   valid state.  The last data to be appended or compressed is saved in an
+   auxiliary file, so that if the operation is interrupted, it can be completed
+   the next time an append operation is attempted.
+
+   gzlog maintains another auxiliary file with the last 32K of data from the
+   compressed portion, which is preloaded for the compression of the subsequent
+   data.  This minimizes the impact to the compression ratio of appending.
+ */
+
+/*
+   Operations Concept:
+
+   Files (log name "foo"):
+   foo.gz -- gzip file with the complete log
+   foo.add -- last message to append or last data to compress
+   foo.dict -- dictionary of the last 32K of data for next compression
+   foo.temp -- temporary dictionary file for compression after this one
+   foo.lock -- lock file for reading and writing the other files
+   foo.repairs -- log file for log file recovery operations (not compressed)
+
+   gzip file structure:
+   - fixed-length (no file name) header with extra field (see below)
+   - compressed data ending initially with empty stored block
+   - uncompressed data filling out originally empty stored block and
+     subsequent stored blocks as needed (16K max each)
+   - gzip trailer
+   - no junk at end (no other gzip streams)
+
+   When appending data, the information in the first three items above plus the
+   foo.add file are sufficient to recover an interrupted append operation.  The
+   extra field has the necessary information to restore the start of the last
+   stored block and determine where to append the data in the foo.add file, as
+   well as the crc and length of the gzip data before the append operation.
+
+   The foo.add file is created before the gzip file is marked for append, and
+   deleted after the gzip file is marked as complete.  So if the append
+   operation is interrupted, the data to add will still be there.  If due to
+   some external force, the foo.add file gets deleted between when the append
+   operation was interrupted and when recovery is attempted, the gzip file will
+   still be restored, but without the appended data.
+
+   When compressing data, the information in the first two items above plus the
+   foo.add file are sufficient to recover an interrupted compress operation.
+   The extra field has the necessary information to find the end of the
+   compressed data, and contains both the crc and length of just the compressed
+   data and of the complete set of data including the contents of the foo.add
+   file.
+
+   Again, the foo.add file is maintained during the compress operation in case
+   of an interruption.  If in the unlikely event the foo.add file with the data
+   to be compressed is missing due to some external force, a gzip file with
+   just the previous compressed data will be reconstructed.  In this case, all
+   of the data that was to be compressed is lost (approximately one megabyte).
+   This will not occur if all that happened was an interruption of the compress
+   operation.
+
+   The third state that is marked is the replacement of the old dictionary with
+   the new dictionary after a compress operation.  Once compression is
+   complete, the gzip file is marked as being in the replace state.  This
+   completes the gzip file, so an interrupt after being so marked does not
+   result in recompression.  Then the dictionary file is replaced, and the gzip
+   file is marked as completed.  This state prevents the possibility of
+   restarting compression with the wrong dictionary file.
+
+   All three operations are wrapped by a lock/unlock procedure.  In order to
+   gain exclusive access to the log files, first a foo.lock file must be
+   exclusively created.  When all operations are complete, the lock is
+   released by deleting the foo.lock file.  If when attempting to create the
+   lock file, it already exists and the modify time of the lock file is more
+   than five minutes old (set by the PATIENCE define below), then the old
+   lock file is considered stale and deleted, and the exclusive creation of
+   the lock file is retried.  To assure that there are no false assessments
+   of the staleness of the lock file, the operations periodically touch the
+   lock file to update the modified date.
+
+   Following is the definition of the extra field with all of the information
+   required to enable the above append and compress operations and their
+   recovery if interrupted.  Multi-byte values are stored little endian
+   (consistent with the gzip format).  File pointers are eight bytes long.
+   The crc's and lengths for the gzip trailer are four bytes long.  (Note that
+   the length at the end of a gzip file is used for error checking only, and
+   for large files is actually the length modulo 2^32.)  The stored block
+   length is two bytes long.  The gzip extra field two-byte identification is
+   "ap" for append.  It is assumed that writing the extra field to the file is
+   an "atomic" operation.  That is, either all of the extra field is written
+   to the file, or none of it is, if the operation is interrupted right at the
+   point of updating the extra field.  This is a reasonable assumption, since
+   the extra field is within the first 52 bytes of the file, which is smaller
+   than any expected block size for a mass storage device (usually 512 bytes or
+   larger).
+
+   Extra field (35 bytes):
+   - Pointer to first stored block length -- this points to the two-byte length
+     of the first stored block, which is followed by the two-byte, one's
+     complement of that length.  The stored block length is preceded by the
+     three-bit header of the stored block, which is the actual start of the
+     stored block in the deflate format.  See the bit offset field below.
+   - Pointer to the last stored block length.  This is the same as above, but
+     for the last stored block of the uncompressed data in the gzip file.
+     Initially this is the same as the first stored block length pointer.
+     When the stored block gets to 16K (see the MAX_STORE define), then a new
+     stored block as added, at which point the last stored block length pointer
+     is different from the first stored block length pointer.  When they are
+     different, the first bit of the last stored block header is eight bits, or
+     one byte back from the block length.
+   - Compressed data crc and length.  This is the crc and length of the data
+     that is in the compressed portion of the deflate stream.  These are used
+     only in the event that the foo.add file containing the data to compress is
+     lost after a compress operation is interrupted.
+   - Total data crc and length.  This is the crc and length of all of the data
+     stored in the gzip file, compressed and uncompressed.  It is used to
+     reconstruct the gzip trailer when compressing, as well as when recovering
+     interrupted operations.
+   - Final stored block length.  This is used to quickly find where to append,
+     and allows the restoration of the original final stored block state when
+     an append operation is interrupted.
+   - First stored block start as the number of bits back from the final stored
+     block first length byte.  This value is in the range of 3..10, and is
+     stored as the low three bits of the final byte of the extra field after
+     subtracting three (0..7).  This allows the last-block bit of the stored
+     block header to be updated when a new stored block is added, for the case
+     when the first stored block and the last stored block are the same.  (When
+     they are different, the numbers of bits back is known to be eight.)  This
+     also allows for new compressed data to be appended to the old compressed
+     data in the compress operation, overwriting the previous first stored
+     block, or for the compressed data to be terminated and a valid gzip file
+     reconstructed on the off chance that a compression operation was
+     interrupted and the data to compress in the foo.add file was deleted.
+   - The operation in process.  This is the next two bits in the last byte (the
+     bits under the mask 0x18).  The are interpreted as 0: nothing in process,
+     1: append in process, 2: compress in process, 3: replace in process.
+   - The top three bits of the last byte in the extra field are reserved and
+     are currently set to zero.
+
+   Main procedure:
+   - Exclusively create the foo.lock file using the O_CREAT and O_EXCL modes of
+     the system open() call.  If the modify time of an existing lock file is
+     more than PATIENCE seconds old, then the lock file is deleted and the
+     exclusive create is retried.
+   - Load the extra field from the foo.gz file, and see if an operation was in
+     progress but not completed.  If so, apply the recovery procedure below.
+   - Perform the append procedure with the provided data.
+   - If the uncompressed data in the foo.gz file is 1MB or more, apply the
+     compress procedure.
+   - Delete the foo.lock file.
+
+   Append procedure:
+   - Put what to append in the foo.add file so that the operation can be
+     restarted if this procedure is interrupted.
+   - Mark the foo.gz extra field with the append operation in progress.
+   + Restore the original last-block bit and stored block length of the last
+     stored block from the information in the extra field, in case a previous
+     append operation was interrupted.
+   - Append the provided data to the last stored block, creating new stored
+     blocks as needed and updating the stored blocks last-block bits and
+     lengths.
+   - Update the crc and length with the new data, and write the gzip trailer.
+   - Write over the extra field (with a single write operation) with the new
+     pointers, lengths, and crc's, and mark the gzip file as not in process.
+     Though there is still a foo.add file, it will be ignored since nothing
+     is in process.  If a foo.add file is leftover from a previously
+     completed operation, it is truncated when writing new data to it.
+   - Delete the foo.add file.
+
+   Compress and replace procedures:
+   - Read all of the uncompressed data in the stored blocks in foo.gz and write
+     it to foo.add.  Also write foo.temp with the last 32K of that data to
+     provide a dictionary for the next invocation of this procedure.
+   - Rewrite the extra field marking foo.gz with a compression in process.
+   * If there is no data provided to compress (due to a missing foo.add file
+     when recovering), reconstruct and truncate the foo.gz file to contain
+     only the previous compressed data and proceed to the step after the next
+     one.  Otherwise ...
+   - Compress the data with the dictionary in foo.dict, and write to the
+     foo.gz file starting at the bit immediately following the last previously
+     compressed block.  If there is no foo.dict, proceed anyway with the
+     compression at slightly reduced efficiency.  (For the foo.dict file to be
+     missing requires some external failure beyond simply the interruption of
+     a compress operation.)  During this process, the foo.lock file is
+     periodically touched to assure that that file is not considered stale by
+     another process before we're done.  The deflation is terminated with a
+     non-last empty static block (10 bits long), that is then located and
+     written over by a last-bit-set empty stored block.
+   - Append the crc and length of the data in the gzip file (previously
+     calculated during the append operations).
+   - Write over the extra field with the updated stored block offsets, bits
+     back, crc's, and lengths, and mark foo.gz as in process for a replacement
+     of the dictionary.
+   @ Delete the foo.add file.
+   - Replace foo.dict with foo.temp.
+   - Write over the extra field, marking foo.gz as complete.
+
+   Recovery procedure:
+   - If not a replace recovery, read in the foo.add file, and provide that data
+     to the appropriate recovery below.  If there is no foo.add file, provide
+     a zero data length to the recovery.  In that case, the append recovery
+     restores the foo.gz to the previous compressed + uncompressed data state.
+     For the the compress recovery, a missing foo.add file results in foo.gz
+     being restored to the previous compressed-only data state.
+   - Append recovery:
+     - Pick up append at + step above
+   - Compress recovery:
+     - Pick up compress at * step above
+   - Replace recovery:
+     - Pick up compress at @ step above
+   - Log the repair with a date stamp in foo.repairs
+ */
+
+#include <sys/types.h>
+#include <stdio.h>      /* rename, fopen, fprintf, fclose */
+#include <stdlib.h>     /* malloc, free */
+#include <string.h>     /* strlen, strrchr, strcpy, strncpy, strcmp */
+#include <fcntl.h>      /* open */
+#include <unistd.h>     /* lseek, read, write, close, unlink, sleep, */
+                        /* ftruncate, fsync */
+#include <errno.h>      /* errno */
+#include <time.h>       /* time, ctime */
+#include <sys/stat.h>   /* stat */
+#include <sys/time.h>   /* utimes */
+#include "zlib.h"       /* crc32 */
+
+#include "gzlog.h"      /* header for external access */
 
-#include "gzlog.h"              /* interface */
 #define local static
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+/* Macro for debugging to deterministically force recovery operations */
+#ifdef DEBUG
+    #include <setjmp.h>         /* longjmp */
+    jmp_buf gzlog_jump;         /* where to go back to */
+    int gzlog_bail = 0;         /* which point to bail at (1..8) */
+    int gzlog_count = -1;       /* number of times through to wait */
+#   define BAIL(n) do { if (n == gzlog_bail && gzlog_count-- == 0) \
+                            longjmp(gzlog_jump, gzlog_bail); } while (0)
+#else
+#   define BAIL(n)
+#endif
+
+/* how old the lock file can be in seconds before considering it stale */
+#define PATIENCE 300
+
+/* maximum stored block size in Kbytes -- must be in 1..63 */
+#define MAX_STORE 16
 
-/* log object structure */
-typedef struct {
-    int id;                 /* object identifier */
-    int fd;                 /* log file descriptor */
-    off_t extra;            /* offset of extra "ap" subfield */
-    off_t mark_off;         /* offset of marked data */
-    off_t last_off;         /* offset of last block */
-    unsigned long crc;      /* uncompressed crc */
-    unsigned long len;      /* uncompressed length (modulo 2^32) */
-    unsigned stored;        /* length of current stored block */
-} gz_log;
-
-#define GZLOGID 19334       /* gz_log object identifier */
-
-#define LOCK_RETRY 1            /* retry lock once a second */
-#define LOCK_PATIENCE 1200      /* try about twenty minutes before forcing */
-
-/* acquire a lock on a file */
-local int lock(int fd)
+/* number of stored Kbytes to trigger compression (must be >= 32 to allow
+   dictionary construction, and <= 204 * MAX_STORE, in order for >> 10 to
+   discard the stored block headers contribution of five bytes each) */
+#define TRIGGER 1024
+
+/* size of a deflate dictionary (this cannot be changed) */
+#define DICT 32768U
+
+/* values for the operation (2 bits) */
+#define NO_OP 0
+#define APPEND_OP 1
+#define COMPRESS_OP 2
+#define REPLACE_OP 3
+
+/* macros to extract little-endian integers from an unsigned byte buffer */
+#define PULL2(p) ((p)[0]+((uint)((p)[1])<<8))
+#define PULL4(p) (PULL2(p)+((ulong)PULL2(p+2)<<16))
+#define PULL8(p) (PULL4(p)+((off_t)PULL4(p+4)<<32))
+
+/* macros to store integers into a byte buffer in little-endian order */
+#define PUT2(p,a) do {(p)[0]=a;(p)[1]=(a)>>8;} while(0)
+#define PUT4(p,a) do {PUT2(p,a);PUT2(p+2,a>>16);} while(0)
+#define PUT8(p,a) do {PUT4(p,a);PUT4(p+4,a>>32);} while(0)
+
+/* internal structure for log information */
+#define LOGID "\106\035\172"    /* should be three non-zero characters */
+struct log {
+    char id[4];     /* contains LOGID to detect inadvertent overwrites */
+    int fd;         /* file descriptor for .gz file, opened read/write */
+    char *path;     /* allocated path, e.g. "/var/log/foo" or "foo" */
+    char *end;      /* end of path, for appending suffices such as ".gz" */
+    off_t first;    /* offset of first stored block first length byte */
+    int back;       /* location of first block id in bits back from first */
+    uint stored;    /* bytes currently in last stored block */
+    off_t last;     /* offset of last stored block first length byte */
+    ulong ccrc;     /* crc of compressed data */
+    ulong clen;     /* length (modulo 2^32) of compressed data */
+    ulong tcrc;     /* crc of total data */
+    ulong tlen;     /* length (modulo 2^32) of total data */
+    time_t lock;    /* last modify time of our lock file */
+};
+
+/* gzip header for gzlog */
+local unsigned char log_gzhead[] = {
+    0x1f, 0x8b,                 /* magic gzip id */
+    8,                          /* compression method is deflate */
+    4,                          /* there is an extra field (no file name) */
+    0, 0, 0, 0,                 /* no modification time provided */
+    0, 0xff,                    /* no extra flags, no OS specified */
+    39, 0, 'a', 'p', 35, 0      /* extra field with "ap" subfield */
+                                /* 35 is EXTRA, 39 is EXTRA + 4 */
+};
+
+#define HEAD sizeof(log_gzhead)     /* should be 16 */
+
+/* initial gzip extra field content (52 == HEAD + EXTRA + 1) */
+local unsigned char log_gzext[] = {
+    52, 0, 0, 0, 0, 0, 0, 0,    /* offset of first stored block length */
+    52, 0, 0, 0, 0, 0, 0, 0,    /* offset of last stored block length */
+    0, 0, 0, 0, 0, 0, 0, 0,     /* compressed data crc and length */
+    0, 0, 0, 0, 0, 0, 0, 0,     /* total data crc and length */
+    0, 0,                       /* final stored block data length */
+    5                           /* op is NO_OP, last bit 8 bits back */
+};
+
+#define EXTRA sizeof(log_gzext)     /* should be 35 */
+
+/* initial gzip data and trailer */
+local unsigned char log_gzbody[] = {
+    1, 0, 0, 0xff, 0xff,        /* empty stored block (last) */
+    0, 0, 0, 0,                 /* crc */
+    0, 0, 0, 0                  /* uncompressed length */
+};
+
+#define BODY sizeof(log_gzbody)
+
+/* Exclusively create foo.lock in order to negotiate exclusive access to the
+   foo.* files.  If the modify time of an existing lock file is greater than
+   PATIENCE seconds in the past, then consider the lock file to have been
+   abandoned, delete it, and try the exclusive create again.  Save the lock
+   file modify time for verification of ownership.  Return 0 on success, or -1
+   on failure, usually due to an access restriction or invalid path.  Note that
+   if stat() or unlink() fails, it may be due to another process noticing the
+   abandoned lock file a smidge sooner and deleting it, so those are not
+   flagged as an error. */
+local int log_lock(struct log *log)
 {
-    int patience;
+    int fd;
+    struct stat st;
 
-    /* try to lock every LOCK_RETRY seconds for LOCK_PATIENCE seconds */
-    patience = LOCK_PATIENCE;
-    do {
-        if (flock(fd, LOCK_EX + LOCK_NB) == 0)
-            return 0;
-        (void)sleep(LOCK_RETRY);
-        patience -= LOCK_RETRY;
-    } while (patience > 0);
+    strcpy(log->end, ".lock");
+    while ((fd = open(log->path, O_CREAT | O_EXCL, 0644)) < 0) {
+        if (errno != EEXIST)
+            return -1;
+        if (stat(log->path, &st) == 0 && time(NULL) - st.st_mtime > PATIENCE) {
+            unlink(log->path);
+            continue;
+        }
+        sleep(2);       /* relinquish the CPU for two seconds while waiting */
+    }
+    close(fd);
+    if (stat(log->path, &st) == 0)
+        log->lock = st.st_mtime;
+    return 0;
+}
 
-    /* we've run out of patience -- give up */
-    return -1;
+/* Update the modify time of the lock file to now, in order to prevent another
+   task from thinking that the lock is stale.  Save the lock file modify time
+   for verification of ownership. */
+local void log_touch(struct log *log)
+{
+    struct stat st;
+
+    strcpy(log->end, ".lock");
+    utimes(log->path, NULL);
+    if (stat(log->path, &st) == 0)
+        log->lock = st.st_mtime;
 }
 
-/* release lock */
-local void unlock(int fd)
+/* Check the log file modify time against what is expected.  Return true if
+   this is not our lock.  If it is our lock, touch it to keep it. */
+local int log_check(struct log *log)
 {
-    (void)flock(fd, LOCK_UN);
+    struct stat st;
+
+    strcpy(log->end, ".lock");
+    if (stat(log->path, &st) || st.st_mtime != log->lock)
+        return 1;
+    log_touch(log);
+    return 0;
 }
 
-/* release a log object */
-local void log_clean(gz_log *log)
+/* Unlock a previously acquired lock, but only if it's ours. */
+local void log_unlock(struct log *log)
 {
-    unlock(log->fd);
-    (void)close(log->fd);
-    free(log);
+    if (log_check(log))
+        return;
+    strcpy(log->end, ".lock");
+    unlink(log->path);
+    log->lock = 0;
 }
 
-/* read an unsigned long from a byte buffer little-endian */
-local unsigned long make_ulg(unsigned char *buf)
+/* Check the gzip header and read in the extra field, filling in the values in
+   the log structure.  Return op on success or -1 if the gzip header was not as
+   expected.  op is the current operation in progress last written to the extra
+   field.  This assumes that the gzip file has already been opened, with the
+   file descriptor log->fd. */
+local int log_head(struct log *log)
 {
-    int n;
-    unsigned long val;
+    int op;
+    unsigned char buf[HEAD + EXTRA];
 
-    val = (unsigned long)(*buf++);
-    for (n = 8; n < 32; n += 8)
-        val += (unsigned long)(*buf++) << n;
-    return val;
+    if (lseek(log->fd, 0, SEEK_SET) < 0 ||
+        read(log->fd, buf, HEAD + EXTRA) != HEAD + EXTRA ||
+        memcmp(buf, log_gzhead, HEAD)) {
+        return -1;
+    }
+    log->first = PULL8(buf + HEAD);
+    log->last = PULL8(buf + HEAD + 8);
+    log->ccrc = PULL4(buf + HEAD + 16);
+    log->clen = PULL4(buf + HEAD + 20);
+    log->tcrc = PULL4(buf + HEAD + 24);
+    log->tlen = PULL4(buf + HEAD + 28);
+    log->stored = PULL2(buf + HEAD + 32);
+    log->back = 3 + (buf[HEAD + 34] & 7);
+    op = (buf[HEAD + 34] >> 3) & 3;
+    return op;
 }
 
-/* read an off_t from a byte buffer little-endian */
-local off_t make_off(unsigned char *buf)
+/* Write over the extra field contents, marking the operation as op.  Use fsync
+   to assure that the device is written to, and in the requested order.  This
+   operation, and only this operation, is assumed to be atomic in order to
+   assure that the log is recoverable in the event of an interruption at any
+   point in the process.  Return -1 if the write to foo.gz failed. */
+local int log_mark(struct log *log, int op)
 {
-    int n;
-    off_t val;
+    int ret;
+    unsigned char ext[EXTRA];
 
-    val = (off_t)(*buf++);
-    for (n = 8; n < 64; n += 8)
-        val += (off_t)(*buf++) << n;
-    return val;
+    PUT8(ext, log->first);
+    PUT8(ext + 8, log->last);
+    PUT4(ext + 16, log->ccrc);
+    PUT4(ext + 20, log->clen);
+    PUT4(ext + 24, log->tcrc);
+    PUT4(ext + 28, log->tlen);
+    PUT2(ext + 32, log->stored);
+    ext[34] = log->back - 3 + (op << 3);
+    fsync(log->fd);
+    ret = lseek(log->fd, HEAD, SEEK_SET) < 0 ||
+          write(log->fd, ext, EXTRA) != EXTRA ? -1 : 0;
+    fsync(log->fd);
+    return ret;
 }
 
-/* write an unsigned long little-endian to byte buffer */
-local void dice_ulg(unsigned long val, unsigned char *buf)
+/* Rewrite the last block header bits and subsequent zero bits to get to a byte
+   boundary, setting the last block bit if last is true, and then write the
+   remainder of the stored block header (length and one's complement).  Leave
+   the file pointer after the end of the last stored block data.  Return -1 if
+   there is a read or write failure on the foo.gz file */
+local int log_last(struct log *log, int last)
 {
-    int n;
+    int back, len, mask;
+    unsigned char buf[6];
+
+    /* determine the locations of the bytes and bits to modify */
+    back = log->last == log->first ? log->back : 8;
+    len = back > 8 ? 2 : 1;                 /* bytes back from log->last */
+    mask = 0x80 >> ((back - 1) & 7);        /* mask for block last-bit */
+
+    /* get the byte to modify (one or two back) into buf[0] -- don't need to
+       read the byte if the last-bit is eight bits back, since in that case
+       the entire byte will be modified */
+    buf[0] = 0;
+    if (back != 8 && (lseek(log->fd, log->last - len, SEEK_SET) < 0 ||
+                      read(log->fd, buf, 1) != 1))
+        return -1;
+
+    /* change the last-bit of the last stored block as requested -- note
+       that all bits above the last-bit are set to zero, per the type bits
+       of a stored block being 00 and per the convention that the bits to
+       bring the stream to a byte boundary are also zeros */
+    buf[1] = 0;
+    buf[2 - len] = (*buf & (mask - 1)) + (last ? mask : 0);
 
-    for (n = 0; n < 4; n++) {
-        *buf++ = val & 0xff;
-        val >>= 8;
+    /* write the modified stored block header and lengths, move the file
+       pointer to after the last stored block data */
+    PUT2(buf + 2, log->stored);
+    PUT2(buf + 4, log->stored ^ 0xffff);
+    return lseek(log->fd, log->last - len, SEEK_SET) < 0 ||
+           write(log->fd, buf + 2 - len, len + 4) != len + 4 ||
+           lseek(log->fd, log->stored, SEEK_CUR) < 0 ? -1 : 0;
+}
+
+/* Append len bytes from data to the locked and open log file.  len may be zero
+   if recovering and no .add file was found.  In that case, the previous state
+   of the foo.gz file is restored.  The data is appended uncompressed in
+   deflate stored blocks.  Return -1 if there was an error reading or writing
+   the foo.gz file. */
+local int log_append(struct log *log, unsigned char *data, size_t len)
+{
+    uint put;
+    off_t end;
+    unsigned char buf[8];
+
+    /* set the last block last-bit and length, in case recovering an
+       interrupted append, then position the file pointer to append to the
+       block */
+    if (log_last(log, 1))
+        return -1;
+
+    /* append, adding stored blocks and updating the offset of the last stored
+       block as needed, and update the total crc and length */
+    while (len) {
+        /* append as much as we can to the last block */
+        put = (MAX_STORE << 10) - log->stored;
+        if (put > len)
+            put = (uint)len;
+        if (put) {
+            if (write(log->fd, data, put) != put)
+                return -1;
+            BAIL(1);
+            log->tcrc = crc32(log->tcrc, data, put);
+            log->tlen += put;
+            log->stored += put;
+            data += put;
+            len -= put;
+        }
+
+        /* if we need to, add a new empty stored block */
+        if (len) {
+            /* mark current block as not last */
+            if (log_last(log, 0))
+                return -1;
+
+            /* point to new, empty stored block */
+            log->last += 4 + log->stored + 1;
+            log->stored = 0;
+        }
+
+        /* mark last block as last, update its length */
+        if (log_last(log, 1))
+            return -1;
+        BAIL(2);
     }
+
+    /* write the new crc and length trailer, and truncate just in case (could
+       be recovering from partial append with a missing foo.add file) */
+    PUT4(buf, log->tcrc);
+    PUT4(buf + 4, log->tlen);
+    if (write(log->fd, buf, 8) != 8 ||
+        (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end))
+        return -1;
+
+    /* write the extra field, marking the log file as done, delete .add file */
+    if (log_mark(log, NO_OP))
+        return -1;
+    strcpy(log->end, ".add");
+    unlink(log->path);          /* ignore error, since may not exist */
+    return 0;
 }
 
-/* write an off_t little-endian to byte buffer */
-local void dice_off(off_t val, unsigned char *buf)
+/* Replace the foo.dict file with the foo.temp file.  Also delete the foo.add
+   file, since the compress operation may have been interrupted before that was
+   done.  Returns 1 if memory could not be allocated, or -1 if reading or
+   writing foo.gz fails, or if the rename fails for some reason other than
+   foo.temp not existing.  foo.temp not existing is a permitted error, since
+   the replace operation may have been interrupted after the rename is done,
+   but before foo.gz is marked as complete. */
+local int log_replace(struct log *log)
 {
-    int n;
+    int ret;
+    char *dest;
+
+    /* delete foo.add file */
+    strcpy(log->end, ".add");
+    unlink(log->path);         /* ignore error, since may not exist */
+    BAIL(3);
+
+    /* rename foo.name to foo.dict, replacing foo.dict if it exists */
+    strcpy(log->end, ".dict");
+    dest = malloc(strlen(log->path) + 1);
+    if (dest == NULL)
+        return -2;
+    strcpy(dest, log->path);
+    strcpy(log->end, ".temp");
+    ret = rename(log->path, dest);
+    free(dest);
+    if (ret && errno != ENOENT)
+        return -1;
+    BAIL(4);
 
-    for (n = 0; n < 8; n++) {
-        *buf++ = val & 0xff;
-        val >>= 8;
+    /* mark the foo.gz file as done */
+    return log_mark(log, NO_OP);
+}
+
+/* Compress the len bytes at data and append the compressed data to the
+   foo.gz deflate data immediately after the previous compressed data.  This
+   overwrites the previous uncompressed data, which was stored in foo.add
+   and is the data provided in data[0..len-1].  If this operation is
+   interrupted, it picks up at the start of this routine, with the foo.add
+   file read in again.  If there is no data to compress (len == 0), then we
+   simply terminate the foo.gz file after the previously compressed data,
+   appending a final empty stored block and the gzip trailer.  Return -1 if
+   reading or writing the log.gz file failed, or -2 if there was a memory
+   allocation failure. */
+local int log_compress(struct log *log, unsigned char *data, size_t len)
+{
+    int fd;
+    uint got, max;
+    ssize_t dict;
+    off_t end;
+    z_stream strm;
+    unsigned char buf[DICT];
+
+    /* compress and append compressed data */
+    if (len) {
+        /* set up for deflate, allocating memory */
+        strm.zalloc = Z_NULL;
+        strm.zfree = Z_NULL;
+        strm.opaque = Z_NULL;
+        if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8,
+                         Z_DEFAULT_STRATEGY) != Z_OK)
+            return -2;
+
+        /* read in dictionary (last 32K of data that was compressed) */
+        strcpy(log->end, ".dict");
+        fd = open(log->path, O_RDONLY, 0);
+        if (fd >= 0) {
+            dict = read(fd, buf, DICT);
+            close(fd);
+            if (dict < 0) {
+                deflateEnd(&strm);
+                return -1;
+            }
+            if (dict)
+                deflateSetDictionary(&strm, buf, (uint)dict);
+        }
+        log_touch(log);
+
+        /* prime deflate with last bits of previous block, position write
+           pointer to write those bits and overwrite what follows */
+        if (lseek(log->fd, log->first - (log->back > 8 ? 2 : 1),
+                SEEK_SET) < 0 ||
+            read(log->fd, buf, 1) != 1 || lseek(log->fd, -1, SEEK_CUR) < 0) {
+            deflateEnd(&strm);
+            return -1;
+        }
+        deflatePrime(&strm, (8 - log->back) & 7, *buf);
+
+        /* compress, finishing with a partial non-last empty static block */
+        strm.next_in = data;
+        max = (((uint)0 - 1) >> 1) + 1; /* in case int smaller than size_t */
+        do {
+            strm.avail_in = len > max ? max : (uint)len;
+            len -= strm.avail_in;
+            do {
+                strm.avail_out = DICT;
+                strm.next_out = buf;
+                deflate(&strm, len ? Z_NO_FLUSH : Z_PARTIAL_FLUSH);
+                got = DICT - strm.avail_out;
+                if (got && write(log->fd, buf, got) != got) {
+                    deflateEnd(&strm);
+                    return -1;
+                }
+                log_touch(log);
+            } while (strm.avail_out == 0);
+        } while (len);
+        deflateEnd(&strm);
+        BAIL(5);
+
+        /* find start of empty static block -- scanning backwards the first one
+           bit is the second bit of the block, if the last byte is zero, then
+           we know the byte before that has a one in the top bit, since an
+           empty static block is ten bits long */
+        if ((log->first = lseek(log->fd, -1, SEEK_CUR)) < 0 ||
+            read(log->fd, buf, 1) != 1)
+            return -1;
+        log->first++;
+        if (*buf) {
+            log->back = 1;
+            while ((*buf & ((uint)1 << (8 - log->back++))) == 0)
+                ;       /* guaranteed to terminate, since *buf != 0 */
+        }
+        else
+            log->back = 10;
+
+        /* update compressed crc and length */
+        log->ccrc = log->tcrc;
+        log->clen = log->tlen;
+    }
+    else {
+        /* no data to compress -- fix up existing gzip stream */
+        log->tcrc = log->ccrc;
+        log->tlen = log->clen;
     }
+
+    /* complete and truncate gzip stream */
+    log->last = log->first;
+    log->stored = 0;
+    PUT4(buf, log->tcrc);
+    PUT4(buf + 4, log->tlen);
+    if (log_last(log, 1) || write(log->fd, buf, 8) != 8 ||
+        (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end))
+        return -1;
+    BAIL(6);
+
+    /* mark as being in the replace operation */
+    if (log_mark(log, REPLACE_OP))
+        return -1;
+
+    /* execute the replace operation and mark the file as done */
+    return log_replace(log);
 }
 
-/* initial, empty gzip file for appending */
-local char empty_gz[] = {
-    0x1f, 0x8b,                 /* magic gzip id */
-    8,                          /* compression method is deflate */
-    4,                          /* there is an extra field */
-    0, 0, 0, 0,                 /* no modification time provided */
-    0, 0xff,                    /* no extra flags, no OS */
-    20, 0, 'a', 'p', 16, 0,     /* extra field with "ap" subfield */
-    32, 0, 0, 0, 0, 0, 0, 0,    /* offset of uncompressed data */
-    32, 0, 0, 0, 0, 0, 0, 0,    /* offset of last block */
-    1, 0, 0, 0xff, 0xff,        /* empty stored block (last) */
-    0, 0, 0, 0,                 /* crc */
-    0, 0, 0, 0                  /* uncompressed length */
-};
+/* log a repair record to the .repairs file */
+local void log_log(struct log *log, int op, char *record)
+{
+    time_t now;
+    FILE *rec;
 
-/* initialize a log object with locking */
-void *gzlog_open(char *path)
+    now = time(NULL);
+    strcpy(log->end, ".repairs");
+    rec = fopen(log->path, "a");
+    if (rec == NULL)
+        return;
+    fprintf(rec, "%.24s %s recovery: %s\n", ctime(&now), op == APPEND_OP ?
+            "append" : (op == COMPRESS_OP ? "compress" : "replace"), record);
+    fclose(rec);
+    return;
+}
+
+/* Recover the interrupted operation op.  First read foo.add for recovering an
+   append or compress operation.  Return -1 if there was an error reading or
+   writing foo.gz or reading an existing foo.add, or -2 if there was a memory
+   allocation failure. */
+local int log_recover(struct log *log, int op)
 {
-    unsigned xlen;
-    unsigned char temp[20];
-    unsigned sub_len;
-    int good;
-    gz_log *log;
-
-    /* allocate log structure */
-    log = malloc(sizeof(gz_log));
-    if (log == NULL)
-        return NULL;
-    log->id = GZLOGID;
+    int fd, ret = 0;
+    unsigned char *data = NULL;
+    size_t len = 0;
+    struct stat st;
 
-    /* open file, creating it if necessary, and locking it */
-    log->fd = open(path, O_RDWR | O_CREAT, 0600);
-    if (log->fd < 0) {
-        free(log);
-        return NULL;
+    /* log recovery */
+    log_log(log, op, "start");
+
+    /* load foo.add file if expected and present */
+    if (op == APPEND_OP || op == COMPRESS_OP) {
+        strcpy(log->end, ".add");
+        if (stat(log->path, &st) == 0 && st.st_size) {
+            len = (size_t)(st.st_size);
+            if ((off_t)len != st.st_size ||
+                    (data = malloc(st.st_size)) == NULL) {
+                log_log(log, op, "allocation failure");
+                return -2;
+            }
+            if ((fd = open(log->path, O_RDONLY, 0)) < 0) {
+                log_log(log, op, ".add file read failure");
+                return -1;
+            }
+            ret = (size_t)read(fd, data, len) != len;
+            close(fd);
+            if (ret) {
+                log_log(log, op, ".add file read failure");
+                return -1;
+            }
+            log_log(log, op, "loaded .add file");
+        }
+        else
+            log_log(log, op, "missing .add file!");
+    }
+
+    /* recover the interrupted operation */
+    switch (op) {
+    case APPEND_OP:
+        ret = log_append(log, data, len);
+        break;
+    case COMPRESS_OP:
+        ret = log_compress(log, data, len);
+        break;
+    case REPLACE_OP:
+        ret = log_replace(log);
     }
-    if (lock(log->fd)) {
+
+    /* log status */
+    log_log(log, op, ret ? "failure" : "complete");
+
+    /* clean up */
+    if (data != NULL)
+        free(data);
+    return ret;
+}
+
+/* Close the foo.gz file (if open) and release the lock. */
+local void log_close(struct log *log)
+{
+    if (log->fd >= 0)
         close(log->fd);
-        free(log);
-        return NULL;
+    log->fd = -1;
+    log_unlock(log);
+}
+
+/* Open foo.gz, verify the header, and load the extra field contents, after
+   first creating the foo.lock file to gain exclusive access to the foo.*
+   files.  If foo.gz does not exist or is empty, then write the initial header,
+   extra, and body content of an empty foo.gz log file.  If there is an error
+   creating the lock file due to access restrictions, or an error reading or
+   writing the foo.gz file, or if the foo.gz file is not a proper log file for
+   this object (e.g. not a gzip file or does not contain the expected extra
+   field), then return true.  If there is an error, the lock is released.
+   Otherwise, the lock is left in place. */
+local int log_open(struct log *log)
+{
+    int op;
+
+    /* release open file resource if left over -- can occur if lock lost
+       between gzlog_open() and gzlog_write() */
+    if (log->fd >= 0)
+        close(log->fd);
+    log->fd = -1;
+
+    /* negotiate exclusive access */
+    if (log_lock(log) < 0)
+        return -1;
+
+    /* open the log file, foo.gz */
+    strcpy(log->end, ".gz");
+    log->fd = open(log->path, O_RDWR | O_CREAT, 0644);
+    if (log->fd < 0) {
+        log_close(log);
+        return -1;
     }
 
-    /* if file is empty, write new gzip stream */
+    /* if new, initialize foo.gz with an empty log, delete old dictionary */
     if (lseek(log->fd, 0, SEEK_END) == 0) {
-        if (write(log->fd, empty_gz, sizeof(empty_gz)) != sizeof(empty_gz)) {
-            log_clean(log);
-            return NULL;
+        if (write(log->fd, log_gzhead, HEAD) != HEAD ||
+            write(log->fd, log_gzext, EXTRA) != EXTRA ||
+            write(log->fd, log_gzbody, BODY) != BODY) {
+            log_close(log);
+            return -1;
         }
+        strcpy(log->end, ".dict");
+        unlink(log->path);
     }
 
-    /* check gzip header */
-    (void)lseek(log->fd, 0, SEEK_SET);
-    if (read(log->fd, temp, 12) != 12 || temp[0] != 0x1f ||
-        temp[1] != 0x8b || temp[2] != 8 || (temp[3] & 4) == 0) {
-        log_clean(log);
-        return NULL;
+    /* verify log file and load extra field information */
+    if ((op = log_head(log)) < 0) {
+        log_close(log);
+        return -1;
     }
 
-    /* process extra field to find "ap" sub-field */
-    xlen = temp[10] + (temp[11] << 8);
-    good = 0;
-    while (xlen) {
-        if (xlen < 4 || read(log->fd, temp, 4) != 4)
-            break;
-        sub_len = temp[2];
-        sub_len += temp[3] << 8;
-        xlen -= 4;
-        if (memcmp(temp, "ap", 2) == 0 && sub_len == 16) {
-            good = 1;
-            break;
-        }
-        if (xlen < sub_len)
-            break;
-        (void)lseek(log->fd, sub_len, SEEK_CUR);
-        xlen -= sub_len;
+    /* check for interrupted process and if so, recover */
+    if (op != NO_OP && log_recover(log, op)) {
+        log_close(log);
+        return -1;
     }
-    if (!good) {
-        log_clean(log);
+
+    /* touch the lock file to prevent another process from grabbing it */
+    log_touch(log);
+    return 0;
+}
+
+/* See gzlog.h for the description of the external methods below */
+gzlog *gzlog_open(char *path)
+{
+    size_t n;
+    struct log *log;
+
+    /* check arguments */
+    if (path == NULL || *path == 0)
         return NULL;
-    }
 
-    /* read in "ap" sub-field */
-    log->extra = lseek(log->fd, 0, SEEK_CUR);
-    if (read(log->fd, temp, 16) != 16) {
-        log_clean(log);
+    /* allocate and initialize log structure */
+    log = malloc(sizeof(struct log));
+    if (log == NULL)
+        return NULL;
+    strcpy(log->id, LOGID);
+    log->fd = -1;
+
+    /* save path and end of path for name construction */
+    n = strlen(path);
+    log->path = malloc(n + 9);              /* allow for ".repairs" */
+    if (log->path == NULL) {
+        free(log);
         return NULL;
     }
-    log->mark_off = make_off(temp);
-    log->last_off = make_off(temp + 8);
-
-    /* get crc, length of gzip file */
-    (void)lseek(log->fd, log->last_off, SEEK_SET);
-    if (read(log->fd, temp, 13) != 13 ||
-        memcmp(temp, "\001\000\000\377\377", 5) != 0) {
-        log_clean(log);
+    strcpy(log->path, path);
+    log->end = log->path + n;
+
+    /* gain exclusive access and verify log file -- may perform a
+       recovery operation if needed */
+    if (log_open(log)) {
+        free(log->path);
+        free(log);
         return NULL;
     }
-    log->crc = make_ulg(temp + 5);
-    log->len = make_ulg(temp + 9);
 
-    /* set up to write over empty last block */
-    (void)lseek(log->fd, log->last_off + 5, SEEK_SET);
-    log->stored = 0;
-    return (void *)log;
+    /* return pointer to log structure */
+    return log;
 }
 
-/* maximum amount to put in a stored block before starting a new one */
-#define MAX_BLOCK 16384
-
-/* write a block to a log object */
-int gzlog_write(void *obj, char *data, size_t len)
+/* gzlog_compress() return values:
+    0: all good
+   -1: file i/o error (usually access issue)
+   -2: memory allocation failure
+   -3: invalid log pointer argument */
+int gzlog_compress(gzlog *logd)
 {
-    size_t some;
-    unsigned char temp[5];
-    gz_log *log;
+    int fd, ret;
+    uint block;
+    size_t len, next;
+    unsigned char *data, buf[5];
+    struct log *log = logd;
 
-    /* check object */
-    log = (gz_log *)obj;
-    if (log == NULL || log->id != GZLOGID)
-        return 1;
+    /* check arguments */
+    if (log == NULL || strcmp(log->id, LOGID))
+        return -3;
 
-    /* write stored blocks until all of the input is written */
-    do {
-        some = MAX_BLOCK - log->stored;
-        if (some > len)
-            some = len;
-        if (write(log->fd, data, some) != some)
-            return 1;
-        log->crc = crc32(log->crc, data, some);
-        log->len += some;
-        len -= some;
-        data += some;
-        log->stored += some;
-
-        /* if the stored block is full, end it and start another */
-        if (log->stored == MAX_BLOCK) {
-            (void)lseek(log->fd, log->last_off, SEEK_SET);
-            temp[0] = 0;
-            dice_ulg(log->stored + ((unsigned long)(~log->stored) << 16),
-                     temp + 1);
-            if (write(log->fd, temp, 5) != 5)
-                return 1;
-            log->last_off = lseek(log->fd, log->stored, SEEK_CUR);
-            (void)lseek(log->fd, 5, SEEK_CUR);
-            log->stored = 0;
-        }
-    } while (len);
-    return 0;
-}
+    /* see if we lost the lock -- if so get it again and reload the extra
+       field information (it probably changed), recover last operation if
+       necessary */
+    if (log_check(log) && log_open(log))
+        return -1;
 
-/* recompress the remaining stored deflate data in place */
-local int recomp(gz_log *log)
-{
-    z_stream strm;
-    size_t len, max;
-    unsigned char *in;
-    unsigned char *out;
-    unsigned char temp[16];
-
-    /* allocate space and read it all in (it's around 1 MB) */
-    len = log->last_off - log->mark_off;
-    max = len + (len >> 12) + (len >> 14) + 11;
-    out = malloc(max);
-    if (out == NULL)
-        return 1;
-    in = malloc(len);
-    if (in == NULL) {
-        free(out);
-        return 1;
-    }
-    (void)lseek(log->fd, log->mark_off, SEEK_SET);
-    if (read(log->fd, in, len) != len) {
-        free(in);
-        free(out);
-        return 1;
-    }
+    /* create space for uncompressed data */
+    len = ((size_t)(log->last - log->first) & ~(((size_t)1 << 10) - 1)) +
+          log->stored;
+    if ((data = malloc(len)) == NULL)
+        return -2;
 
-    /* recompress in memory, decoding stored data as we go */
-    /* note: this assumes that unsigned is four bytes or more */
-    /*       consider not making that assumption */
-    strm.zalloc = Z_NULL;
-    strm.zfree = Z_NULL;
-    strm.opaque = Z_NULL;
-    if (deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, -15, 8,
-        Z_DEFAULT_STRATEGY) != Z_OK) {
-        free(in);
-        free(out);
-        return 1;
-    }
-    strm.next_in = in;
-    strm.avail_out = max;
-    strm.next_out = out;
-    while (len >= 5) {
-        if (strm.next_in[0] != 0)
+    /* do statement here is just a cheap trick for error handling */
+    do {
+        /* read in the uncompressed data */
+        if (lseek(log->fd, log->first - 1, SEEK_SET) < 0)
             break;
-        strm.avail_in = strm.next_in[1] + (strm.next_in[2] << 8);
-        strm.next_in += 5;
-        len -= 5;
-        if (strm.avail_in != 0) {
-            if (len < strm.avail_in)
+        next = 0;
+        while (next < len) {
+            if (read(log->fd, buf, 5) != 5)
                 break;
-            len -= strm.avail_in;
-            (void)deflate(&strm, Z_NO_FLUSH);
-            if (strm.avail_in != 0 || strm.avail_out == 0)
+            block = PULL2(buf + 1);
+            if (next + block > len ||
+                read(log->fd, (char *)data + next, block) != block)
                 break;
+            next += block;
         }
-    }
-    (void)deflate(&strm, Z_SYNC_FLUSH);
-    (void)deflateEnd(&strm);
-    free(in);
-    if (len != 0 || strm.avail_out == 0) {
-        free(out);
-        return 1;
-    }
+        if (lseek(log->fd, 0, SEEK_CUR) != log->last + 4 + log->stored)
+            break;
+        log_touch(log);
 
-    /* overwrite stored data with compressed data */
-    (void)lseek(log->fd, log->mark_off, SEEK_SET);
-    len = max - strm.avail_out;
-    if (write(log->fd, out, len) != len) {
-        free(out);
-        return 1;
-    }
-    free(out);
-
-    /* write last empty block, crc, and length */
-    log->mark_off = log->last_off = lseek(log->fd, 0, SEEK_CUR);
-    temp[0] = 1;
-    dice_ulg(0xffffL << 16, temp + 1);
-    dice_ulg(log->crc, temp + 5);
-    dice_ulg(log->len, temp + 9);
-    if (write(log->fd, temp, 13) != 13)
-        return 1;
+        /* write the uncompressed data to the .add file */
+        strcpy(log->end, ".add");
+        fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+        if (fd < 0)
+            break;
+        ret = (size_t)write(fd, data, len) != len;
+        if (ret | close(fd))
+            break;
+        log_touch(log);
 
-    /* truncate file to discard remaining stored data and old trailer */
-    ftruncate(log->fd, lseek(log->fd, 0, SEEK_CUR));
+        /* write the dictionary for the next compress to the .temp file */
+        strcpy(log->end, ".temp");
+        fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+        if (fd < 0)
+            break;
+        next = DICT > len ? len : DICT;
+        ret = (size_t)write(fd, (char *)data + len - next, next) != next;
+        if (ret | close(fd))
+            break;
+        log_touch(log);
 
-    /* update extra field to point to new last empty block */
-    (void)lseek(log->fd, log->extra, SEEK_SET);
-    dice_off(log->mark_off, temp);
-    dice_off(log->last_off, temp + 8);
-    if (write(log->fd, temp, 16) != 16)
-        return 1;
-    return 0;
-}
+        /* roll back to compressed data, mark the compress in progress */
+        log->last = log->first;
+        log->stored = 0;
+        if (log_mark(log, COMPRESS_OP))
+            break;
+        BAIL(7);
+
+        /* compress and append the data (clears mark) */
+        ret = log_compress(log, data, len);
+        free(data);
+        return ret;
+    } while (0);
 
-/* maximum accumulation of stored blocks before compressing */
-#define MAX_STORED 1048576
+    /* broke out of do above on i/o error */
+    free(data);
+    return -1;
+}
 
-/* close log object */
-int gzlog_close(void *obj)
+/* gzlog_write() return values:
+    0: all good
+   -1: file i/o error (usually access issue)
+   -2: memory allocation failure
+   -3: invalid log pointer argument */
+int gzlog_write(gzlog *logd, void *data, size_t len)
 {
-    unsigned char temp[8];
-    gz_log *log;
+    int fd, ret;
+    struct log *log = logd;
 
-    /* check object */
-    log = (gz_log *)obj;
-    if (log == NULL || log->id != GZLOGID)
-        return 1;
+    /* check arguments */
+    if (log == NULL || strcmp(log->id, LOGID))
+        return -3;
+    if (data == NULL || len <= 0)
+        return 0;
 
-    /* go to start of most recent block being written */
-    (void)lseek(log->fd, log->last_off, SEEK_SET);
-
-    /* if some stuff was put there, update block */
-    if (log->stored) {
-        temp[0] = 0;
-        dice_ulg(log->stored + ((unsigned long)(~log->stored) << 16),
-                 temp + 1);
-        if (write(log->fd, temp, 5) != 5)
-            return 1;
-        log->last_off = lseek(log->fd, log->stored, SEEK_CUR);
-    }
+    /* see if we lost the lock -- if so get it again and reload the extra
+       field information (it probably changed), recover last operation if
+       necessary */
+    if (log_check(log) && log_open(log))
+        return -1;
 
-    /* write last block (empty) */
-    if (write(log->fd, "\001\000\000\377\377", 5) != 5)
-        return 1;
+    /* create and write .add file */
+    strcpy(log->end, ".add");
+    fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+    if (fd < 0)
+        return -1;
+    ret = (size_t)write(fd, data, len) != len;
+    if (ret | close(fd))
+        return -1;
+    log_touch(log);
 
-    /* write updated crc and uncompressed length */
-    dice_ulg(log->crc, temp);
-    dice_ulg(log->len, temp + 4);
-    if (write(log->fd, temp, 8) != 8)
-        return 1;
+    /* mark log file with append in progress */
+    if (log_mark(log, APPEND_OP))
+        return -1;
+    BAIL(8);
 
-    /* put offset of that last block in gzip extra block */
-    (void)lseek(log->fd, log->extra + 8, SEEK_SET);
-    dice_off(log->last_off, temp);
-    if (write(log->fd, temp, 8) != 8)
-        return 1;
+    /* append data (clears mark) */
+    if (log_append(log, data, len))
+        return -1;
 
-    /* if more than 1 MB stored, then time to compress it */
-    if (log->last_off - log->mark_off > MAX_STORED) {
-        if (recomp(log))
-            return 1;
-    }
+    /* check to see if it's time to compress -- if not, then done */
+    if (((log->last - log->first) >> 10) + (log->stored >> 10) < TRIGGER)
+        return 0;
+
+    /* time to compress */
+    return gzlog_compress(log);
+}
+
+/* gzlog_close() return values:
+    0: ok
+   -3: invalid log pointer argument */
+int gzlog_close(gzlog *logd)
+{
+    struct log *log = logd;
 
-    /* unlock and close file */
-    log_clean(log);
+    /* check arguments */
+    if (log == NULL || strcmp(log->id, LOGID))
+        return -3;
+
+    /* close the log file and release the lock */
+    log_close(log);
+
+    /* free structure and return */
+    if (log->path != NULL)
+        free(log->path);
+    strcpy(log->id, "bad");
+    free(log);
     return 0;
 }
diff --git a/third_party/zlib/examples/gzlog.h b/third_party/zlib/examples/gzlog.h
index a800bd5..86f0cec 100644
--- a/third_party/zlib/examples/gzlog.h
+++ b/third_party/zlib/examples/gzlog.h
@@ -1,6 +1,6 @@
 /* gzlog.h
-  Copyright (C) 2004 Mark Adler, all rights reserved
-  version 1.0, 26 Nov 2004
+  Copyright (C) 2004, 2008, 2012 Mark Adler, all rights reserved
+  version 2.2, 14 Aug 2012
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the author be held liable for any damages
@@ -21,38 +21,71 @@
   Mark Adler    madler at alumni.caltech.edu
  */
 
+/* Version History:
+   1.0  26 Nov 2004  First version
+   2.0  25 Apr 2008  Complete redesign for recovery of interrupted operations
+                     Interface changed slightly in that now path is a prefix
+                     Compression now occurs as needed during gzlog_write()
+                     gzlog_write() now always leaves the log file as valid gzip
+   2.1   8 Jul 2012  Fix argument checks in gzlog_compress() and gzlog_write()
+   2.2  14 Aug 2012  Clean up signed comparisons
+ */
+
 /*
    The gzlog object allows writing short messages to a gzipped log file,
    opening the log file locked for small bursts, and then closing it.  The log
-   object works by appending stored data to the gzip file until 1 MB has been
-   accumulated.  At that time, the stored data is compressed, and replaces the
-   uncompressed data in the file.  The log file is truncated to its new size at
-   that time.  After closing, the log file is always valid gzip file that can
-   decompressed to recover what was written.
-
-   A gzip header "extra" field contains two file offsets for appending.  The
-   first points to just after the last compressed data.  The second points to
-   the last stored block in the deflate stream, which is empty.  All of the
-   data between those pointers is uncompressed.
+   object works by appending stored (uncompressed) data to the gzip file until
+   1 MB has been accumulated.  At that time, the stored data is compressed, and
+   replaces the uncompressed data in the file.  The log file is truncated to
+   its new size at that time.  After each write operation, the log file is a
+   valid gzip file that can decompressed to recover what was written.
+
+   The gzlog operations can be interupted at any point due to an application or
+   system crash, and the log file will be recovered the next time the log is
+   opened with gzlog_open().
  */
 
+#ifndef GZLOG_H
+#define GZLOG_H
+
+/* gzlog object type */
+typedef void gzlog;
+
 /* Open a gzlog object, creating the log file if it does not exist.  Return
-   NULL on error.  Note that gzlog_open() could take a long time to return if
-   there is difficulty in locking the file. */
-void *gzlog_open(char *path);
-
-/* Write to a gzlog object.  Return non-zero on error.  This function will
-   simply write data to the file uncompressed.  Compression of the data
-   will not occur until gzlog_close() is called.  It is expected that
-   gzlog_write() is used for a short message, and then gzlog_close() is
-   called.  If a large amount of data is to be written, then the application
-   should write no more than 1 MB at a time with gzlog_write() before
-   calling gzlog_close() and then gzlog_open() again. */
-int gzlog_write(void *log, char *data, size_t len);
-
-/* Close a gzlog object.  Return non-zero on error.  The log file is locked
-   until this function is called.  This function will compress stored data
-   at the end of the gzip file if at least 1 MB has been accumulated.  Note
-   that the file will not be a valid gzip file until this function completes.
- */
-int gzlog_close(void *log);
+   NULL on error.  Note that gzlog_open() could take a while to complete if it
+   has to wait to verify that a lock is stale (possibly for five minutes), or
+   if there is significant contention with other instantiations of this object
+   when locking the resource.  path is the prefix of the file names created by
+   this object.  If path is "foo", then the log file will be "foo.gz", and
+   other auxiliary files will be created and destroyed during the process:
+   "foo.dict" for a compression dictionary, "foo.temp" for a temporary (next)
+   dictionary, "foo.add" for data being added or compressed, "foo.lock" for the
+   lock file, and "foo.repairs" to log recovery operations performed due to
+   interrupted gzlog operations.  A gzlog_open() followed by a gzlog_close()
+   will recover a previously interrupted operation, if any. */
+gzlog *gzlog_open(char *path);
+
+/* Write to a gzlog object.  Return zero on success, -1 if there is a file i/o
+   error on any of the gzlog files (this should not happen if gzlog_open()
+   succeeded, unless the device has run out of space or leftover auxiliary
+   files have permissions or ownership that prevent their use), -2 if there is
+   a memory allocation failure, or -3 if the log argument is invalid (e.g. if
+   it was not created by gzlog_open()).  This function will write data to the
+   file uncompressed, until 1 MB has been accumulated, at which time that data
+   will be compressed.  The log file will be a valid gzip file upon successful
+   return. */
+int gzlog_write(gzlog *log, void *data, size_t len);
+
+/* Force compression of any uncompressed data in the log.  This should be used
+   sparingly, if at all.  The main application would be when a log file will
+   not be appended to again.  If this is used to compress frequently while
+   appending, it will both significantly increase the execution time and
+   reduce the compression ratio.  The return codes are the same as for
+   gzlog_write(). */
+int gzlog_compress(gzlog *log);
+
+/* Close a gzlog object.  Return zero on success, -3 if the log argument is
+   invalid.  The log object is freed, and so cannot be referenced again. */
+int gzlog_close(gzlog *log);
+
+#endif
diff --git a/third_party/zlib/examples/zlib_how.html b/third_party/zlib/examples/zlib_how.html
index 40998db..444ff1c 100644
--- a/third_party/zlib/examples/zlib_how.html
+++ b/third_party/zlib/examples/zlib_how.html
@@ -4,7 +4,7 @@
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <title>zlib Usage Example</title>
-<!--  Copyright (c) 2004 Mark Adler.  -->
+<!--  Copyright (c) 2004, 2005 Mark Adler.  -->
 </head>
 <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#00A000">
 <h2 align="center"> zlib Usage Example </h2>
@@ -21,13 +21,16 @@ Without further adieu, here is the program <a href="zpipe.c"><tt>zpipe.c</tt></a
 <pre><b>
 /* zpipe.c: example of proper use of zlib's inflate() and deflate()
    Not copyrighted -- provided to the public domain
-   Version 1.2  9 November 2004  Mark Adler */
+   Version 1.4  11 December 2005  Mark Adler */
 
 /* Version history:
    1.0  30 Oct 2004  First version
    1.1   8 Nov 2004  Add void casting for unused return values
                      Use switch statement for inflate() return values
    1.2   9 Nov 2004  Add assertions to document zlib guarantees
+   1.3   6 Apr 2005  Remove incorrect assertion in inf()
+   1.4  11 Dec 2005  Add hack to avoid MSDOS end-of-line conversions
+                     Avoid some compiler warnings for input and output buffers
  */
 </b></pre><!-- -->
 We now include the header files for the required definitions.  From
@@ -47,6 +50,21 @@ functions <tt>inflateInit()</tt>, <tt>inflate()</tt>, and
 #include <assert.h>
 #include "zlib.h"
 </b></pre><!-- -->
+This is an ugly hack required to avoid corruption of the input and output data on
+Windows/MS-DOS systems.  Without this, those systems would assume that the input and output
+files are text, and try to convert the end-of-line characters from one standard to
+another.  That would corrupt binary data, and in particular would render the compressed data unusable.
+This sets the input and output to binary which suppresses the end-of-line conversions.
+<tt>SET_BINARY_MODE()</tt> will be used later on <tt>stdin</tt> and <tt>stdout</tt>, at the beginning of <tt>main()</tt>.
+<pre><b>
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
+#  include <fcntl.h>
+#  include <io.h>
+#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+#  define SET_BINARY_MODE(file)
+#endif
+</b></pre><!-- -->
 <tt>CHUNK</tt> is simply the buffer size for feeding data to and pulling data
 from the <em>zlib</em> routines.  Larger buffer sizes would be more efficient,
 especially for <tt>inflate()</tt>.  If the memory is available, buffers sizes
@@ -80,8 +98,8 @@ is used to pass information to and from the <em>zlib</em> routines, and to maint
     int ret, flush;
     unsigned have;
     z_stream strm;
-    char in[CHUNK];
-    char out[CHUNK];
+    unsigned char in[CHUNK];
+    unsigned char out[CHUNK];
 </b></pre><!-- -->
 The first thing we do is to initialize the <em>zlib</em> state for compression using
 <tt>deflateInit()</tt>.  This must be done before the first use of <tt>deflate()</tt>.
@@ -313,8 +331,8 @@ can tell from the <em>zlib</em> stream itself when the stream is complete.
     int ret;
     unsigned have;
     z_stream strm;
-    char in[CHUNK];
-    char out[CHUNK];
+    unsigned char in[CHUNK];
+    unsigned char out[CHUNK];
 </b></pre><!-- -->
 The initialization of the state is the same, except that there is no compression level,
 of course, and two more elements of the structure are initialized.  <tt>avail_in</tt>
@@ -494,6 +512,10 @@ int main(int argc, char **argv)
 {
     int ret;
 
+    /* avoid end-of-line conversions */
+    SET_BINARY_MODE(stdin);
+    SET_BINARY_MODE(stdout);
+
     /* do compression if no arguments */
     if (argc == 1) {
         ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
@@ -518,6 +540,6 @@ int main(int argc, char **argv)
 }
 </b></pre>
 <hr>
-<i>Copyright (c) 2004 by Mark Adler<br>Last modified 13 November 2004</i>
+<i>Copyright (c) 2004, 2005 by Mark Adler<br>Last modified 11 December 2005</i>
 </body>
 </html>
diff --git a/third_party/zlib/examples/zpipe.c b/third_party/zlib/examples/zpipe.c
index 26abb56..83535d1 100644
--- a/third_party/zlib/examples/zpipe.c
+++ b/third_party/zlib/examples/zpipe.c
@@ -1,6 +1,6 @@
 /* zpipe.c: example of proper use of zlib's inflate() and deflate()
    Not copyrighted -- provided to the public domain
-   Version 1.2  9 November 2004  Mark Adler */
+   Version 1.4  11 December 2005  Mark Adler */
 
 /* Version history:
    1.0  30 Oct 2004  First version
@@ -8,6 +8,8 @@
                      Use switch statement for inflate() return values
    1.2   9 Nov 2004  Add assertions to document zlib guarantees
    1.3   6 Apr 2005  Remove incorrect assertion in inf()
+   1.4  11 Dec 2005  Add hack to avoid MSDOS end-of-line conversions
+                     Avoid some compiler warnings for input and output buffers
  */
 
 #include <stdio.h>
@@ -15,6 +17,14 @@
 #include <assert.h>
 #include "zlib.h"
 
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
+#  include <fcntl.h>
+#  include <io.h>
+#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+#  define SET_BINARY_MODE(file)
+#endif
+
 #define CHUNK 16384
 
 /* Compress from file source to file dest until EOF on source.
@@ -28,8 +38,8 @@ int def(FILE *source, FILE *dest, int level)
     int ret, flush;
     unsigned have;
     z_stream strm;
-    char in[CHUNK];
-    char out[CHUNK];
+    unsigned char in[CHUNK];
+    unsigned char out[CHUNK];
 
     /* allocate deflate state */
     strm.zalloc = Z_NULL;
@@ -84,8 +94,8 @@ int inf(FILE *source, FILE *dest)
     int ret;
     unsigned have;
     z_stream strm;
-    char in[CHUNK];
-    char out[CHUNK];
+    unsigned char in[CHUNK];
+    unsigned char out[CHUNK];
 
     /* allocate inflate state */
     strm.zalloc = Z_NULL;
@@ -167,6 +177,10 @@ int main(int argc, char **argv)
 {
     int ret;
 
+    /* avoid end-of-line conversions */
+    SET_BINARY_MODE(stdin);
+    SET_BINARY_MODE(stdout);
+
     /* do compression if no arguments */
     if (argc == 1) {
         ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
diff --git a/third_party/zlib/examples/zran.c b/third_party/zlib/examples/zran.c
index 8c7717e..278f9ad 100644
--- a/third_party/zlib/examples/zran.c
+++ b/third_party/zlib/examples/zran.c
@@ -1,7 +1,12 @@
 /* zran.c -- example of zlib/gzip stream indexing and random access
- * Copyright (C) 2005 Mark Adler
+ * Copyright (C) 2005, 2012 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
-   Version 1.0  29 May 2005  Mark Adler */
+   Version 1.1  29 Sep 2012  Mark Adler */
+
+/* Version History:
+ 1.0  29 May 2005  First version
+ 1.1  29 Sep 2012  Fix memory reallocation error
+ */
 
 /* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary()
    for random access of a compressed file.  A file containing a zlib or gzip
@@ -221,7 +226,7 @@ local int build_index(FILE *in, off_t span, struct access **built)
 
     /* clean up and return index (release unused entries in list) */
     (void)inflateEnd(&strm);
-    index = realloc(index, sizeof(struct point) * index->have);
+    index->list = realloc(index->list, sizeof(struct point) * index->have);
     index->size = index->have;
     *built = index;
     return index->size;
@@ -351,7 +356,7 @@ int main(int argc, char **argv)
     int len;
     off_t offset;
     FILE *in;
-    struct access *index;
+    struct access *index = NULL;
     unsigned char buf[CHUNK];
 
     /* open input file */
diff --git a/third_party/zlib/gzio.c b/third_party/zlib/gzio.c
deleted file mode 100644
index 55521a3..0000000
--- a/third_party/zlib/gzio.c
+++ /dev/null
@@ -1,1024 +0,0 @@
-/* gzio.c -- IO on .gz files
- * Copyright (C) 1995-2005 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- *
- * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
- */
-
-/* @(#) $Id$ */
-
-#include "zutil.h"
-
-#ifdef NO_DEFLATE       /* for compatibility with old definition */
-#  define NO_GZCOMPRESS
-#endif
-
-#ifndef NO_DUMMY_DECL
-struct internal_state {int dummy;}; /* for buggy compilers */
-#endif
-
-#ifndef Z_BUFSIZE
-#  ifdef MAXSEG_64K
-#    define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
-#  else
-#    define Z_BUFSIZE 16384
-#  endif
-#endif
-#ifndef Z_PRINTF_BUFSIZE
-#  define Z_PRINTF_BUFSIZE 4096
-#endif
-
-#ifdef __MVS__
-#  pragma map (fdopen , "\174\174FDOPEN")
-   FILE *fdopen(int, const char *);
-#endif
-
-#ifndef STDC
-extern voidp  malloc OF((uInt size));
-extern void   free   OF((voidpf ptr));
-#endif
-
-#define ALLOC(size) malloc(size)
-#define TRYFREE(p) {if (p) free(p);}
-
-static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
-
-/* gzip flag byte */
-/*#define ASCII_FLAG   0x01 *//* bit 0 set: file probably ascii text */
-#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
-#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
-#define COMMENT      0x10 /* bit 4 set: file comment present */
-#define RESERVED     0xE0 /* bits 5..7: reserved */
-
-typedef struct gz_stream {
-    z_stream stream;
-    int      z_err;   /* error code for last stream operation */
-    int      z_eof;   /* set if end of input file */
-    FILE     *file;   /* .gz file */
-    Byte     *inbuf;  /* input buffer */
-    Byte     *outbuf; /* output buffer */
-    uLong    crc;     /* crc32 of uncompressed data */
-    char     *msg;    /* error message */
-    char     *path;   /* path name for debugging only */
-    int      transparent; /* 1 if input file is not a .gz file */
-    char     mode;    /* 'w' or 'r' */
-    z_off_t  start;   /* start of compressed data in file (header skipped) */
-    z_off_t  in;      /* bytes into deflate or inflate */
-    z_off_t  out;     /* bytes out of deflate or inflate */
-    int      back;    /* one character push-back */
-    int      last;    /* true if push-back is last character */
-} gz_stream;
-
-
-local gzFile gz_open      OF((const char *path, const char *mode, int  fd));
-local int do_flush        OF((gzFile file, int flush));
-local int    get_byte     OF((gz_stream *s));
-local void   check_header OF((gz_stream *s));
-local int    destroy      OF((gz_stream *s));
-local void   putLong      OF((FILE *file, uLong x));
-local uLong  getLong      OF((gz_stream *s));
-
-/* ===========================================================================
-     Opens a gzip (.gz) file for reading or writing. The mode parameter
-   is as in fopen ("rb" or "wb"). The file is given either by file descriptor
-   or path name (if fd == -1).
-     gz_open returns NULL if the file could not be opened or if there was
-   insufficient memory to allocate the (de)compression state; errno
-   can be checked to distinguish the two cases (if errno is zero, the
-   zlib error is Z_MEM_ERROR).
-*/
-local gzFile gz_open (path, mode, fd)
-    const char *path;
-    const char *mode;
-    int  fd;
-{
-    int err;
-    int level = Z_DEFAULT_COMPRESSION; /* compression level */
-    int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
-    const char *p = mode;
-    gz_stream *s;
-    char fmode[80]; /* copy of mode, without the compression level */
-    char *m = fmode;
-
-    if (!path || !mode) return Z_NULL;
-
-    s = (gz_stream *)ALLOC(sizeof(gz_stream));
-    if (!s) return Z_NULL;
-
-    s->stream.zalloc = (alloc_func)0;
-    s->stream.zfree = (free_func)0;
-    s->stream.opaque = (voidpf)0;
-    s->stream.next_in = s->inbuf = Z_NULL;
-    s->stream.next_out = s->outbuf = Z_NULL;
-    s->stream.avail_in = s->stream.avail_out = 0;
-    s->file = NULL;
-    s->z_err = Z_OK;
-    s->z_eof = 0;
-    s->in = 0;
-    s->out = 0;
-    s->back = EOF;
-    s->crc = crc32(0L, Z_NULL, 0);
-    s->msg = NULL;
-    s->transparent = 0;
-
-    s->path = (char*)ALLOC(strlen(path)+1);
-    if (s->path == NULL) {
-        return destroy(s), (gzFile)Z_NULL;
-    }
-    strcpy(s->path, path); /* do this early for debugging */
-
-    s->mode = '\0';
-    do {
-        if (*p == 'r') s->mode = 'r';
-        if (*p == 'w' || *p == 'a') s->mode = 'w';
-        if (*p >= '0' && *p <= '9') {
-            level = *p - '0';
-        } else if (*p == 'f') {
-          strategy = Z_FILTERED;
-        } else if (*p == 'h') {
-          strategy = Z_HUFFMAN_ONLY;
-        } else if (*p == 'R') {
-          strategy = Z_RLE;
-        } else {
-            *m++ = *p; /* copy the mode */
-        }
-    } while (*p++ && m != fmode + sizeof(fmode));
-    if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
-
-    if (s->mode == 'w') {
-#ifdef NO_GZCOMPRESS
-        err = Z_STREAM_ERROR;
-#else
-        err = deflateInit2(&(s->stream), level,
-                           Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
-        /* windowBits is passed < 0 to suppress zlib header */
-
-        s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
-#endif
-        if (err != Z_OK || s->outbuf == Z_NULL) {
-            return destroy(s), (gzFile)Z_NULL;
-        }
-    } else {
-        s->stream.next_in  = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
-
-        err = inflateInit2(&(s->stream), -MAX_WBITS);
-        /* windowBits is passed < 0 to tell that there is no zlib header.
-         * Note that in this case inflate *requires* an extra "dummy" byte
-         * after the compressed stream in order to complete decompression and
-         * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
-         * present after the compressed stream.
-         */
-        if (err != Z_OK || s->inbuf == Z_NULL) {
-            return destroy(s), (gzFile)Z_NULL;
-        }
-    }
-    s->stream.avail_out = Z_BUFSIZE;
-
-    errno = 0;
-    s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
-
-    if (s->file == NULL) {
-        return destroy(s), (gzFile)Z_NULL;
-    }
-    if (s->mode == 'w') {
-        /* Write a very simple .gz header:
-         */
-        fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
-             Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
-        s->start = 10L;
-        /* We use 10L instead of ftell(s->file) to because ftell causes an
-         * fflush on some systems. This version of the library doesn't use
-         * start anyway in write mode, so this initialization is not
-         * necessary.
-         */
-    } else {
-        check_header(s); /* skip the .gz header */
-        s->start = ftell(s->file) - s->stream.avail_in;
-    }
-
-    return (gzFile)s;
-}
-
-/* ===========================================================================
-     Opens a gzip (.gz) file for reading or writing.
-*/
-gzFile ZEXPORT gzopen (path, mode)
-    const char *path;
-    const char *mode;
-{
-    return gz_open (path, mode, -1);
-}
-
-/* ===========================================================================
-     Associate a gzFile with the file descriptor fd. fd is not dup'ed here
-   to mimic the behavio(u)r of fdopen.
-*/
-gzFile ZEXPORT gzdopen (fd, mode)
-    int fd;
-    const char *mode;
-{
-    char name[46];      /* allow for up to 128-bit integers */
-
-    if (fd < 0) return (gzFile)Z_NULL;
-    sprintf(name, "<fd:%d>", fd); /* for debugging */
-
-    return gz_open (name, mode, fd);
-}
-
-/* ===========================================================================
- * Update the compression level and strategy
- */
-int ZEXPORT gzsetparams (file, level, strategy)
-    gzFile file;
-    int level;
-    int strategy;
-{
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
-
-    /* Make room to allow flushing */
-    if (s->stream.avail_out == 0) {
-
-        s->stream.next_out = s->outbuf;
-        if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
-            s->z_err = Z_ERRNO;
-        }
-        s->stream.avail_out = Z_BUFSIZE;
-    }
-
-    return deflateParams (&(s->stream), level, strategy);
-}
-
-/* ===========================================================================
-     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
-   for end of file.
-   IN assertion: the stream s has been successfully opened for reading.
-*/
-local int get_byte(s)
-    gz_stream *s;
-{
-    if (s->z_eof) return EOF;
-    if (s->stream.avail_in == 0) {
-        errno = 0;
-        s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
-        if (s->stream.avail_in == 0) {
-            s->z_eof = 1;
-            if (ferror(s->file)) s->z_err = Z_ERRNO;
-            return EOF;
-        }
-        s->stream.next_in = s->inbuf;
-    }
-    s->stream.avail_in--;
-    return *(s->stream.next_in)++;
-}
-
-/* ===========================================================================
-      Check the gzip header of a gz_stream opened for reading. Set the stream
-    mode to transparent if the gzip magic header is not present; set s->err
-    to Z_DATA_ERROR if the magic header is present but the rest of the header
-    is incorrect.
-    IN assertion: the stream s has already been created successfully;
-       s->stream.avail_in is zero for the first time, but may be non-zero
-       for concatenated .gz files.
-*/
-local void check_header(s)
-    gz_stream *s;
-{
-    int method; /* method byte */
-    int flags;  /* flags byte */
-    uInt len;
-    int c;
-
-    /* Assure two bytes in the buffer so we can peek ahead -- handle case
-       where first byte of header is at the end of the buffer after the last
-       gzip segment */
-    len = s->stream.avail_in;
-    if (len < 2) {
-        if (len) s->inbuf[0] = s->stream.next_in[0];
-        errno = 0;
-        len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
-        if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
-        s->stream.avail_in += len;
-        s->stream.next_in = s->inbuf;
-        if (s->stream.avail_in < 2) {
-            s->transparent = s->stream.avail_in;
-            return;
-        }
-    }
-
-    /* Peek ahead to check the gzip magic header */
-    if (s->stream.next_in[0] != gz_magic[0] ||
-        s->stream.next_in[1] != gz_magic[1]) {
-        s->transparent = 1;
-        return;
-    }
-    s->stream.avail_in -= 2;
-    s->stream.next_in += 2;
-
-    /* Check the rest of the gzip header */
-    method = get_byte(s);
-    flags = get_byte(s);
-    if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
-        s->z_err = Z_DATA_ERROR;
-        return;
-    }
-
-    /* Discard time, xflags and OS code: */
-    for (len = 0; len < 6; len++) (void)get_byte(s);
-
-    if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
-        len  =  (uInt)get_byte(s);
-        len += ((uInt)get_byte(s))<<8;
-        /* len is garbage if EOF but the loop below will quit anyway */
-        while (len-- != 0 && get_byte(s) != EOF) ;
-    }
-    if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
-        while ((c = get_byte(s)) != 0 && c != EOF) ;
-    }
-    if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
-        while ((c = get_byte(s)) != 0 && c != EOF) ;
-    }
-    if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
-        for (len = 0; len < 2; len++) (void)get_byte(s);
-    }
-    s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
-}
-
- /* ===========================================================================
- * Cleanup then free the given gz_stream. Return a zlib error code.
-   Try freeing in the reverse order of allocations.
- */
-local int destroy (s)
-    gz_stream *s;
-{
-    int err = Z_OK;
-
-    if (!s) return Z_STREAM_ERROR;
-
-    TRYFREE(s->msg);
-
-    if (s->stream.state != NULL) {
-        if (s->mode == 'w') {
-#ifdef NO_GZCOMPRESS
-            err = Z_STREAM_ERROR;
-#else
-            err = deflateEnd(&(s->stream));
-#endif
-        } else if (s->mode == 'r') {
-            err = inflateEnd(&(s->stream));
-        }
-    }
-    if (s->file != NULL && fclose(s->file)) {
-#ifdef ESPIPE
-        if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
-#endif
-            err = Z_ERRNO;
-    }
-    if (s->z_err < 0) err = s->z_err;
-
-    TRYFREE(s->inbuf);
-    TRYFREE(s->outbuf);
-    TRYFREE(s->path);
-    TRYFREE(s);
-    return err;
-}
-
-/* ===========================================================================
-     Reads the given number of uncompressed bytes from the compressed file.
-   gzread returns the number of bytes actually read (0 for end of file).
-*/
-int ZEXPORT gzread (file, buf, len)
-    gzFile file;
-    voidp buf;
-    unsigned len;
-{
-    gz_stream *s = (gz_stream*)file;
-    Bytef *start = (Bytef*)buf; /* starting point for crc computation */
-    Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
-
-    if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
-
-    if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
-    if (s->z_err == Z_STREAM_END) return 0;  /* EOF */
-
-    next_out = (Byte*)buf;
-    s->stream.next_out = (Bytef*)buf;
-    s->stream.avail_out = len;
-
-    if (s->stream.avail_out && s->back != EOF) {
-        *next_out++ = s->back;
-        s->stream.next_out++;
-        s->stream.avail_out--;
-        s->back = EOF;
-        s->out++;
-        start++;
-        if (s->last) {
-            s->z_err = Z_STREAM_END;
-            return 1;
-        }
-    }
-
-    while (s->stream.avail_out != 0) {
-
-        if (s->transparent) {
-            /* Copy first the lookahead bytes: */
-            uInt n = s->stream.avail_in;
-            if (n > s->stream.avail_out) n = s->stream.avail_out;
-            if (n > 0) {
-                zmemcpy(s->stream.next_out, s->stream.next_in, n);
-                next_out += n;
-                s->stream.next_out = next_out;
-                s->stream.next_in   += n;
-                s->stream.avail_out -= n;
-                s->stream.avail_in  -= n;
-            }
-            if (s->stream.avail_out > 0) {
-                s->stream.avail_out -=
-                    (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
-            }
-            len -= s->stream.avail_out;
-            s->in  += len;
-            s->out += len;
-            if (len == 0) s->z_eof = 1;
-            return (int)len;
-        }
-        if (s->stream.avail_in == 0 && !s->z_eof) {
-
-            errno = 0;
-            s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
-            if (s->stream.avail_in == 0) {
-                s->z_eof = 1;
-                if (ferror(s->file)) {
-                    s->z_err = Z_ERRNO;
-                    break;
-                }
-            }
-            s->stream.next_in = s->inbuf;
-        }
-        s->in += s->stream.avail_in;
-        s->out += s->stream.avail_out;
-        s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
-        s->in -= s->stream.avail_in;
-        s->out -= s->stream.avail_out;
-
-        if (s->z_err == Z_STREAM_END) {
-            /* Check CRC and original size */
-            s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
-            start = s->stream.next_out;
-
-            if (getLong(s) != s->crc) {
-                s->z_err = Z_DATA_ERROR;
-            } else {
-                (void)getLong(s);
-                /* The uncompressed length returned by above getlong() may be
-                 * different from s->out in case of concatenated .gz files.
-                 * Check for such files:
-                 */
-                check_header(s);
-                if (s->z_err == Z_OK) {
-                    inflateReset(&(s->stream));
-                    s->crc = crc32(0L, Z_NULL, 0);
-                }
-            }
-        }
-        if (s->z_err != Z_OK || s->z_eof) break;
-    }
-    s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
-
-    if (len == s->stream.avail_out &&
-        (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
-        return -1;
-    return (int)(len - s->stream.avail_out);
-}
-
-
-/* ===========================================================================
-      Reads one byte from the compressed file. gzgetc returns this byte
-   or -1 in case of end of file or error.
-*/
-int ZEXPORT gzgetc(file)
-    gzFile file;
-{
-    unsigned char c;
-
-    return gzread(file, &c, 1) == 1 ? c : -1;
-}
-
-
-/* ===========================================================================
-      Push one byte back onto the stream.
-*/
-int ZEXPORT gzungetc(c, file)
-    int c;
-    gzFile file;
-{
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
-    s->back = c;
-    s->out--;
-    s->last = (s->z_err == Z_STREAM_END);
-    if (s->last) s->z_err = Z_OK;
-    s->z_eof = 0;
-    return c;
-}
-
-
-/* ===========================================================================
-      Reads bytes from the compressed file until len-1 characters are
-   read, or a newline character is read and transferred to buf, or an
-   end-of-file condition is encountered.  The string is then terminated
-   with a null character.
-      gzgets returns buf, or Z_NULL in case of error.
-
-      The current implementation is not optimized at all.
-*/
-char * ZEXPORT gzgets(file, buf, len)
-    gzFile file;
-    char *buf;
-    int len;
-{
-    char *b = buf;
-    if (buf == Z_NULL || len <= 0) return Z_NULL;
-
-    while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
-    *buf = '\0';
-    return b == buf && len > 0 ? Z_NULL : b;
-}
-
-
-#ifndef NO_GZCOMPRESS
-/* ===========================================================================
-     Writes the given number of uncompressed bytes into the compressed file.
-   gzwrite returns the number of bytes actually written (0 in case of error).
-*/
-int ZEXPORT gzwrite (file, buf, len)
-    gzFile file;
-    voidpc buf;
-    unsigned len;
-{
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
-
-    s->stream.next_in = (const Bytef*)buf;
-    s->stream.avail_in = len;
-
-    while (s->stream.avail_in != 0) {
-
-        if (s->stream.avail_out == 0) {
-
-            s->stream.next_out = s->outbuf;
-            if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
-                s->z_err = Z_ERRNO;
-                break;
-            }
-            s->stream.avail_out = Z_BUFSIZE;
-        }
-        s->in += s->stream.avail_in;
-        s->out += s->stream.avail_out;
-        s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
-        s->in -= s->stream.avail_in;
-        s->out -= s->stream.avail_out;
-        if (s->z_err != Z_OK) break;
-    }
-    s->crc = crc32(s->crc, (const Bytef *)buf, len);
-
-    return (int)(len - s->stream.avail_in);
-}
-
-
-/* ===========================================================================
-     Converts, formats, and writes the args to the compressed file under
-   control of the format string, as in fprintf. gzprintf returns the number of
-   uncompressed bytes actually written (0 in case of error).
-*/
-#ifdef STDC
-#include <stdarg.h>
-
-int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
-{
-    char buf[Z_PRINTF_BUFSIZE];
-    va_list va;
-    int len;
-
-    buf[sizeof(buf) - 1] = 0;
-    va_start(va, format);
-#ifdef NO_vsnprintf
-#  ifdef HAS_vsprintf_void
-    (void)vsprintf(buf, format, va);
-    va_end(va);
-    for (len = 0; len < sizeof(buf); len++)
-        if (buf[len] == 0) break;
-#  else
-    len = vsprintf(buf, format, va);
-    va_end(va);
-#  endif
-#else
-#  ifdef HAS_vsnprintf_void
-    (void)vsnprintf(buf, sizeof(buf), format, va);
-    va_end(va);
-    len = strlen(buf);
-#  else
-    len = vsnprintf(buf, sizeof(buf), format, va);
-    va_end(va);
-#  endif
-#endif
-    if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0)
-        return 0;
-    return gzwrite(file, buf, (unsigned)len);
-}
-#else /* not ANSI C */
-
-int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
-                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
-    gzFile file;
-    const char *format;
-    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
-        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
-{
-    char buf[Z_PRINTF_BUFSIZE];
-    int len;
-
-    buf[sizeof(buf) - 1] = 0;
-#ifdef NO_snprintf
-#  ifdef HAS_sprintf_void
-    sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
-            a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
-    for (len = 0; len < sizeof(buf); len++)
-        if (buf[len] == 0) break;
-#  else
-    len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
-                a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
-#  endif
-#else
-#  ifdef HAS_snprintf_void
-    snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
-             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
-    len = strlen(buf);
-#  else
-    len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
-                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
-#  endif
-#endif
-    if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
-        return 0;
-    return gzwrite(file, buf, len);
-}
-#endif
-
-/* ===========================================================================
-      Writes c, converted to an unsigned char, into the compressed file.
-   gzputc returns the value that was written, or -1 in case of error.
-*/
-int ZEXPORT gzputc(file, c)
-    gzFile file;
-    int c;
-{
-    unsigned char cc = (unsigned char) c; /* required for big endian systems */
-
-    return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
-}
-
-
-/* ===========================================================================
-      Writes the given null-terminated string to the compressed file, excluding
-   the terminating null character.
-      gzputs returns the number of characters written, or -1 in case of error.
-*/
-int ZEXPORT gzputs(file, s)
-    gzFile file;
-    const char *s;
-{
-    return gzwrite(file, (voidpc)s, (unsigned)strlen(s));
-}
-
-
-/* ===========================================================================
-     Flushes all pending output into the compressed file. The parameter
-   flush is as in the deflate() function.
-*/
-local int do_flush (file, flush)
-    gzFile file;
-    int flush;
-{
-    uInt len;
-    int done = 0;
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
-
-    s->stream.avail_in = 0; /* should be zero already anyway */
-
-    for (;;) {
-        len = Z_BUFSIZE - s->stream.avail_out;
-
-        if (len != 0) {
-            if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
-                s->z_err = Z_ERRNO;
-                return Z_ERRNO;
-            }
-            s->stream.next_out = s->outbuf;
-            s->stream.avail_out = Z_BUFSIZE;
-        }
-        if (done) break;
-        s->out += s->stream.avail_out;
-        s->z_err = deflate(&(s->stream), flush);
-        s->out -= s->stream.avail_out;
-
-        /* Ignore the second of two consecutive flushes: */
-        if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
-
-        /* deflate has finished flushing only when it hasn't used up
-         * all the available space in the output buffer:
-         */
-        done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
-
-        if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
-    }
-    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
-}
-
-int ZEXPORT gzflush (file, flush)
-     gzFile file;
-     int flush;
-{
-    gz_stream *s = (gz_stream*)file;
-    int err = do_flush (file, flush);
-
-    if (err) return err;
-    fflush(s->file);
-    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
-}
-#endif /* NO_GZCOMPRESS */
-
-/* ===========================================================================
-      Sets the starting position for the next gzread or gzwrite on the given
-   compressed file. The offset represents a number of bytes in the
-      gzseek returns the resulting offset location as measured in bytes from
-   the beginning of the uncompressed stream, or -1 in case of error.
-      SEEK_END is not implemented, returns error.
-      In this version of the library, gzseek can be extremely slow.
-*/
-z_off_t ZEXPORT gzseek (file, offset, whence)
-    gzFile file;
-    z_off_t offset;
-    int whence;
-{
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL || whence == SEEK_END ||
-        s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
-        return -1L;
-    }
-
-    if (s->mode == 'w') {
-#ifdef NO_GZCOMPRESS
-        return -1L;
-#else
-        if (whence == SEEK_SET) {
-            offset -= s->in;
-        }
-        if (offset < 0) return -1L;
-
-        /* At this point, offset is the number of zero bytes to write. */
-        if (s->inbuf == Z_NULL) {
-            s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
-            if (s->inbuf == Z_NULL) return -1L;
-            zmemzero(s->inbuf, Z_BUFSIZE);
-        }
-        while (offset > 0)  {
-            uInt size = Z_BUFSIZE;
-            if (offset < Z_BUFSIZE) size = (uInt)offset;
-
-            size = gzwrite(file, s->inbuf, size);
-            if (size == 0) return -1L;
-
-            offset -= size;
-        }
-        return s->in;
-#endif
-    }
-    /* Rest of function is for reading only */
-
-    /* compute absolute position */
-    if (whence == SEEK_CUR) {
-        offset += s->out;
-    }
-    if (offset < 0) return -1L;
-
-    if (s->transparent) {
-        /* map to fseek */
-        s->back = EOF;
-        s->stream.avail_in = 0;
-        s->stream.next_in = s->inbuf;
-        if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
-
-        s->in = s->out = offset;
-        return offset;
-    }
-
-    /* For a negative seek, rewind and use positive seek */
-    if (offset >= s->out) {
-        offset -= s->out;
-    } else if (gzrewind(file) < 0) {
-        return -1L;
-    }
-    /* offset is now the number of bytes to skip. */
-
-    if (offset != 0 && s->outbuf == Z_NULL) {
-        s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
-        if (s->outbuf == Z_NULL) return -1L;
-    }
-    if (offset && s->back != EOF) {
-        s->back = EOF;
-        s->out++;
-        offset--;
-        if (s->last) s->z_err = Z_STREAM_END;
-    }
-    while (offset > 0)  {
-        int size = Z_BUFSIZE;
-        if (offset < Z_BUFSIZE) size = (int)offset;
-
-        size = gzread(file, s->outbuf, (uInt)size);
-        if (size <= 0) return -1L;
-        offset -= size;
-    }
-    return s->out;
-}
-
-/* ===========================================================================
-     Rewinds input file.
-*/
-int ZEXPORT gzrewind (file)
-    gzFile file;
-{
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL || s->mode != 'r') return -1;
-
-    s->z_err = Z_OK;
-    s->z_eof = 0;
-    s->back = EOF;
-    s->stream.avail_in = 0;
-    s->stream.next_in = s->inbuf;
-    s->crc = crc32(0L, Z_NULL, 0);
-    if (!s->transparent) (void)inflateReset(&s->stream);
-    s->in = 0;
-    s->out = 0;
-    return fseek(s->file, s->start, SEEK_SET);
-}
-
-/* ===========================================================================
-     Returns the starting position for the next gzread or gzwrite on the
-   given compressed file. This position represents a number of bytes in the
-   uncompressed data stream.
-*/
-z_off_t ZEXPORT gztell (file)
-    gzFile file;
-{
-    return gzseek(file, 0L, SEEK_CUR);
-}
-
-/* ===========================================================================
-     Returns 1 when EOF has previously been detected reading the given
-   input stream, otherwise zero.
-*/
-int ZEXPORT gzeof (file)
-    gzFile file;
-{
-    gz_stream *s = (gz_stream*)file;
-
-    /* With concatenated compressed files that can have embedded
-     * crc trailers, z_eof is no longer the only/best indicator of EOF
-     * on a gz_stream. Handle end-of-stream error explicitly here.
-     */
-    if (s == NULL || s->mode != 'r') return 0;
-    if (s->z_eof) return 1;
-    return s->z_err == Z_STREAM_END;
-}
-
-/* ===========================================================================
-     Returns 1 if reading and doing so transparently, otherwise zero.
-*/
-int ZEXPORT gzdirect (file)
-    gzFile file;
-{
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL || s->mode != 'r') return 0;
-    return s->transparent;
-}
-
-/* ===========================================================================
-   Outputs a long in LSB order to the given file
-*/
-local void putLong (file, x)
-    FILE *file;
-    uLong x;
-{
-    int n;
-    for (n = 0; n < 4; n++) {
-        fputc((int)(x & 0xff), file);
-        x >>= 8;
-    }
-}
-
-/* ===========================================================================
-   Reads a long in LSB order from the given gz_stream. Sets z_err in case
-   of error.
-*/
-local uLong getLong (s)
-    gz_stream *s;
-{
-    uLong x = (uLong)get_byte(s);
-    int c;
-
-    x += ((uLong)get_byte(s))<<8;
-    x += ((uLong)get_byte(s))<<16;
-    c = get_byte(s);
-    if (c == EOF) s->z_err = Z_DATA_ERROR;
-    x += ((uLong)c)<<24;
-    return x;
-}
-
-/* ===========================================================================
-     Flushes all pending output if necessary, closes the compressed file
-   and deallocates all the (de)compression state.
-*/
-int ZEXPORT gzclose (file)
-    gzFile file;
-{
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL) return Z_STREAM_ERROR;
-
-    if (s->mode == 'w') {
-#ifdef NO_GZCOMPRESS
-        return Z_STREAM_ERROR;
-#else
-        if (do_flush (file, Z_FINISH) != Z_OK)
-            return destroy((gz_stream*)file);
-
-        putLong (s->file, s->crc);
-        putLong (s->file, (uLong)(s->in & 0xffffffff));
-#endif
-    }
-    return destroy((gz_stream*)file);
-}
-
-#ifdef STDC
-#  define zstrerror(errnum) strerror(errnum)
-#else
-#  define zstrerror(errnum) ""
-#endif
-
-/* ===========================================================================
-     Returns the error message for the last error which occurred on the
-   given compressed file. errnum is set to zlib error number. If an
-   error occurred in the file system and not in the compression library,
-   errnum is set to Z_ERRNO and the application may consult errno
-   to get the exact error code.
-*/
-const char * ZEXPORT gzerror (file, errnum)
-    gzFile file;
-    int *errnum;
-{
-    const char *m;
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL) {
-        *errnum = Z_STREAM_ERROR;
-        return (const char*)ERR_MSG(Z_STREAM_ERROR);
-    }
-    *errnum = s->z_err;
-    if (*errnum == Z_OK) return (const char*)"";
-
-    m = (*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
-
-    if (m == NULL || *m == '\0') m = ERR_MSG(s->z_err);
-
-    TRYFREE(s->msg);
-    s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
-    if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
-    strcpy(s->msg, s->path);
-    strcat(s->msg, ": ");
-    strcat(s->msg, m);
-    return (const char*)s->msg;
-}
-
-/* ===========================================================================
-     Clear the error and end-of-file flags, and do the same for the real file.
-*/
-void ZEXPORT gzclearerr (file)
-    gzFile file;
-{
-    gz_stream *s = (gz_stream*)file;
-
-    if (s == NULL) return;
-    if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;
-    s->z_eof = 0;
-    clearerr(s->file);
-}
diff --git a/third_party/zlib/infback.c b/third_party/zlib/infback.c
index 284d523..f3833c2 100644
--- a/third_party/zlib/infback.c
+++ b/third_party/zlib/infback.c
@@ -1,5 +1,5 @@
 /* infback.c -- inflate using a call-back interface
- * Copyright (C) 1995-2005 Mark Adler
+ * Copyright (C) 1995-2011 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -42,10 +42,19 @@ int stream_size;
         return Z_STREAM_ERROR;
     strm->msg = Z_NULL;                 /* in case we return an error */
     if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
         strm->zalloc = zcalloc;
         strm->opaque = (voidpf)0;
+#endif
     }
-    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+    strm->zfree = zcfree;
+#endif
     state = (struct inflate_state FAR *)ZALLOC(strm, 1,
                                                sizeof(struct inflate_state));
     if (state == Z_NULL) return Z_MEM_ERROR;
@@ -55,7 +64,7 @@ int stream_size;
     state->wbits = windowBits;
     state->wsize = 1U << windowBits;
     state->window = window;
-    state->write = 0;
+    state->wnext = 0;
     state->whave = 0;
     return Z_OK;
 }
@@ -246,14 +255,14 @@ out_func out;
 void FAR *out_desc;
 {
     struct inflate_state FAR *state;
-    unsigned const char FAR *next; /* next input */
+    z_const unsigned char FAR *next;    /* next input */
     unsigned char FAR *put;     /* next output */
     unsigned have, left;        /* available input and output */
     unsigned long hold;         /* bit buffer */
     unsigned bits;              /* bits in bit buffer */
     unsigned copy;              /* number of stored or match bytes to copy */
     unsigned char FAR *from;    /* where to copy match bytes from */
-    code this;                  /* current decoding table entry */
+    code here;                  /* current decoding table entry */
     code last;                  /* parent table entry */
     unsigned len;               /* length to copy for repeats, bits to drop */
     int ret;                    /* return code */
@@ -308,8 +317,8 @@ void FAR *out_desc;
                 state->mode = TABLE;
                 break;
             case 3:
-                strm->msg = "invalid block type";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
             }
             DROPBITS(2);
             break;
@@ -319,8 +328,8 @@ void FAR *out_desc;
             BYTEBITS();                         /* go to byte boundary */
             NEEDBITS(32);
             if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
-                strm->msg = "invalid stored block lengths";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
                 break;
             }
             state->length = (unsigned)hold & 0xffff;
@@ -357,8 +366,8 @@ void FAR *out_desc;
             DROPBITS(4);
 #ifndef PKZIP_BUG_WORKAROUND
             if (state->nlen > 286 || state->ndist > 30) {
-                strm->msg = "too many length or distance symbols";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
                 break;
             }
 #endif
@@ -379,8 +388,8 @@ void FAR *out_desc;
             ret = inflate_table(CODES, state->lens, 19, &(state->next),
                                 &(state->lenbits), state->work);
             if (ret) {
-                strm->msg = "invalid code lengths set";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
                 break;
             }
             Tracev((stderr, "inflate:       code lengths ok\n"));
@@ -389,45 +398,44 @@ void FAR *out_desc;
             state->have = 0;
             while (state->have < state->nlen + state->ndist) {
                 for (;;) {
-                    this = state->lencode[BITS(state->lenbits)];
-                    if ((unsigned)(this.bits) <= bits) break;
+                    here = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(here.bits) <= bits) break;
                     PULLBYTE();
                 }
-                if (this.val < 16) {
-                    NEEDBITS(this.bits);
-                    DROPBITS(this.bits);
-                    state->lens[state->have++] = this.val;
+                if (here.val < 16) {
+                    DROPBITS(here.bits);
+                    state->lens[state->have++] = here.val;
                 }
                 else {
-                    if (this.val == 16) {
-                        NEEDBITS(this.bits + 2);
-                        DROPBITS(this.bits);
+                    if (here.val == 16) {
+                        NEEDBITS(here.bits + 2);
+                        DROPBITS(here.bits);
                         if (state->have == 0) {
-                            strm->msg = "invalid bit length repeat";
-                            state->mode = BAD_DATA;
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
                             break;
                         }
                         len = (unsigned)(state->lens[state->have - 1]);
                         copy = 3 + BITS(2);
                         DROPBITS(2);
                     }
-                    else if (this.val == 17) {
-                        NEEDBITS(this.bits + 3);
-                        DROPBITS(this.bits);
+                    else if (here.val == 17) {
+                        NEEDBITS(here.bits + 3);
+                        DROPBITS(here.bits);
                         len = 0;
                         copy = 3 + BITS(3);
                         DROPBITS(3);
                     }
                     else {
-                        NEEDBITS(this.bits + 7);
-                        DROPBITS(this.bits);
+                        NEEDBITS(here.bits + 7);
+                        DROPBITS(here.bits);
                         len = 0;
                         copy = 11 + BITS(7);
                         DROPBITS(7);
                     }
                     if (state->have + copy > state->nlen + state->ndist) {
-                        strm->msg = "invalid bit length repeat";
-                        state->mode = BAD_DATA;
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
                         break;
                     }
                     while (copy--)
@@ -436,17 +444,26 @@ void FAR *out_desc;
             }
 
             /* handle error breaks in while */
-            if (state->mode == BAD_DATA) break;
+            if (state->mode == BAD) break;
+
+            /* check for end-of-block code (better have one) */
+            if (state->lens[256] == 0) {
+                strm->msg = (char *)"invalid code -- missing end-of-block";
+                state->mode = BAD;
+                break;
+            }
 
-            /* build code tables */
+            /* build code tables -- note: do not change the lenbits or distbits
+               values here (9 and 6) without reading the comments in inftrees.h
+               concerning the ENOUGH constants, which depend on those values */
             state->next = state->codes;
             state->lencode = (code const FAR *)(state->next);
             state->lenbits = 9;
             ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
                                 &(state->lenbits), state->work);
             if (ret) {
-                strm->msg = "invalid literal/lengths set";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
                 break;
             }
             state->distcode = (code const FAR *)(state->next);
@@ -454,8 +471,8 @@ void FAR *out_desc;
             ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
                             &(state->next), &(state->distbits), state->work);
             if (ret) {
-                strm->msg = "invalid distances set";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
                 break;
             }
             Tracev((stderr, "inflate:       codes ok\n"));
@@ -474,28 +491,28 @@ void FAR *out_desc;
 
             /* get a literal, length, or end-of-block code */
             for (;;) {
-                this = state->lencode[BITS(state->lenbits)];
-                if ((unsigned)(this.bits) <= bits) break;
+                here = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(here.bits) <= bits) break;
                 PULLBYTE();
             }
-            if (this.op && (this.op & 0xf0) == 0) {
-                last = this;
+            if (here.op && (here.op & 0xf0) == 0) {
+                last = here;
                 for (;;) {
-                    this = state->lencode[last.val +
+                    here = state->lencode[last.val +
                             (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
                     PULLBYTE();
                 }
                 DROPBITS(last.bits);
             }
-            DROPBITS(this.bits);
-            state->length = (unsigned)this.val;
+            DROPBITS(here.bits);
+            state->length = (unsigned)here.val;
 
             /* process literal */
-            if (this.op == 0) {
-                Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+            if (here.op == 0) {
+                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
                         "inflate:         literal '%c'\n" :
-                        "inflate:         literal 0x%02x\n", this.val));
+                        "inflate:         literal 0x%02x\n", here.val));
                 ROOM();
                 *put++ = (unsigned char)(state->length);
                 left--;
@@ -504,21 +521,21 @@ void FAR *out_desc;
             }
 
             /* process end of block */
-            if (this.op & 32) {
+            if (here.op & 32) {
                 Tracevv((stderr, "inflate:         end of block\n"));
                 state->mode = TYPE;
                 break;
             }
 
             /* invalid code */
-            if (this.op & 64) {
-                strm->msg = "invalid literal/length code";
-                state->mode = BAD_DATA;
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
                 break;
             }
 
             /* length code -- get extra bits, if any */
-            state->extra = (unsigned)(this.op) & 15;
+            state->extra = (unsigned)(here.op) & 15;
             if (state->extra != 0) {
                 NEEDBITS(state->extra);
                 state->length += BITS(state->extra);
@@ -528,30 +545,30 @@ void FAR *out_desc;
 
             /* get distance code */
             for (;;) {
-                this = state->distcode[BITS(state->distbits)];
-                if ((unsigned)(this.bits) <= bits) break;
+                here = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(here.bits) <= bits) break;
                 PULLBYTE();
             }
-            if ((this.op & 0xf0) == 0) {
-                last = this;
+            if ((here.op & 0xf0) == 0) {
+                last = here;
                 for (;;) {
-                    this = state->distcode[last.val +
+                    here = state->distcode[last.val +
                             (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
                     PULLBYTE();
                 }
                 DROPBITS(last.bits);
             }
-            DROPBITS(this.bits);
-            if (this.op & 64) {
-                strm->msg = "invalid distance code";
-                state->mode = BAD_DATA;
+            DROPBITS(here.bits);
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
                 break;
             }
-            state->offset = (unsigned)this.val;
+            state->offset = (unsigned)here.val;
 
             /* get distance extra bits, if any */
-            state->extra = (unsigned)(this.op) & 15;
+            state->extra = (unsigned)(here.op) & 15;
             if (state->extra != 0) {
                 NEEDBITS(state->extra);
                 state->offset += BITS(state->extra);
@@ -559,8 +576,8 @@ void FAR *out_desc;
             }
             if (state->offset > state->wsize - (state->whave < state->wsize ?
                                                 left : 0)) {
-                strm->msg = "invalid distance too far back";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
                 break;
             }
             Tracevv((stderr, "inflate:         distance %u\n", state->offset));
@@ -595,7 +612,7 @@ void FAR *out_desc;
             }
             goto inf_leave;
 
-        case BAD_DATA:
+        case BAD:
             ret = Z_DATA_ERROR;
             goto inf_leave;
 
diff --git a/third_party/zlib/inffast.c b/third_party/zlib/inffast.c
index 687dfa0..bda59ce 100644
--- a/third_party/zlib/inffast.c
+++ b/third_party/zlib/inffast.c
@@ -1,5 +1,5 @@
 /* inffast.c -- fast decoding
- * Copyright (C) 1995-2004 Mark Adler
+ * Copyright (C) 1995-2008, 2010, 2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -49,7 +49,7 @@
 
         LEN -- ran out of enough output space or enough available input
         TYPE -- reached end of block code, inflate() to interpret next block
-        BAD_DATA -- error in block data
+        BAD -- error in block data
 
    Notes:
 
@@ -64,13 +64,13 @@
       requires strm->avail_out >= 258 for each loop to avoid checking for
       output space.
  */
-void inflate_fast(strm, start)
+void ZLIB_INTERNAL inflate_fast(strm, start)
 z_streamp strm;
 unsigned start;         /* inflate()'s starting value for strm->avail_out */
 {
     struct inflate_state FAR *state;
-    unsigned const char FAR *in;   /* local strm->next_in */
-    unsigned const char FAR *last; /* while in < last, enough input available */
+    z_const unsigned char FAR *in;      /* local strm->next_in */
+    z_const unsigned char FAR *last;    /* have enough input while in < last */
     unsigned char FAR *out;     /* local strm->next_out */
     unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
     unsigned char FAR *end;     /* while out < end, enough space available */
@@ -79,7 +79,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
 #endif
     unsigned wsize;             /* window size or zero if not using window */
     unsigned whave;             /* valid bytes in the window */
-    unsigned write;             /* window write index */
+    unsigned wnext;             /* window write index */
     unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
     unsigned long hold;         /* local strm->hold */
     unsigned bits;              /* local strm->bits */
@@ -87,7 +87,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
     code const FAR *dcode;      /* local strm->distcode */
     unsigned lmask;             /* mask for first level of length codes */
     unsigned dmask;             /* mask for first level of distance codes */
-    code this;                  /* retrieved table entry */
+    code here;                  /* retrieved table entry */
     unsigned op;                /* code bits, operation, extra bits, or */
                                 /*  window position, window bytes to copy */
     unsigned len;               /* match length, unused bytes */
@@ -106,7 +106,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
 #endif
     wsize = state->wsize;
     whave = state->whave;
-    write = state->write;
+    wnext = state->wnext;
     window = state->window;
     hold = state->hold;
     bits = state->bits;
@@ -124,20 +124,20 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
             hold += (unsigned long)(PUP(in)) << bits;
             bits += 8;
         }
-        this = lcode[hold & lmask];
+        here = lcode[hold & lmask];
       dolen:
-        op = (unsigned)(this.bits);
+        op = (unsigned)(here.bits);
         hold >>= op;
         bits -= op;
-        op = (unsigned)(this.op);
+        op = (unsigned)(here.op);
         if (op == 0) {                          /* literal */
-            Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
                     "inflate:         literal '%c'\n" :
-                    "inflate:         literal 0x%02x\n", this.val));
-            PUP(out) = (unsigned char)(this.val);
+                    "inflate:         literal 0x%02x\n", here.val));
+            PUP(out) = (unsigned char)(here.val);
         }
         else if (op & 16) {                     /* length base */
-            len = (unsigned)(this.val);
+            len = (unsigned)(here.val);
             op &= 15;                           /* number of extra bits */
             if (op) {
                 if (bits < op) {
@@ -155,14 +155,14 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
                 hold += (unsigned long)(PUP(in)) << bits;
                 bits += 8;
             }
-            this = dcode[hold & dmask];
+            here = dcode[hold & dmask];
           dodist:
-            op = (unsigned)(this.bits);
+            op = (unsigned)(here.bits);
             hold >>= op;
             bits -= op;
-            op = (unsigned)(this.op);
+            op = (unsigned)(here.op);
             if (op & 16) {                      /* distance base */
-                dist = (unsigned)(this.val);
+                dist = (unsigned)(here.val);
                 op &= 15;                       /* number of extra bits */
                 if (bits < op) {
                     hold += (unsigned long)(PUP(in)) << bits;
@@ -176,7 +176,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
 #ifdef INFLATE_STRICT
                 if (dist > dmax) {
                     strm->msg = (char *)"invalid distance too far back";
-                    state->mode = BAD_DATA;
+                    state->mode = BAD;
                     break;
                 }
 #endif
@@ -187,12 +187,34 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
                 if (dist > op) {                /* see if copy from window */
                     op = dist - op;             /* distance back in window */
                     if (op > whave) {
-                        strm->msg = "invalid distance too far back";
-                        state->mode = BAD_DATA;
-                        break;
+                        if (state->sane) {
+                            strm->msg =
+                                (char *)"invalid distance too far back";
+                            state->mode = BAD;
+                            break;
+                        }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                        if (len <= op - whave) {
+                            do {
+                                PUP(out) = 0;
+                            } while (--len);
+                            continue;
+                        }
+                        len -= op - whave;
+                        do {
+                            PUP(out) = 0;
+                        } while (--op > whave);
+                        if (op == 0) {
+                            from = out - dist;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--len);
+                            continue;
+                        }
+#endif
                     }
                     from = window - OFF;
-                    if (write == 0) {           /* very common case */
+                    if (wnext == 0) {           /* very common case */
                         from += wsize - op;
                         if (op < len) {         /* some from window */
                             len -= op;
@@ -202,17 +224,17 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
                             from = out - dist;  /* rest from output */
                         }
                     }
-                    else if (write < op) {      /* wrap around window */
-                        from += wsize + write - op;
-                        op -= write;
+                    else if (wnext < op) {      /* wrap around window */
+                        from += wsize + wnext - op;
+                        op -= wnext;
                         if (op < len) {         /* some from end of window */
                             len -= op;
                             do {
                                 PUP(out) = PUP(from);
                             } while (--op);
                             from = window - OFF;
-                            if (write < len) {  /* some from start of window */
-                                op = write;
+                            if (wnext < len) {  /* some from start of window */
+                                op = wnext;
                                 len -= op;
                                 do {
                                     PUP(out) = PUP(from);
@@ -222,7 +244,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
                         }
                     }
                     else {                      /* contiguous in window */
-                        from += write - op;
+                        from += wnext - op;
                         if (op < len) {         /* some from window */
                             len -= op;
                             do {
@@ -259,17 +281,17 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
                 }
             }
             else if ((op & 64) == 0) {          /* 2nd level distance code */
-                this = dcode[this.val + (hold & ((1U << op) - 1))];
+                here = dcode[here.val + (hold & ((1U << op) - 1))];
                 goto dodist;
             }
             else {
-                strm->msg = "invalid distance code";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
                 break;
             }
         }
         else if ((op & 64) == 0) {              /* 2nd level length code */
-            this = lcode[this.val + (hold & ((1U << op) - 1))];
+            here = lcode[here.val + (hold & ((1U << op) - 1))];
             goto dolen;
         }
         else if (op & 32) {                     /* end-of-block */
@@ -278,8 +300,8 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
             break;
         }
         else {
-            strm->msg = "invalid literal/length code";
-            state->mode = BAD_DATA;
+            strm->msg = (char *)"invalid literal/length code";
+            state->mode = BAD;
             break;
         }
     } while (in < last && out < end);
@@ -305,7 +327,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
    inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
    - Using bit fields for code structure
    - Different op definition to avoid & for extra bits (do & for table bits)
-   - Three separate decoding do-loops for direct, window, and write == 0
+   - Three separate decoding do-loops for direct, window, and wnext == 0
    - Special case for distance > 1 copies to do overlapped load and store copy
    - Explicit branch predictions (based on measured branch probabilities)
    - Deferring match copy and interspersed it with decoding subsequent codes
diff --git a/third_party/zlib/inffast.h b/third_party/zlib/inffast.h
index 1e88d2d..e5c1aa4 100644
--- a/third_party/zlib/inffast.h
+++ b/third_party/zlib/inffast.h
@@ -1,5 +1,5 @@
 /* inffast.h -- header to use inffast.c
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2003, 2010 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -8,4 +8,4 @@
    subject to change. Applications should only use zlib.h.
  */
 
-void inflate_fast OF((z_streamp strm, unsigned start));
+void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/third_party/zlib/inffixed.h b/third_party/zlib/inffixed.h
index 75ed4b5..d628327 100644
--- a/third_party/zlib/inffixed.h
+++ b/third_party/zlib/inffixed.h
@@ -2,9 +2,9 @@
      * Generated automatically by makefixed().
      */
 
-    /* WARNING: this file should *not* be used by applications. It
-       is part of the implementation of the compression library and
-       is subject to change. Applications should only use zlib.h.
+    /* WARNING: this file should *not* be used by applications.
+       It is part of the implementation of this library and is
+       subject to change. Applications should only use zlib.h.
      */
 
     static const code lenfix[512] = {
diff --git a/third_party/zlib/inflate.c b/third_party/zlib/inflate.c
index bcaca0d..870f89b 100644
--- a/third_party/zlib/inflate.c
+++ b/third_party/zlib/inflate.c
@@ -1,5 +1,5 @@
 /* inflate.c -- zlib decompression
- * Copyright (C) 1995-2005 Mark Adler
+ * Copyright (C) 1995-2012 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -45,7 +45,7 @@
  * - Rearrange window copies in inflate_fast() for speed and simplification
  * - Unroll last copy for window match in inflate_fast()
  * - Use local copies of window variables in inflate_fast() for speed
- * - Pull out common write == 0 case for speed in inflate_fast()
+ * - Pull out common wnext == 0 case for speed in inflate_fast()
  * - Make op and len in inflate_fast() unsigned for consistency
  * - Add FAR to lcode and dcode declarations in inflate_fast()
  * - Simplified bad distance check in inflate_fast()
@@ -93,14 +93,15 @@
 
 /* function prototypes */
 local void fixedtables OF((struct inflate_state FAR *state));
-local int updatewindow OF((z_streamp strm, unsigned out));
+local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
+                           unsigned copy));
 #ifdef BUILDFIXED
    void makefixed OF((void));
 #endif
-local unsigned syncsearch OF((unsigned FAR *have, unsigned const char FAR *buf,
+local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
                               unsigned len));
 
-int ZEXPORT inflateReset(strm)
+int ZEXPORT inflateResetKeep(strm)
 z_streamp strm;
 {
     struct inflate_state FAR *state;
@@ -109,36 +110,71 @@ z_streamp strm;
     state = (struct inflate_state FAR *)strm->state;
     strm->total_in = strm->total_out = state->total = 0;
     strm->msg = Z_NULL;
-    strm->adler = 1;        /* to support ill-conceived Java test suite */
+    if (state->wrap)        /* to support ill-conceived Java test suite */
+        strm->adler = state->wrap & 1;
     state->mode = HEAD;
     state->last = 0;
     state->havedict = 0;
     state->dmax = 32768U;
     state->head = Z_NULL;
-    state->wsize = 0;
-    state->whave = 0;
-    state->write = 0;
     state->hold = 0;
     state->bits = 0;
     state->lencode = state->distcode = state->next = state->codes;
+    state->sane = 1;
+    state->back = -1;
     Tracev((stderr, "inflate: reset\n"));
     return Z_OK;
 }
 
-int ZEXPORT inflatePrime(strm, bits, value)
+int ZEXPORT inflateReset(strm)
 z_streamp strm;
-int bits;
-int value;
 {
     struct inflate_state FAR *state;
 
     if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
     state = (struct inflate_state FAR *)strm->state;
-    if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
-    value &= (1L << bits) - 1;
-    state->hold += value << state->bits;
-    state->bits += bits;
-    return Z_OK;
+    state->wsize = 0;
+    state->whave = 0;
+    state->wnext = 0;
+    return inflateResetKeep(strm);
+}
+
+int ZEXPORT inflateReset2(strm, windowBits)
+z_streamp strm;
+int windowBits;
+{
+    int wrap;
+    struct inflate_state FAR *state;
+
+    /* get the state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* extract wrap request from windowBits parameter */
+    if (windowBits < 0) {
+        wrap = 0;
+        windowBits = -windowBits;
+    }
+    else {
+        wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+        if (windowBits < 48)
+            windowBits &= 15;
+#endif
+    }
+
+    /* set number of window bits, free window if different */
+    if (windowBits && (windowBits < 8 || windowBits > 15))
+        return Z_STREAM_ERROR;
+    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
+        ZFREE(strm, state->window);
+        state->window = Z_NULL;
+    }
+
+    /* update state and reset the rest of it */
+    state->wrap = wrap;
+    state->wbits = (unsigned)windowBits;
+    return inflateReset(strm);
 }
 
 int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
@@ -147,6 +183,7 @@ int windowBits;
 const char *version;
 int stream_size;
 {
+    int ret;
     struct inflate_state FAR *state;
 
     if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
@@ -155,33 +192,31 @@ int stream_size;
     if (strm == Z_NULL) return Z_STREAM_ERROR;
     strm->msg = Z_NULL;                 /* in case we return an error */
     if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
         strm->zalloc = zcalloc;
         strm->opaque = (voidpf)0;
+#endif
     }
-    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zfree = zcfree;
+#endif
     state = (struct inflate_state FAR *)
             ZALLOC(strm, 1, sizeof(struct inflate_state));
     if (state == Z_NULL) return Z_MEM_ERROR;
     Tracev((stderr, "inflate: allocated\n"));
     strm->state = (struct internal_state FAR *)state;
-    if (windowBits < 0) {
-        state->wrap = 0;
-        windowBits = -windowBits;
-    }
-    else {
-        state->wrap = (windowBits >> 4) + 1;
-#ifdef GUNZIP
-        if (windowBits < 48) windowBits &= 15;
-#endif
-    }
-    if (windowBits < 8 || windowBits > 15) {
+    state->window = Z_NULL;
+    ret = inflateReset2(strm, windowBits);
+    if (ret != Z_OK) {
         ZFREE(strm, state);
         strm->state = Z_NULL;
-        return Z_STREAM_ERROR;
     }
-    state->wbits = (unsigned)windowBits;
-    state->window = Z_NULL;
-    return inflateReset(strm);
+    return ret;
 }
 
 int ZEXPORT inflateInit_(strm, version, stream_size)
@@ -192,6 +227,27 @@ int stream_size;
     return inflateInit2_(strm, DEF_WBITS, version, stream_size);
 }
 
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (bits < 0) {
+        state->hold = 0;
+        state->bits = 0;
+        return Z_OK;
+    }
+    if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+    value &= (1L << bits) - 1;
+    state->hold += value << state->bits;
+    state->bits += bits;
+    return Z_OK;
+}
+
 /*
    Return state with length and distance decoding tables and index sizes set to
    fixed code decoding.  Normally this returns fixed tables from inffixed.h.
@@ -286,8 +342,8 @@ void makefixed()
     low = 0;
     for (;;) {
         if ((low % 7) == 0) printf("\n        ");
-        printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
-               state.lencode[low].val);
+        printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
+               state.lencode[low].bits, state.lencode[low].val);
         if (++low == size) break;
         putchar(',');
     }
@@ -320,12 +376,13 @@ void makefixed()
    output will fall in the output data, making match copies simpler and faster.
    The advantage may be dependent on the size of the processor's data caches.
  */
-local int updatewindow(strm, out)
+local int updatewindow(strm, end, copy)
 z_streamp strm;
-unsigned out;
+const Bytef *end;
+unsigned copy;
 {
     struct inflate_state FAR *state;
-    unsigned copy, dist;
+    unsigned dist;
 
     state = (struct inflate_state FAR *)strm->state;
 
@@ -340,30 +397,29 @@ unsigned out;
     /* if window not in use yet, initialize */
     if (state->wsize == 0) {
         state->wsize = 1U << state->wbits;
-        state->write = 0;
+        state->wnext = 0;
         state->whave = 0;
     }
 
     /* copy state->wsize or less output bytes into the circular window */
-    copy = out - strm->avail_out;
     if (copy >= state->wsize) {
-        zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
-        state->write = 0;
+        zmemcpy(state->window, end - state->wsize, state->wsize);
+        state->wnext = 0;
         state->whave = state->wsize;
     }
     else {
-        dist = state->wsize - state->write;
+        dist = state->wsize - state->wnext;
         if (dist > copy) dist = copy;
-        zmemcpy(state->window + state->write, strm->next_out - copy, dist);
+        zmemcpy(state->window + state->wnext, end - copy, dist);
         copy -= dist;
         if (copy) {
-            zmemcpy(state->window, strm->next_out - copy, copy);
-            state->write = copy;
+            zmemcpy(state->window, end - copy, copy);
+            state->wnext = copy;
             state->whave = state->wsize;
         }
         else {
-            state->write += dist;
-            if (state->write == state->wsize) state->write = 0;
+            state->wnext += dist;
+            if (state->wnext == state->wsize) state->wnext = 0;
             if (state->whave < state->wsize) state->whave += dist;
         }
     }
@@ -464,11 +520,6 @@ unsigned out;
         bits -= bits & 7; \
     } while (0)
 
-/* Reverse the bytes in a 32-bit value */
-#define REVERSE(q) \
-    ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
-     (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
-
 /*
    inflate() uses a state machine to process as much input data and generate as
    much output data as possible before returning.  The state machine is
@@ -556,7 +607,7 @@ z_streamp strm;
 int flush;
 {
     struct inflate_state FAR *state;
-    unsigned const char FAR *next;    /* next input */
+    z_const unsigned char FAR *next;    /* next input */
     unsigned char FAR *put;     /* next output */
     unsigned have, left;        /* available input and output */
     unsigned long hold;         /* bit buffer */
@@ -564,7 +615,7 @@ int flush;
     unsigned in, out;           /* save starting available input and output */
     unsigned copy;              /* number of stored or match bytes to copy */
     unsigned char FAR *from;    /* where to copy match bytes from */
-    code this;                  /* current decoding table entry */
+    code here;                  /* current decoding table entry */
     code last;                  /* parent table entry */
     unsigned len;               /* length to copy for repeats, bits to drop */
     int ret;                    /* return code */
@@ -608,20 +659,22 @@ int flush;
             if (
 #endif
                 ((BITS(8) << 8) + (hold >> 8)) % 31) {
-                strm->msg = "incorrect header check";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"incorrect header check";
+                state->mode = BAD;
                 break;
             }
             if (BITS(4) != Z_DEFLATED) {
-                strm->msg = "unknown compression method";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
                 break;
             }
             DROPBITS(4);
             len = BITS(4) + 8;
-            if (len > state->wbits) {
-                strm->msg = "invalid window size";
-                state->mode = BAD_DATA;
+            if (state->wbits == 0)
+                state->wbits = len;
+            else if (len > state->wbits) {
+                strm->msg = (char *)"invalid window size";
+                state->mode = BAD;
                 break;
             }
             state->dmax = 1U << len;
@@ -635,13 +688,13 @@ int flush;
             NEEDBITS(16);
             state->flags = (int)(hold);
             if ((state->flags & 0xff) != Z_DEFLATED) {
-                strm->msg = "unknown compression method";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
                 break;
             }
             if (state->flags & 0xe000) {
-                strm->msg = "unknown header flags set";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"unknown header flags set";
+                state->mode = BAD;
                 break;
             }
             if (state->head != Z_NULL)
@@ -744,8 +797,8 @@ int flush;
             if (state->flags & 0x0200) {
                 NEEDBITS(16);
                 if (hold != (state->check & 0xffff)) {
-                    strm->msg = "header crc mismatch";
-                    state->mode = BAD_DATA;
+                    strm->msg = (char *)"header crc mismatch";
+                    state->mode = BAD;
                     break;
                 }
                 INITBITS();
@@ -760,7 +813,7 @@ int flush;
 #endif
         case DICTID:
             NEEDBITS(32);
-            strm->adler = state->check = REVERSE(hold);
+            strm->adler = state->check = ZSWAP32(hold);
             INITBITS();
             state->mode = DICT;
         case DICT:
@@ -771,7 +824,7 @@ int flush;
             strm->adler = state->check = adler32(0L, Z_NULL, 0);
             state->mode = TYPE;
         case TYPE:
-            if (flush == Z_BLOCK) goto inf_leave;
+            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
         case TYPEDO:
             if (state->last) {
                 BYTEBITS();
@@ -791,7 +844,11 @@ int flush;
                 fixedtables(state);
                 Tracev((stderr, "inflate:     fixed codes block%s\n",
                         state->last ? " (last)" : ""));
-                state->mode = LEN;              /* decode codes */
+                state->mode = LEN_;             /* decode codes */
+                if (flush == Z_TREES) {
+                    DROPBITS(2);
+                    goto inf_leave;
+                }
                 break;
             case 2:                             /* dynamic block */
                 Tracev((stderr, "inflate:     dynamic codes block%s\n",
@@ -799,8 +856,8 @@ int flush;
                 state->mode = TABLE;
                 break;
             case 3:
-                strm->msg = "invalid block type";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
             }
             DROPBITS(2);
             break;
@@ -808,14 +865,17 @@ int flush;
             BYTEBITS();                         /* go to byte boundary */
             NEEDBITS(32);
             if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
-                strm->msg = "invalid stored block lengths";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
                 break;
             }
             state->length = (unsigned)hold & 0xffff;
             Tracev((stderr, "inflate:       stored length %u\n",
                     state->length));
             INITBITS();
+            state->mode = COPY_;
+            if (flush == Z_TREES) goto inf_leave;
+        case COPY_:
             state->mode = COPY;
         case COPY:
             copy = state->length;
@@ -844,8 +904,8 @@ int flush;
             DROPBITS(4);
 #ifndef PKZIP_BUG_WORKAROUND
             if (state->nlen > 286 || state->ndist > 30) {
-                strm->msg = "too many length or distance symbols";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
                 break;
             }
 #endif
@@ -861,13 +921,13 @@ int flush;
             while (state->have < 19)
                 state->lens[order[state->have++]] = 0;
             state->next = state->codes;
-            state->lencode = (code const FAR *)(state->next);
+            state->lencode = (const code FAR *)(state->next);
             state->lenbits = 7;
             ret = inflate_table(CODES, state->lens, 19, &(state->next),
                                 &(state->lenbits), state->work);
             if (ret) {
-                strm->msg = "invalid code lengths set";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
                 break;
             }
             Tracev((stderr, "inflate:       code lengths ok\n"));
@@ -876,45 +936,44 @@ int flush;
         case CODELENS:
             while (state->have < state->nlen + state->ndist) {
                 for (;;) {
-                    this = state->lencode[BITS(state->lenbits)];
-                    if ((unsigned)(this.bits) <= bits) break;
+                    here = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(here.bits) <= bits) break;
                     PULLBYTE();
                 }
-                if (this.val < 16) {
-                    NEEDBITS(this.bits);
-                    DROPBITS(this.bits);
-                    state->lens[state->have++] = this.val;
+                if (here.val < 16) {
+                    DROPBITS(here.bits);
+                    state->lens[state->have++] = here.val;
                 }
                 else {
-                    if (this.val == 16) {
-                        NEEDBITS(this.bits + 2);
-                        DROPBITS(this.bits);
+                    if (here.val == 16) {
+                        NEEDBITS(here.bits + 2);
+                        DROPBITS(here.bits);
                         if (state->have == 0) {
-                            strm->msg = "invalid bit length repeat";
-                            state->mode = BAD_DATA;
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
                             break;
                         }
                         len = state->lens[state->have - 1];
                         copy = 3 + BITS(2);
                         DROPBITS(2);
                     }
-                    else if (this.val == 17) {
-                        NEEDBITS(this.bits + 3);
-                        DROPBITS(this.bits);
+                    else if (here.val == 17) {
+                        NEEDBITS(here.bits + 3);
+                        DROPBITS(here.bits);
                         len = 0;
                         copy = 3 + BITS(3);
                         DROPBITS(3);
                     }
                     else {
-                        NEEDBITS(this.bits + 7);
-                        DROPBITS(this.bits);
+                        NEEDBITS(here.bits + 7);
+                        DROPBITS(here.bits);
                         len = 0;
                         copy = 11 + BITS(7);
                         DROPBITS(7);
                     }
                     if (state->have + copy > state->nlen + state->ndist) {
-                        strm->msg = "invalid bit length repeat";
-                        state->mode = BAD_DATA;
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
                         break;
                     }
                     while (copy--)
@@ -923,124 +982,142 @@ int flush;
             }
 
             /* handle error breaks in while */
-            if (state->mode == BAD_DATA) break;
+            if (state->mode == BAD) break;
 
-            /* build code tables */
+            /* check for end-of-block code (better have one) */
+            if (state->lens[256] == 0) {
+                strm->msg = (char *)"invalid code -- missing end-of-block";
+                state->mode = BAD;
+                break;
+            }
+
+            /* build code tables -- note: do not change the lenbits or distbits
+               values here (9 and 6) without reading the comments in inftrees.h
+               concerning the ENOUGH constants, which depend on those values */
             state->next = state->codes;
-            state->lencode = (code const FAR *)(state->next);
+            state->lencode = (const code FAR *)(state->next);
             state->lenbits = 9;
             ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
                                 &(state->lenbits), state->work);
             if (ret) {
-                strm->msg = "invalid literal/lengths set";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
                 break;
             }
-            state->distcode = (code const FAR *)(state->next);
+            state->distcode = (const code FAR *)(state->next);
             state->distbits = 6;
             ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
                             &(state->next), &(state->distbits), state->work);
             if (ret) {
-                strm->msg = "invalid distances set";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
                 break;
             }
             Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN_;
+            if (flush == Z_TREES) goto inf_leave;
+        case LEN_:
             state->mode = LEN;
         case LEN:
             if (have >= 6 && left >= 258) {
                 RESTORE();
                 inflate_fast(strm, out);
                 LOAD();
+                if (state->mode == TYPE)
+                    state->back = -1;
                 break;
             }
+            state->back = 0;
             for (;;) {
-                this = state->lencode[BITS(state->lenbits)];
-                if ((unsigned)(this.bits) <= bits) break;
+                here = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(here.bits) <= bits) break;
                 PULLBYTE();
             }
-            if (this.op && (this.op & 0xf0) == 0) {
-                last = this;
+            if (here.op && (here.op & 0xf0) == 0) {
+                last = here;
                 for (;;) {
-                    this = state->lencode[last.val +
+                    here = state->lencode[last.val +
                             (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
                     PULLBYTE();
                 }
                 DROPBITS(last.bits);
+                state->back += last.bits;
             }
-            DROPBITS(this.bits);
-            state->length = (unsigned)this.val;
-            if ((int)(this.op) == 0) {
-                Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            state->length = (unsigned)here.val;
+            if ((int)(here.op) == 0) {
+                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
                         "inflate:         literal '%c'\n" :
-                        "inflate:         literal 0x%02x\n", this.val));
+                        "inflate:         literal 0x%02x\n", here.val));
                 state->mode = LIT;
                 break;
             }
-            if (this.op & 32) {
+            if (here.op & 32) {
                 Tracevv((stderr, "inflate:         end of block\n"));
+                state->back = -1;
                 state->mode = TYPE;
                 break;
             }
-            if (this.op & 64) {
-                strm->msg = "invalid literal/length code";
-                state->mode = BAD_DATA;
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
                 break;
             }
-            state->extra = (unsigned)(this.op) & 15;
+            state->extra = (unsigned)(here.op) & 15;
             state->mode = LENEXT;
         case LENEXT:
             if (state->extra) {
                 NEEDBITS(state->extra);
                 state->length += BITS(state->extra);
                 DROPBITS(state->extra);
+                state->back += state->extra;
             }
             Tracevv((stderr, "inflate:         length %u\n", state->length));
+            state->was = state->length;
             state->mode = DIST;
         case DIST:
             for (;;) {
-                this = state->distcode[BITS(state->distbits)];
-                if ((unsigned)(this.bits) <= bits) break;
+                here = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(here.bits) <= bits) break;
                 PULLBYTE();
             }
-            if ((this.op & 0xf0) == 0) {
-                last = this;
+            if ((here.op & 0xf0) == 0) {
+                last = here;
                 for (;;) {
-                    this = state->distcode[last.val +
+                    here = state->distcode[last.val +
                             (BITS(last.bits + last.op) >> last.bits)];
-                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
                     PULLBYTE();
                 }
                 DROPBITS(last.bits);
+                state->back += last.bits;
             }
-            DROPBITS(this.bits);
-            if (this.op & 64) {
-                strm->msg = "invalid distance code";
-                state->mode = BAD_DATA;
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
                 break;
             }
-            state->offset = (unsigned)this.val;
-            state->extra = (unsigned)(this.op) & 15;
+            state->offset = (unsigned)here.val;
+            state->extra = (unsigned)(here.op) & 15;
             state->mode = DISTEXT;
         case DISTEXT:
             if (state->extra) {
                 NEEDBITS(state->extra);
                 state->offset += BITS(state->extra);
                 DROPBITS(state->extra);
+                state->back += state->extra;
             }
 #ifdef INFLATE_STRICT
             if (state->offset > state->dmax) {
-                strm->msg = "invalid distance too far back";
-                state->mode = BAD_DATA;
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
                 break;
             }
 #endif
-            if (state->offset > state->whave + out - left) {
-                strm->msg = "invalid distance too far back";
-                state->mode = BAD_DATA;
-                break;
-            }
             Tracevv((stderr, "inflate:         distance %u\n", state->offset));
             state->mode = MATCH;
         case MATCH:
@@ -1048,12 +1125,32 @@ int flush;
             copy = out - left;
             if (state->offset > copy) {         /* copy from window */
                 copy = state->offset - copy;
-                if (copy > state->write) {
-                    copy -= state->write;
+                if (copy > state->whave) {
+                    if (state->sane) {
+                        strm->msg = (char *)"invalid distance too far back";
+                        state->mode = BAD;
+                        break;
+                    }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                    Trace((stderr, "inflate.c too far\n"));
+                    copy -= state->whave;
+                    if (copy > state->length) copy = state->length;
+                    if (copy > left) copy = left;
+                    left -= copy;
+                    state->length -= copy;
+                    do {
+                        *put++ = 0;
+                    } while (--copy);
+                    if (state->length == 0) state->mode = LEN;
+                    break;
+#endif
+                }
+                if (copy > state->wnext) {
+                    copy -= state->wnext;
                     from = state->window + (state->wsize - copy);
                 }
                 else
-                    from = state->window + (state->write - copy);
+                    from = state->window + (state->wnext - copy);
                 if (copy > state->length) copy = state->length;
             }
             else {                              /* copy from output */
@@ -1088,9 +1185,9 @@ int flush;
 #ifdef GUNZIP
                      state->flags ? hold :
 #endif
-                     REVERSE(hold)) != state->check) {
-                    strm->msg = "incorrect data check";
-                    state->mode = BAD_DATA;
+                     ZSWAP32(hold)) != state->check) {
+                    strm->msg = (char *)"incorrect data check";
+                    state->mode = BAD;
                     break;
                 }
                 INITBITS();
@@ -1102,8 +1199,8 @@ int flush;
             if (state->wrap && state->flags) {
                 NEEDBITS(32);
                 if (hold != (state->total & 0xffffffffUL)) {
-                    strm->msg = "incorrect length check";
-                    state->mode = BAD_DATA;
+                    strm->msg = (char *)"incorrect length check";
+                    state->mode = BAD;
                     break;
                 }
                 INITBITS();
@@ -1114,7 +1211,7 @@ int flush;
         case DONE:
             ret = Z_STREAM_END;
             goto inf_leave;
-        case BAD_DATA:
+        case BAD:
             ret = Z_DATA_ERROR;
             goto inf_leave;
         case MEM:
@@ -1132,8 +1229,9 @@ int flush;
      */
   inf_leave:
     RESTORE();
-    if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
-        if (updatewindow(strm, out)) {
+    if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
+            (state->mode < CHECK || flush != Z_FINISH)))
+        if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
             state->mode = MEM;
             return Z_MEM_ERROR;
         }
@@ -1146,7 +1244,8 @@ int flush;
         strm->adler = state->check =
             UPDATE(state->check, strm->next_out - out, out);
     strm->data_type = state->bits + (state->last ? 64 : 0) +
-                      (state->mode == TYPE ? 128 : 0);
+                      (state->mode == TYPE ? 128 : 0) +
+                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
     if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
         ret = Z_BUF_ERROR;
     return ret;
@@ -1166,13 +1265,37 @@ z_streamp strm;
     return Z_OK;
 }
 
+int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+Bytef *dictionary;
+uInt *dictLength;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* copy dictionary */
+    if (state->whave && dictionary != Z_NULL) {
+        zmemcpy(dictionary, state->window + state->wnext,
+                state->whave - state->wnext);
+        zmemcpy(dictionary + state->whave - state->wnext,
+                state->window, state->wnext);
+    }
+    if (dictLength != Z_NULL)
+        *dictLength = state->whave;
+    return Z_OK;
+}
+
 int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
 z_streamp strm;
 const Bytef *dictionary;
 uInt dictLength;
 {
     struct inflate_state FAR *state;
-    unsigned long id;
+    unsigned long dictid;
+    int ret;
 
     /* check state */
     if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
@@ -1180,29 +1303,21 @@ uInt dictLength;
     if (state->wrap != 0 && state->mode != DICT)
         return Z_STREAM_ERROR;
 
-    /* check for correct dictionary id */
+    /* check for correct dictionary identifier */
     if (state->mode == DICT) {
-        id = adler32(0L, Z_NULL, 0);
-        id = adler32(id, dictionary, dictLength);
-        if (id != state->check)
+        dictid = adler32(0L, Z_NULL, 0);
+        dictid = adler32(dictid, dictionary, dictLength);
+        if (dictid != state->check)
             return Z_DATA_ERROR;
     }
 
-    /* copy dictionary to window */
-    if (updatewindow(strm, strm->avail_out)) {
+    /* copy dictionary to window using updatewindow(), which will amend the
+       existing dictionary if appropriate */
+    ret = updatewindow(strm, dictionary + dictLength, dictLength);
+    if (ret) {
         state->mode = MEM;
         return Z_MEM_ERROR;
     }
-    if (dictLength > state->wsize) {
-        zmemcpy(state->window, dictionary + dictLength - state->wsize,
-                state->wsize);
-        state->whave = state->wsize;
-    }
-    else {
-        zmemcpy(state->window + state->wsize - dictLength, dictionary,
-                dictLength);
-        state->whave = dictLength;
-    }
     state->havedict = 1;
     Tracev((stderr, "inflate:   dictionary set\n"));
     return Z_OK;
@@ -1238,7 +1353,7 @@ gz_headerp head;
  */
 local unsigned syncsearch(have, buf, len)
 unsigned FAR *have;
-unsigned const char FAR *buf;
+const unsigned char FAR *buf;
 unsigned len;
 {
     unsigned got;
@@ -1350,8 +1465,8 @@ z_streamp source;
     }
 
     /* copy state */
-    zmemcpy(dest, source, sizeof(z_stream));
-    zmemcpy(copy, state, sizeof(struct inflate_state));
+    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+    zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
     if (state->lencode >= state->codes &&
         state->lencode <= state->codes + ENOUGH - 1) {
         copy->lencode = copy->codes + (state->lencode - state->codes);
@@ -1366,3 +1481,32 @@ z_streamp source;
     dest->state = (struct internal_state FAR *)copy;
     return Z_OK;
 }
+
+int ZEXPORT inflateUndermine(strm, subvert)
+z_streamp strm;
+int subvert;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    state->sane = !subvert;
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+    return Z_OK;
+#else
+    state->sane = 1;
+    return Z_DATA_ERROR;
+#endif
+}
+
+long ZEXPORT inflateMark(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16;
+    state = (struct inflate_state FAR *)strm->state;
+    return ((long)(state->back) << 16) +
+        (state->mode == COPY ? state->length :
+            (state->mode == MATCH ? state->was - state->length : 0));
+}
diff --git a/third_party/zlib/inflate.h b/third_party/zlib/inflate.h
index 25b6538..95f4986 100644
--- a/third_party/zlib/inflate.h
+++ b/third_party/zlib/inflate.h
@@ -1,5 +1,5 @@
 /* inflate.h -- internal inflate state definition
- * Copyright (C) 1995-2004 Mark Adler
+ * Copyright (C) 1995-2009 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -32,11 +32,13 @@ typedef enum {
         TYPE,       /* i: waiting for type bits, including last-flag bit */
         TYPEDO,     /* i: same, but skip check to exit inflate on new block */
         STORED,     /* i: waiting for stored size (length and complement) */
+        COPY_,      /* i/o: same as COPY below, but only first time in */
         COPY,       /* i/o: waiting for input or output to copy stored block */
         TABLE,      /* i: waiting for dynamic block table lengths */
         LENLENS,    /* i: waiting for code length code lengths */
         CODELENS,   /* i: waiting for length/lit and distance code lengths */
-            LEN,        /* i: waiting for length/lit code */
+            LEN_,       /* i: same as LEN below, but only first time in */
+            LEN,        /* i: waiting for length/lit/eob code */
             LENEXT,     /* i: waiting for length extra bits */
             DIST,       /* i: waiting for distance code */
             DISTEXT,    /* i: waiting for distance extra bits */
@@ -45,7 +47,7 @@ typedef enum {
     CHECK,      /* i: waiting for 32-bit check value */
     LENGTH,     /* i: waiting for 32-bit length (gzip) */
     DONE,       /* finished check, done -- remain here until reset */
-    BAD_DATA,        /* got a data error -- remain here until reset */
+    BAD,        /* got a data error -- remain here until reset */
     MEM,        /* got an inflate() memory error -- remain here until reset */
     SYNC        /* looking for synchronization bytes to restart inflate() */
 } inflate_mode;
@@ -53,19 +55,21 @@ typedef enum {
 /*
     State transitions between above modes -
 
-    (most modes can go to the BAD_DATA or MEM mode -- not shown for clarity)
+    (most modes can go to BAD or MEM on error -- not shown for clarity)
 
     Process header:
-        HEAD -> (gzip) or (zlib)
-        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
-        NAME -> COMMENT -> HCRC -> TYPE
+        HEAD -> (gzip) or (zlib) or (raw)
+        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
+                  HCRC -> TYPE
         (zlib) -> DICTID or TYPE
         DICTID -> DICT -> TYPE
+        (raw) -> TYPEDO
     Read deflate blocks:
-            TYPE -> STORED or TABLE or LEN or CHECK
-            STORED -> COPY -> TYPE
-            TABLE -> LENLENS -> CODELENS -> LEN
-    Read deflate codes:
+            TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
+            STORED -> COPY_ -> COPY -> TYPE
+            TABLE -> LENLENS -> CODELENS -> LEN_
+            LEN_ -> LEN
+    Read deflate codes in fixed or dynamic block:
                 LEN -> LENEXT or LIT or TYPE
                 LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
                 LIT -> LEN
@@ -73,7 +77,7 @@ typedef enum {
         CHECK -> LENGTH -> DONE
  */
 
-/* state maintained between inflate() calls.  Approximately 7K bytes. */
+/* state maintained between inflate() calls.  Approximately 10K bytes. */
 struct inflate_state {
     inflate_mode mode;          /* current inflate mode */
     int last;                   /* true if processing last block */
@@ -88,7 +92,7 @@ struct inflate_state {
     unsigned wbits;             /* log base 2 of requested window size */
     unsigned wsize;             /* window size or zero if not using window */
     unsigned whave;             /* valid bytes in the window */
-    unsigned write;             /* window write index */
+    unsigned wnext;             /* window write index */
     unsigned char FAR *window;  /* allocated sliding window, if needed */
         /* bit accumulator */
     unsigned long hold;         /* input bit accumulator */
@@ -112,4 +116,7 @@ struct inflate_state {
     unsigned short lens[320];   /* temporary storage for code lengths */
     unsigned short work[288];   /* work area for code table building */
     code codes[ENOUGH];         /* space for code tables */
+    int sane;                   /* if false, allow invalid distance too far */
+    int back;                   /* bits back of last unprocessed length/lit */
+    unsigned was;               /* initial length of match */
 };
diff --git a/third_party/zlib/inftrees.c b/third_party/zlib/inftrees.c
index 8a9c13f..44d89cf 100644
--- a/third_party/zlib/inftrees.c
+++ b/third_party/zlib/inftrees.c
@@ -1,5 +1,5 @@
 /* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2005 Mark Adler
+ * Copyright (C) 1995-2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -9,7 +9,7 @@
 #define MAXBITS 15
 
 const char inflate_copyright[] =
-   " inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
+   " inflate 1.2.8 Copyright 1995-2013 Mark Adler ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -29,7 +29,7 @@ const char inflate_copyright[] =
    table index bits.  It will differ if the request is greater than the
    longest code or if it is less than the shortest code.
  */
-int inflate_table(type, lens, codes, table, bits, work)
+int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
 codetype type;
 unsigned short FAR *lens;
 unsigned codes;
@@ -50,7 +50,7 @@ unsigned short FAR *work;
     unsigned fill;              /* index for replicating entries */
     unsigned low;               /* low bits for current root entry */
     unsigned mask;              /* mask for low root bits */
-    code this;                  /* table entry for duplication */
+    code here;                  /* table entry for duplication */
     code FAR *next;             /* next available space in table */
     const unsigned short FAR *base;     /* base value table to use */
     const unsigned short FAR *extra;    /* extra bits table to use */
@@ -62,7 +62,7 @@ unsigned short FAR *work;
         35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
     static const unsigned short lext[31] = { /* Length codes 257..285 extra */
         16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
-        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78};
     static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
         257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
@@ -115,15 +115,15 @@ unsigned short FAR *work;
         if (count[max] != 0) break;
     if (root > max) root = max;
     if (max == 0) {                     /* no symbols to code at all */
-        this.op = (unsigned char)64;    /* invalid code marker */
-        this.bits = (unsigned char)1;
-        this.val = (unsigned short)0;
-        *(*table)++ = this;             /* make a table to force an error */
-        *(*table)++ = this;
+        here.op = (unsigned char)64;    /* invalid code marker */
+        here.bits = (unsigned char)1;
+        here.val = (unsigned short)0;
+        *(*table)++ = here;             /* make a table to force an error */
+        *(*table)++ = here;
         *bits = 1;
         return 0;     /* no symbols, but wait for decoding to report error */
     }
-    for (min = 1; min <= MAXBITS; min++)
+    for (min = 1; min < max; min++)
         if (count[min] != 0) break;
     if (root < min) root = min;
 
@@ -166,11 +166,10 @@ unsigned short FAR *work;
        entered in the tables.
 
        used keeps track of how many table entries have been allocated from the
-       provided *table space.  It is checked when a LENS table is being made
-       against the space in *table, ENOUGH, minus the maximum space needed by
-       the worst case distance code, MAXD.  This should never happen, but the
-       sufficiency of ENOUGH has not been proven exhaustively, hence the check.
-       This assumes that when type == LENS, bits == 9.
+       provided *table space.  It is checked for LENS and DIST tables against
+       the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+       the initial root table size constants.  See the comments in inftrees.h
+       for more information.
 
        sym increments through all symbols, and the loop terminates when
        all codes of length max, i.e. all codes, have been processed.  This
@@ -209,24 +208,25 @@ unsigned short FAR *work;
     mask = used - 1;            /* mask for comparing low */
 
     /* check available table space */
-    if (type == LENS && used >= ENOUGH - MAXD)
+    if ((type == LENS && used > ENOUGH_LENS) ||
+        (type == DISTS && used > ENOUGH_DISTS))
         return 1;
 
     /* process all codes and make table entries */
     for (;;) {
         /* create table entry */
-        this.bits = (unsigned char)(len - drop);
+        here.bits = (unsigned char)(len - drop);
         if ((int)(work[sym]) < end) {
-            this.op = (unsigned char)0;
-            this.val = work[sym];
+            here.op = (unsigned char)0;
+            here.val = work[sym];
         }
         else if ((int)(work[sym]) > end) {
-            this.op = (unsigned char)(extra[work[sym]]);
-            this.val = base[work[sym]];
+            here.op = (unsigned char)(extra[work[sym]]);
+            here.val = base[work[sym]];
         }
         else {
-            this.op = (unsigned char)(32 + 64);         /* end of block */
-            this.val = 0;
+            here.op = (unsigned char)(32 + 64);         /* end of block */
+            here.val = 0;
         }
 
         /* replicate for those indices with low len bits equal to huff */
@@ -235,7 +235,7 @@ unsigned short FAR *work;
         min = fill;                 /* save offset to next table */
         do {
             fill -= incr;
-            next[(huff >> drop) + fill] = this;
+            next[(huff >> drop) + fill] = here;
         } while (fill != 0);
 
         /* backwards increment the len-bit code huff */
@@ -277,7 +277,8 @@ unsigned short FAR *work;
 
             /* check for enough space */
             used += 1U << curr;
-            if (type == LENS && used >= ENOUGH - MAXD)
+            if ((type == LENS && used > ENOUGH_LENS) ||
+                (type == DISTS && used > ENOUGH_DISTS))
                 return 1;
 
             /* point entry in root table to sub-table */
@@ -288,38 +289,14 @@ unsigned short FAR *work;
         }
     }
 
-    /*
-       Fill in rest of table for incomplete codes.  This loop is similar to the
-       loop above in incrementing huff for table indices.  It is assumed that
-       len is equal to curr + drop, so there is no loop needed to increment
-       through high index bits.  When the current sub-table is filled, the loop
-       drops back to the root table to fill in any remaining entries there.
-     */
-    this.op = (unsigned char)64;                /* invalid code marker */
-    this.bits = (unsigned char)(len - drop);
-    this.val = (unsigned short)0;
-    while (huff != 0) {
-        /* when done with sub-table, drop back to root table */
-        if (drop != 0 && (huff & mask) != low) {
-            drop = 0;
-            len = root;
-            next = *table;
-            this.bits = (unsigned char)len;
-        }
-
-        /* put invalid code marker in table */
-        next[huff >> drop] = this;
-
-        /* backwards increment the len-bit code huff */
-        incr = 1U << (len - 1);
-        while (huff & incr)
-            incr >>= 1;
-        if (incr != 0) {
-            huff &= incr - 1;
-            huff += incr;
-        }
-        else
-            huff = 0;
+    /* fill in remaining table entry if code is incomplete (guaranteed to have
+       at most one remaining entry, since if the code is incomplete, the
+       maximum code length that was allowed to get this far is one bit) */
+    if (huff != 0) {
+        here.op = (unsigned char)64;            /* invalid code marker */
+        here.bits = (unsigned char)(len - drop);
+        here.val = (unsigned short)0;
+        next[huff] = here;
     }
 
     /* set return parameters */
diff --git a/third_party/zlib/inftrees.h b/third_party/zlib/inftrees.h
index b1104c8..baa53a0 100644
--- a/third_party/zlib/inftrees.h
+++ b/third_party/zlib/inftrees.h
@@ -1,5 +1,5 @@
 /* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995-2005 Mark Adler
+ * Copyright (C) 1995-2005, 2010 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -35,21 +35,28 @@ typedef struct {
     01000000 - invalid code
  */
 
-/* Maximum size of dynamic tree.  The maximum found in a long but non-
-   exhaustive search was 1444 code structures (852 for length/literals
-   and 592 for distances, the latter actually the result of an
-   exhaustive search).  The true maximum is not known, but the value
-   below is more than safe. */
-#define ENOUGH 2048
-#define MAXD 592
+/* Maximum size of the dynamic table.  The maximum number of code structures is
+   1444, which is the sum of 852 for literal/length codes and 592 for distance
+   codes.  These values were found by exhaustive searches using the program
+   examples/enough.c found in the zlib distribtution.  The arguments to that
+   program are the number of symbols, the initial root table size, and the
+   maximum bit length of a code.  "enough 286 9 15" for literal/length codes
+   returns returns 852, and "enough 30 6 15" for distance codes returns 592.
+   The initial root table size (9 or 6) is found in the fifth argument of the
+   inflate_table() calls in inflate.c and infback.c.  If the root table size is
+   changed, then these maximum sizes would be need to be recalculated and
+   updated. */
+#define ENOUGH_LENS 852
+#define ENOUGH_DISTS 592
+#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
 
-/* Type of code to build for inftable() */
+/* Type of code to build for inflate_table() */
 typedef enum {
     CODES,
     LENS,
     DISTS
 } codetype;
 
-extern int inflate_table OF((codetype type, unsigned short FAR *lens,
+int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
                              unsigned codes, code FAR * FAR *table,
                              unsigned FAR *bits, unsigned short FAR *work));
diff --git a/third_party/zlib/make_vms.com b/third_party/zlib/make_vms.com
index c2a1fb5..65e9d0c 100644
--- a/third_party/zlib/make_vms.com
+++ b/third_party/zlib/make_vms.com
@@ -1,46 +1,95 @@
 $! make libz under VMS written by
 $! Martin P.J. Zinser
-$! <zinser at zinser.no-ip.info or zinser at sysdev.deutsche-boerse.com>
 $!
-$ on error then goto err_exit
+$! In case of problems with the install you might contact me at
+$! zinser at zinser.no-ip.info(preferred) or
+$! martin.zinser at eurexchange.com (work)
 $!
+$! Make procedure history for Zlib
 $!
-$! Just some general constants...
+$!------------------------------------------------------------------------------
+$! Version history
+$! 0.01 20060120 First version to receive a number
+$! 0.02 20061008 Adapt to new Makefile.in
+$! 0.03 20091224 Add support for large file check
+$! 0.04 20100110 Add new gzclose, gzlib, gzread, gzwrite
+$! 0.05 20100221 Exchange zlibdefs.h by zconf.h.in
+$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new exmples
+$!               subdir path, update module search in makefile.in
+$! 0.07 20120115 Triggered by work done by Alexey Chupahin completly redesigned
+$!               shared image creation
+$! 0.08 20120219 Make it work on VAX again, pre-load missing symbols to shared
+$!               image
+$! 0.09 20120305 SMS.  P1 sets builder ("MMK", "MMS", " " (built-in)).
+$!               "" -> automatic, preference: MMK, MMS, built-in.
+$!
+$ on error then goto err_exit
 $!
 $ true  = 1
 $ false = 0
 $ tmpnam = "temp_" + f$getjpi("","pid")
-$ SAY = "WRITE SYS$OUTPUT"
+$ tt = tmpnam + ".txt"
+$ tc = tmpnam + ".c"
+$ th = tmpnam + ".h"
+$ define/nolog tconfig 'th'
+$ its_decc = false
+$ its_vaxc = false
+$ its_gnuc = false
+$ s_case   = False
 $!
 $! Setup variables holding "config" information
 $!
-$ Make     = ""
+$ Make    = "''p1'"
 $ name     = "Zlib"
 $ version  = "?.?.?"
 $ v_string = "ZLIB_VERSION"
 $ v_file   = "zlib.h"
-$ ccopt    = ""
-$ lopts    = ""
+$ ccopt   = "/include = []"
+$ lopts   = ""
+$ dnsrl   = ""
+$ aconf_in_file = "zconf.h.in#zconf.h_in#zconf_h.in"
+$ conf_check_string = ""
 $ linkonly = false
 $ optfile  = name + ".opt"
-$ its_decc = false
-$ its_vaxc = false
-$ its_gnuc = false
-$ axp      = f$getsyi("HW_MODEL").ge.1024
-$ s_case   = false
-$! Check for MMK/MMS
+$ mapfile  = name + ".map"
+$ libdefs  = ""
+$ vax      = f$getsyi("HW_MODEL").lt.1024
+$ axp      = f$getsyi("HW_MODEL").ge.1024 .and. f$getsyi("HW_MODEL").lt.4096
+$ ia64     = f$getsyi("HW_MODEL").ge.4096
+$!
+$! 2012-03-05 SMS.
+$! Why is this needed?  And if it is needed, why not simply ".not. vax"?
 $!
-$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS"
-$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK"
+$!!! if axp .or. ia64 then  set proc/parse=extended
 $!
+$ whoami = f$parse(f$environment("Procedure"),,,,"NO_CONCEAL")
+$ mydef  = F$parse(whoami,,,"DEVICE")
+$ mydir  = f$parse(whoami,,,"DIRECTORY") - "]["
+$ myproc = f$parse(whoami,,,"Name") + f$parse(whoami,,,"type")
+$!
+$! Check for MMK/MMS
+$!
+$ if (Make .eqs. "")
+$ then
+$   If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS"
+$   If F$Type (MMK) .eqs. "STRING" Then Make = "MMK"
+$ else
+$   Make = f$edit( Make, "trim")
+$ endif
 $!
 $ gosub find_version
 $!
+$  open/write topt tmp.opt
+$  open/write optf 'optfile'
+$!
 $ gosub check_opts
 $!
 $! Look for the compiler used
 $!
 $ gosub check_compiler
+$ close topt
+$ close optf
+$!
 $ if its_decc
 $ then
 $   ccopt = "/prefix=all" + ccopt
@@ -54,18 +103,79 @@ $       ccopt = "/decc" + ccopt
 $       define sys decc$library_include:
 $     endif
 $   endif
+$!
+$! 2012-03-05 SMS.
+$! Why /NAMES = AS_IS?  Why not simply ".not. vax"?  And why not on VAX?
+$!
+$   if axp .or. ia64
+$   then
+$       ccopt = ccopt + "/name=as_is/opt=(inline=speed)"
+$       s_case = true
+$   endif
 $ endif
 $ if its_vaxc .or. its_gnuc
 $ then
 $    if f$trnlnm("SYS").eqs."" then define sys sys$library:
 $ endif
 $!
+$! Build a fake configure input header
+$!
+$ open/write conf_hin config.hin
+$ write conf_hin "#undef _LARGEFILE64_SOURCE"
+$ close conf_hin
+$!
+$!
+$ i = 0
+$FIND_ACONF:
+$ fname = f$element(i,"#",aconf_in_file)
+$ if fname .eqs. "#" then goto AMISS_ERR
+$ if f$search(fname) .eqs. ""
+$ then
+$   i = i + 1
+$   goto find_aconf
+$ endif
+$ open/read/err=aconf_err aconf_in 'fname'
+$ open/write aconf zconf.h
+$ACONF_LOOP:
+$ read/end_of_file=aconf_exit aconf_in line
+$ work = f$edit(line, "compress,trim")
+$ if f$extract(0,6,work) .nes. "#undef"
+$ then
+$   if f$extract(0,12,work) .nes. "#cmakedefine"
+$   then
+$       write aconf line
+$   endif
+$ else
+$   cdef = f$element(1," ",work)
+$   gosub check_config
+$ endif
+$ goto aconf_loop
+$ACONF_EXIT:
+$ write aconf ""
+$ write aconf "/* VMS specifics added by make_vms.com: */"
+$ write aconf "#define VMS 1"
+$ write aconf "#include <unistd.h>"
+$ write aconf "#include <unixio.h>"
+$ write aconf "#ifdef _LARGEFILE"
+$ write aconf "# define off64_t __off64_t"
+$ write aconf "# define fopen64 fopen"
+$ write aconf "# define fseeko64 fseeko"
+$ write aconf "# define lseek64 lseek"
+$ write aconf "# define ftello64 ftell"
+$ write aconf "#endif"
+$ write aconf "#if !defined( __VAX) && (__CRTL_VER >= 70312000)"
+$ write aconf "# define HAVE_VSNPRINTF"
+$ write aconf "#endif"
+$ close aconf_in
+$ close aconf
+$ if f$search("''th'") .nes. "" then delete 'th';*
 $! Build the thing plain or with mms
 $!
 $ write sys$output "Compiling Zlib sources ..."
 $ if make.eqs.""
-$  then
-$   dele example.obj;*,minigzip.obj;*
+$ then
+$   if (f$search( "example.obj;*") .nes. "") then delete example.obj;*
+$   if (f$search( "minigzip.obj;*") .nes. "") then delete minigzip.obj;*
 $   CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" -
                 adler32.c zlib.h zconf.h
 $   CALL MAKE compress.OBJ "CC ''CCOPT' compress" -
@@ -74,8 +184,14 @@ $   CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" -
                 crc32.c zlib.h zconf.h
 $   CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" -
                 deflate.c deflate.h zutil.h zlib.h zconf.h
-$   CALL MAKE gzio.OBJ "CC ''CCOPT' gzio" -
-                gzio.c zutil.h zlib.h zconf.h
+$   CALL MAKE gzclose.OBJ "CC ''CCOPT' gzclose" -
+                gzclose.c zutil.h zlib.h zconf.h
+$   CALL MAKE gzlib.OBJ "CC ''CCOPT' gzlib" -
+                gzlib.c zutil.h zlib.h zconf.h
+$   CALL MAKE gzread.OBJ "CC ''CCOPT' gzread" -
+                gzread.c zutil.h zlib.h zconf.h
+$   CALL MAKE gzwrite.OBJ "CC ''CCOPT' gzwrite" -
+                gzwrite.c zutil.h zlib.h zconf.h
 $   CALL MAKE infback.OBJ "CC ''CCOPT' infback" -
                 infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h
 $   CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" -
@@ -93,46 +209,47 @@ $   CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" -
 $   write sys$output "Building Zlib ..."
 $   CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ
 $   write sys$output "Building example..."
-$   CALL MAKE example.OBJ "CC ''CCOPT' example" -
-                example.c zlib.h zconf.h
+$   CALL MAKE example.OBJ "CC ''CCOPT' [.test]example" -
+                [.test]example.c zlib.h zconf.h
 $   call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb
-$   if f$search("x11vms:xvmsutils.olb") .nes. ""
-$   then
-$     write sys$output "Building minigzip..."
-$     CALL MAKE minigzip.OBJ "CC ''CCOPT' minigzip" -
-                minigzip.c zlib.h zconf.h
-$     call make minigzip.exe -
-                "LINK minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib" -
-                minigzip.obj libz.olb
-$   endif
-$  else
+$   write sys$output "Building minigzip..."
+$   CALL MAKE minigzip.OBJ "CC ''CCOPT' [.test]minigzip" -
+              [.test]minigzip.c zlib.h zconf.h
+$   call make minigzip.exe -
+              "LINK minigzip,libz.olb/lib" -
+              minigzip.obj libz.olb
+$ else
 $   gosub crea_mms
-$   SAY "Make ''name' ''version' with ''Make' "
+$   write sys$output "Make ''name' ''version' with ''Make' "
 $   'make'
-$  endif
+$ endif
 $!
-$! Alpha gets a shareable image
+$! Create shareable image
 $!
-$ If axp
-$ Then
-$   gosub crea_olist
-$   write sys$output "Creating libzshr.exe"
-$   call anal_obj_axp modules.opt _link.opt
-$   if s_case
-$   then
-$      open/append optf modules.opt
-$      write optf "case_sensitive=YES"
-$      close optf
-$   endif
-$   LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,_link.opt/opt
-$ endif
+$ gosub crea_olist
+$ write sys$output "Creating libzshr.exe"
+$ call map_2_shopt 'mapfile' 'optfile'
+$ LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,'optfile'/opt
 $ write sys$output "Zlib build completed"
+$ delete/nolog tmp.opt;*
 $ exit
+$AMISS_ERR:
+$ write sys$output "No source for config.hin found."
+$ write sys$output "Tried any of ''aconf_in_file'"
+$ goto err_exit
 $CC_ERR:
 $ write sys$output "C compiler required to build ''name'"
 $ goto err_exit
 $ERR_EXIT:
 $ set message/facil/ident/sever/text
+$ close/nolog optf
+$ close/nolog topt
+$ close/nolog aconf_in
+$ close/nolog aconf
+$ close/nolog out
+$ close/nolog min
+$ close/nolog mod
+$ close/nolog h_in
 $ write sys$output "Exiting..."
 $ exit 2
 $!
@@ -180,61 +297,72 @@ $!------------------------------------------------------------------------------
 $!
 $! Check command line options and set symbols accordingly
 $!
+$!------------------------------------------------------------------------------
+$! Version history
+$! 0.01 20041206 First version to receive a number
+$! 0.02 20060126 Add new "HELP" target
 $ CHECK_OPTS:
 $ i = 1
 $ OPT_LOOP:
 $ if i .lt. 9
 $ then
 $   cparm = f$edit(p'i',"upcase")
-$   if cparm .eqs. "DEBUG"
-$   then
-$     ccopt = ccopt + "/noopt/deb"
-$     lopts = lopts + "/deb"
-$   endif
-$   if f$locate("CCOPT=",cparm) .lt. f$length(cparm)
-$   then
-$     start = f$locate("=",cparm) + 1
-$     len   = f$length(cparm) - start
-$     ccopt = ccopt + f$extract(start,len,cparm)
-$     if f$locate("AS_IS",f$edit(ccopt,"UPCASE")) .lt. f$length(ccopt) -
-         then s_case = true
-$   endif
-$   if cparm .eqs. "LINK" then linkonly = true
-$   if f$locate("LOPTS=",cparm) .lt. f$length(cparm)
-$   then
-$     start = f$locate("=",cparm) + 1
-$     len   = f$length(cparm) - start
-$     lopts = lopts + f$extract(start,len,cparm)
-$   endif
-$   if f$locate("CC=",cparm) .lt. f$length(cparm)
+$!
+$! Check if parameter actually contains something
+$!
+$   if f$edit(cparm,"trim") .nes. ""
 $   then
-$     start  = f$locate("=",cparm) + 1
-$     len    = f$length(cparm) - start
-$     cc_com = f$extract(start,len,cparm)
-      if (cc_com .nes. "DECC") .and. -
-         (cc_com .nes. "VAXC") .and. -
-	 (cc_com .nes. "GNUC")
+$     if cparm .eqs. "DEBUG"
 $     then
-$       write sys$output "Unsupported compiler choice ''cc_com' ignored"
-$       write sys$output "Use DECC, VAXC, or GNUC instead"
-$     else
-$     	if cc_com .eqs. "DECC" then its_decc = true
-$     	if cc_com .eqs. "VAXC" then its_vaxc = true
-$     	if cc_com .eqs. "GNUC" then its_gnuc = true
+$       ccopt = ccopt + "/noopt/deb"
+$       lopts = lopts + "/deb"
 $     endif
-$   endif
-$   if f$locate("MAKE=",cparm) .lt. f$length(cparm)
-$   then
-$     start  = f$locate("=",cparm) + 1
-$     len    = f$length(cparm) - start
-$     mmks = f$extract(start,len,cparm)
-$     if (mmks .eqs. "MMK") .or. (mmks .eqs. "MMS")
+$     if f$locate("CCOPT=",cparm) .lt. f$length(cparm)
 $     then
-$       make = mmks
-$     else
-$       write sys$output "Unsupported make choice ''mmks' ignored"
-$       write sys$output "Use MMK or MMS instead"
+$       start = f$locate("=",cparm) + 1
+$       len   = f$length(cparm) - start
+$       ccopt = ccopt + f$extract(start,len,cparm)
+$       if f$locate("AS_IS",f$edit(ccopt,"UPCASE")) .lt. f$length(ccopt) -
+          then s_case = true
 $     endif
+$     if cparm .eqs. "LINK" then linkonly = true
+$     if f$locate("LOPTS=",cparm) .lt. f$length(cparm)
+$     then
+$       start = f$locate("=",cparm) + 1
+$       len   = f$length(cparm) - start
+$       lopts = lopts + f$extract(start,len,cparm)
+$     endif
+$     if f$locate("CC=",cparm) .lt. f$length(cparm)
+$     then
+$       start  = f$locate("=",cparm) + 1
+$       len    = f$length(cparm) - start
+$       cc_com = f$extract(start,len,cparm)
+        if (cc_com .nes. "DECC") .and. -
+           (cc_com .nes. "VAXC") .and. -
+           (cc_com .nes. "GNUC")
+$       then
+$         write sys$output "Unsupported compiler choice ''cc_com' ignored"
+$         write sys$output "Use DECC, VAXC, or GNUC instead"
+$       else
+$         if cc_com .eqs. "DECC" then its_decc = true
+$         if cc_com .eqs. "VAXC" then its_vaxc = true
+$         if cc_com .eqs. "GNUC" then its_gnuc = true
+$       endif
+$     endif
+$     if f$locate("MAKE=",cparm) .lt. f$length(cparm)
+$     then
+$       start  = f$locate("=",cparm) + 1
+$       len    = f$length(cparm) - start
+$       mmks = f$extract(start,len,cparm)
+$       if (mmks .eqs. "MMK") .or. (mmks .eqs. "MMS")
+$       then
+$         make = mmks
+$       else
+$         write sys$output "Unsupported make choice ''mmks' ignored"
+$         write sys$output "Use MMK or MMS instead"
+$       endif
+$     endif
+$     if cparm .eqs. "HELP" then gosub bhelp
 $   endif
 $   i = i + 1
 $   goto opt_loop
@@ -244,6 +372,11 @@ $!------------------------------------------------------------------------------
 $!
 $! Look for the compiler used
 $!
+$! Version history
+$! 0.01 20040223 First version to receive a number
+$! 0.02 20040229 Save/set value of decc$no_rooted_search_lists
+$! 0.03 20060202 Extend handling of GNU C
+$! 0.04 20090402 Compaq -> hp
 $CHECK_COMPILER:
 $ if (.not. (its_decc .or. its_vaxc .or. its_gnuc))
 $ then
@@ -257,9 +390,26 @@ $!
 $ if (.not. (its_decc .or. its_vaxc .or. its_gnuc))
 $ then goto CC_ERR
 $ else
-$   if its_decc then write sys$output "CC compiler check ... Compaq C"
-$   if its_vaxc then write sys$output "CC compiler check ... VAX C"
-$   if its_gnuc then write sys$output "CC compiler check ... GNU C"
+$   if its_decc
+$   then
+$     write sys$output "CC compiler check ... hp C"
+$     if f$trnlnm("decc$no_rooted_search_lists") .nes. ""
+$     then
+$       dnrsl = f$trnlnm("decc$no_rooted_search_lists")
+$     endif
+$     define/nolog decc$no_rooted_search_lists 1
+$   else
+$     if its_vaxc then write sys$output "CC compiler check ... VAX C"
+$     if its_gnuc
+$     then
+$         write sys$output "CC compiler check ... GNU C"
+$         if f$trnlnm(topt) then write topt "gnu_cc:[000000]gcclib.olb/lib"
+$         if f$trnlnm(optf) then write optf "gnu_cc:[000000]gcclib.olb/lib"
+$         cc = "gcc"
+$     endif
+$     if f$trnlnm(topt) then write topt "sys$share:vaxcrtl.exe/share"
+$     if f$trnlnm(optf) then write optf "sys$share:vaxcrtl.exe/share"
+$   endif
 $ endif
 $ return
 $!------------------------------------------------------------------------------
@@ -274,19 +424,19 @@ $ copy sys$input: out
 $ deck
 # descrip.mms: MMS description file for building zlib on VMS
 # written by Martin P.J. Zinser
-# <zinser at zinser.no-ip.info or zinser at sysdev.deutsche-boerse.com>
+# <zinser at zinser.no-ip.info or martin.zinser at eurexchange.com>
 
-OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj, infback.obj\
+OBJS = adler32.obj, compress.obj, crc32.obj, gzclose.obj, gzlib.obj\
+       gzread.obj, gzwrite.obj, uncompr.obj, infback.obj\
        deflate.obj, trees.obj, zutil.obj, inflate.obj, \
        inftrees.obj, inffast.obj
 
 $ eod
 $ write out "CFLAGS=", ccopt
 $ write out "LOPTS=", lopts
+$ write out "all : example.exe minigzip.exe libz.olb"
 $ copy sys$input: out
 $ deck
-
-all : example.exe minigzip.exe libz.olb
         @ write sys$output " Example applications available"
 
 libz.olb : libz.olb($(OBJS))
@@ -296,7 +446,7 @@ example.exe : example.obj libz.olb
               link $(LOPTS) example,libz.olb/lib
 
 minigzip.exe : minigzip.obj libz.olb
-              link $(LOPTS) minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib
+              link $(LOPTS) minigzip,libz.olb/lib
 
 clean :
 	delete *.obj;*,libz.olb;*,*.opt;*,*.exe;*
@@ -307,12 +457,15 @@ adler32.obj  : adler32.c zutil.h zlib.h zconf.h
 compress.obj : compress.c zlib.h zconf.h
 crc32.obj    : crc32.c zutil.h zlib.h zconf.h
 deflate.obj  : deflate.c deflate.h zutil.h zlib.h zconf.h
-example.obj  : example.c zlib.h zconf.h
-gzio.obj     : gzio.c zutil.h zlib.h zconf.h
+example.obj  : [.test]example.c zlib.h zconf.h
+gzclose.obj  : gzclose.c zutil.h zlib.h zconf.h
+gzlib.obj    : gzlib.c zutil.h zlib.h zconf.h
+gzread.obj   : gzread.c zutil.h zlib.h zconf.h
+gzwrite.obj  : gzwrite.c zutil.h zlib.h zconf.h
 inffast.obj  : inffast.c zutil.h zlib.h zconf.h inftrees.h inffast.h
 inflate.obj  : inflate.c zutil.h zlib.h zconf.h
 inftrees.obj : inftrees.c zutil.h zlib.h zconf.h inftrees.h
-minigzip.obj : minigzip.c zlib.h zconf.h
+minigzip.obj : [.test]minigzip.c zlib.h zconf.h
 trees.obj    : trees.c deflate.h zutil.h zlib.h zconf.h
 uncompr.obj  : uncompr.c zlib.h zconf.h
 zutil.obj    : zutil.c zutil.h zlib.h zconf.h
@@ -328,13 +481,18 @@ $!
 $CREA_OLIST:
 $ open/read min makefile.in
 $ open/write mod modules.opt
-$ src_check = "OBJS ="
+$ src_check_list = "OBJZ =#OBJG ="
 $MRLOOP:
 $ read/end=mrdone min rec
-$ if (f$extract(0,6,rec) .nes. src_check) then goto mrloop
+$ i = 0
+$SRC_CHECK_LOOP:
+$ src_check = f$element(i, "#", src_check_list)
+$ i = i+1
+$ if src_check .eqs. "#" then goto mrloop
+$ if (f$extract(0,6,rec) .nes. src_check) then goto src_check_loop
 $ rec = rec - src_check
 $ gosub extra_filnam
-$ if (f$element(1,"\",rec) .eqs. "\") then goto mrdone
+$ if (f$element(1,"\",rec) .eqs. "\") then goto mrloop
 $MRSLOOP:
 $ read/end=mrdone min rec
 $ gosub extra_filnam
@@ -382,80 +540,328 @@ $ close h_in
 $ return
 $!------------------------------------------------------------------------------
 $!
-$! Analyze Object files for OpenVMS AXP to extract Procedure and Data
-$! information to build a symbol vector for a shareable image
-$! All the "brains" of this logic was suggested by Hartmut Becker
-$! (Hartmut.Becker at compaq.com). All the bugs were introduced by me
-$! (zinser at decus.de), so if you do have problem reports please do not
-$! bother Hartmut/HP, but get in touch with me
+$CHECK_CONFIG:
+$!
+$ in_ldef = f$locate(cdef,libdefs)
+$ if (in_ldef .lt. f$length(libdefs))
+$ then
+$   write aconf "#define ''cdef' 1"
+$   libdefs = f$extract(0,in_ldef,libdefs) + -
+              f$extract(in_ldef + f$length(cdef) + 1, -
+                        f$length(libdefs) - in_ldef - f$length(cdef) - 1, -
+                        libdefs)
+$ else
+$   if (f$type('cdef') .eqs. "INTEGER")
+$   then
+$     write aconf "#define ''cdef' ", 'cdef'
+$   else
+$     if (f$type('cdef') .eqs. "STRING")
+$     then
+$       write aconf "#define ''cdef' ", """", '''cdef'', """"
+$     else
+$       gosub check_cc_def
+$     endif
+$   endif
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Check if this is a define relating to the properties of the C/C++
+$! compiler
+$!
+$ CHECK_CC_DEF:
+$ if (cdef .eqs. "_LARGEFILE64_SOURCE")
+$ then
+$   copy sys$input: 'tc'
+$   deck
+#include "tconfig"
+#define _LARGEFILE
+#include <stdio.h>
+
+int main(){
+FILE *fp;
+  fp = fopen("temp.txt","r");
+  fseeko(fp,1,SEEK_SET);
+  fclose(fp);
+}
+
+$   eod
+$   test_inv = false
+$   comm_h = false
+$   gosub cc_prop_check
+$   return
+$ endif
+$ write aconf "/* ", line, " */"
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Check for properties of C/C++ compiler
+$!
+$! Version history
+$! 0.01 20031020 First version to receive a number
+$! 0.02 20031022 Added logic for defines with value
+$! 0.03 20040309 Make sure local config file gets not deleted
+$! 0.04 20041230 Also write include for configure run
+$! 0.05 20050103 Add processing of "comment defines"
+$CC_PROP_CHECK:
+$ cc_prop = true
+$ is_need = false
+$ is_need = (f$extract(0,4,cdef) .eqs. "NEED") .or. (test_inv .eq. true)
+$ if f$search(th) .eqs. "" then create 'th'
+$ set message/nofac/noident/nosever/notext
+$ on error then continue
+$ cc 'tmpnam'
+$ if .not. ($status)  then cc_prop = false
+$ on error then continue
+$! The headers might lie about the capabilities of the RTL
+$ link 'tmpnam',tmp.opt/opt
+$ if .not. ($status)  then cc_prop = false
+$ set message/fac/ident/sever/text
+$ on error then goto err_exit
+$ delete/nolog 'tmpnam'.*;*/exclude='th'
+$ if (cc_prop .and. .not. is_need) .or. -
+     (.not. cc_prop .and. is_need)
+$ then
+$   write sys$output "Checking for ''cdef'... yes"
+$   if f$type('cdef_val'_yes) .nes. ""
+$   then
+$     if f$type('cdef_val'_yes) .eqs. "INTEGER" -
+         then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_yes)
+$     if f$type('cdef_val'_yes) .eqs. "STRING" -
+         then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_yes)
+$   else
+$     call write_config f$fao("#define !AS 1",cdef)
+$   endif
+$   if (cdef .eqs. "HAVE_FSEEKO") .or. (cdef .eqs. "_LARGE_FILES") .or. -
+       (cdef .eqs. "_LARGEFILE64_SOURCE") then -
+      call write_config f$string("#define _LARGEFILE 1")
+$ else
+$   write sys$output "Checking for ''cdef'... no"
+$   if (comm_h)
+$   then
+      call write_config f$fao("/* !AS */",line)
+$   else
+$     if f$type('cdef_val'_no) .nes. ""
+$     then
+$       if f$type('cdef_val'_no) .eqs. "INTEGER" -
+           then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_no)
+$       if f$type('cdef_val'_no) .eqs. "STRING" -
+           then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_no)
+$     else
+$       call write_config f$fao("#undef !AS",cdef)
+$     endif
+$   endif
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Check for properties of C/C++ compiler with multiple result values
+$!
+$! Version history
+$! 0.01 20040127 First version
+$! 0.02 20050103 Reconcile changes from cc_prop up to version 0.05
+$CC_MPROP_CHECK:
+$ cc_prop = true
+$ i    = 1
+$ idel = 1
+$ MT_LOOP:
+$ if f$type(result_'i') .eqs. "STRING"
+$ then
+$   set message/nofac/noident/nosever/notext
+$   on error then continue
+$   cc 'tmpnam'_'i'
+$   if .not. ($status)  then cc_prop = false
+$   on error then continue
+$! The headers might lie about the capabilities of the RTL
+$   link 'tmpnam'_'i',tmp.opt/opt
+$   if .not. ($status)  then cc_prop = false
+$   set message/fac/ident/sever/text
+$   on error then goto err_exit
+$   delete/nolog 'tmpnam'_'i'.*;*
+$   if (cc_prop)
+$   then
+$     write sys$output "Checking for ''cdef'... ", mdef_'i'
+$     if f$type(mdef_'i') .eqs. "INTEGER" -
+         then call write_config f$fao("#define !AS !UL",cdef,mdef_'i')
+$     if f$type('cdef_val'_yes) .eqs. "STRING" -
+         then call write_config f$fao("#define !AS !AS",cdef,mdef_'i')
+$     goto msym_clean
+$   else
+$     i = i + 1
+$     goto mt_loop
+$   endif
+$ endif
+$ write sys$output "Checking for ''cdef'... no"
+$ call write_config f$fao("#undef !AS",cdef)
+$ MSYM_CLEAN:
+$ if (idel .le. msym_max)
+$ then
+$   delete/sym mdef_'idel'
+$   idel = idel + 1
+$   goto msym_clean
+$ endif
+$ return
+$!------------------------------------------------------------------------------
+$!
+$! Write configuration to both permanent and temporary config file
+$!
+$! Version history
+$! 0.01 20031029 First version to receive a number
+$!
+$WRITE_CONFIG: SUBROUTINE
+$  write aconf 'p1'
+$  open/append confh 'th'
+$  write confh 'p1'
+$  close confh
+$ENDSUBROUTINE
+$!------------------------------------------------------------------------------
+$!
+$! Analyze the project map file and create the symbol vector for a shareable
+$! image from it
+$!
+$! Version history
+$! 0.01 20120128 First version
+$! 0.02 20120226 Add pre-load logic
+$!
+$ MAP_2_SHOPT: Subroutine
 $!
-$ ANAL_OBJ_AXP: Subroutine
-$ V = 'F$Verify(0)
 $ SAY := "WRITE_ SYS$OUTPUT"
-$
+$!
 $ IF F$SEARCH("''P1'") .EQS. ""
 $ THEN
-$    SAY "ANAL_OBJ_AXP-E-NOSUCHFILE:  Error, inputfile ''p1' not available"
-$    goto exit_aa
+$    SAY "MAP_2_SHOPT-E-NOSUCHFILE:  Error, inputfile ''p1' not available"
+$    goto exit_m2s
 $ ENDIF
 $ IF "''P2'" .EQS. ""
 $ THEN
-$    SAY "ANAL_OBJ_AXP:  Error, no output file provided"
-$    goto exit_aa
+$    SAY "MAP_2_SHOPT:  Error, no output file provided"
+$    goto exit_m2s
 $ ENDIF
-$
-$ open/read in 'p1
-$ create a.tmp
-$ open/append atmp a.tmp
-$ loop:
-$ read/end=end_loop in line
-$ f= f$search(line)
-$ if f .eqs. ""
+$!
+$ module1 = "deflate#deflateEnd#deflateInit_#deflateParams#deflateSetDictionary"
+$ module2 = "gzclose#gzerror#gzgetc#gzgets#gzopen#gzprintf#gzputc#gzputs#gzread"
+$ module3 = "gzseek#gztell#inflate#inflateEnd#inflateInit_#inflateSetDictionary"
+$ module4 = "inflateSync#uncompress#zlibVersion#compress"
+$ open/read map 'p1
+$ if axp .or. ia64
 $ then
-$	write sys$output "ANAL_OBJ_AXP-w-nosuchfile, ''line'"
-$	goto loop
+$     open/write aopt a.opt
+$     open/write bopt b.opt
+$     write aopt " CASE_SENSITIVE=YES"
+$     write bopt "SYMBOL_VECTOR= (-"
+$     mod_sym_num = 1
+$ MOD_SYM_LOOP:
+$     if f$type(module'mod_sym_num') .nes. ""
+$     then
+$         mod_in = 0
+$ MOD_SYM_IN:
+$         shared_proc = f$element(mod_in, "#", module'mod_sym_num')
+$         if shared_proc .nes. "#"
+$         then
+$             write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",-
+        		       f$edit(shared_proc,"upcase"),shared_proc)
+$             write bopt f$fao("!AS=PROCEDURE,-",shared_proc)
+$             mod_in = mod_in + 1
+$             goto mod_sym_in
+$         endif
+$         mod_sym_num = mod_sym_num + 1
+$         goto mod_sym_loop
+$     endif
+$MAP_LOOP:
+$     read/end=map_end map line
+$     if (f$locate("{",line).lt. f$length(line)) .or. -
+         (f$locate("global:", line) .lt. f$length(line))
+$     then
+$         proc = true
+$         goto map_loop
+$     endif
+$     if f$locate("}",line).lt. f$length(line) then proc = false
+$     if f$locate("local:", line) .lt. f$length(line) then proc = false
+$     if proc
+$     then
+$         shared_proc = f$edit(line,"collapse")
+$         chop_semi = f$locate(";", shared_proc)
+$         if chop_semi .lt. f$length(shared_proc) then -
+              shared_proc = f$extract(0, chop_semi, shared_proc)
+$         write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",-
+        			 f$edit(shared_proc,"upcase"),shared_proc)
+$         write bopt f$fao("!AS=PROCEDURE,-",shared_proc)
+$     endif
+$     goto map_loop
+$MAP_END:
+$     close/nolog aopt
+$     close/nolog bopt
+$     open/append libopt 'p2'
+$     open/read aopt a.opt
+$     open/read bopt b.opt
+$ALOOP:
+$     read/end=aloop_end aopt line
+$     write libopt line
+$     goto aloop
+$ALOOP_END:
+$     close/nolog aopt
+$     sv = ""
+$BLOOP:
+$     read/end=bloop_end bopt svn
+$     if (svn.nes."")
+$     then
+$        if (sv.nes."") then write libopt sv
+$        sv = svn
+$     endif
+$     goto bloop
+$BLOOP_END:
+$     write libopt f$extract(0,f$length(sv)-2,sv), "-"
+$     write libopt ")"
+$     close/nolog bopt
+$     delete/nolog/noconf a.opt;*,b.opt;*
+$ else
+$     if vax
+$     then
+$     open/append libopt 'p2'
+$     mod_sym_num = 1
+$ VMOD_SYM_LOOP:
+$     if f$type(module'mod_sym_num') .nes. ""
+$     then
+$         mod_in = 0
+$ VMOD_SYM_IN:
+$         shared_proc = f$element(mod_in, "#", module'mod_sym_num')
+$         if shared_proc .nes. "#"
+$         then
+$     	      write libopt f$fao("UNIVERSAL=!AS",-
+      	  			     f$edit(shared_proc,"upcase"))
+$             mod_in = mod_in + 1
+$             goto vmod_sym_in
+$         endif
+$         mod_sym_num = mod_sym_num + 1
+$         goto vmod_sym_loop
+$     endif
+$VMAP_LOOP:
+$     	  read/end=vmap_end map line
+$     	  if (f$locate("{",line).lt. f$length(line)) .or. -
+   	      (f$locate("global:", line) .lt. f$length(line))
+$     	  then
+$     	      proc = true
+$     	      goto vmap_loop
+$     	  endif
+$     	  if f$locate("}",line).lt. f$length(line) then proc = false
+$     	  if f$locate("local:", line) .lt. f$length(line) then proc = false
+$     	  if proc
+$     	  then
+$     	      shared_proc = f$edit(line,"collapse")
+$     	      chop_semi = f$locate(";", shared_proc)
+$     	      if chop_semi .lt. f$length(shared_proc) then -
+      	  	  shared_proc = f$extract(0, chop_semi, shared_proc)
+$     	      write libopt f$fao("UNIVERSAL=!AS",-
+      	  			     f$edit(shared_proc,"upcase"))
+$     	  endif
+$     	  goto vmap_loop
+$VMAP_END:
+$     else
+$         write sys$output "Unknown Architecture (Not VAX, AXP, or IA64)"
+$         write sys$output "No options file created"
+$     endif
 $ endif
-$ define/user sys$output nl:
-$ define/user sys$error nl:
-$ anal/obj/gsd 'f /out=x.tmp
-$ open/read xtmp x.tmp
-$ XLOOP:
-$ read/end=end_xloop xtmp xline
-$ xline = f$edit(xline,"compress")
-$ write atmp xline
-$ goto xloop
-$ END_XLOOP:
-$ close xtmp
-$ goto loop
-$ end_loop:
-$ close in
-$ close atmp
-$ if f$search("a.tmp") .eqs. "" -
-	then $ exit
-$ ! all global definitions
-$ search a.tmp "symbol:","EGSY$V_DEF 1","EGSY$V_NORM 1"/out=b.tmp
-$ ! all procedures
-$ search b.tmp "EGSY$V_NORM 1"/wind=(0,1) /out=c.tmp
-$ search c.tmp "symbol:"/out=d.tmp
-$ define/user sys$output nl:
-$ edito/edt/command=sys$input d.tmp
-sub/symbol: "/symbol_vector=(/whole
-sub/"/=PROCEDURE)/whole
-exit
-$ ! all data
-$ search b.tmp "EGSY$V_DEF 1"/wind=(0,1) /out=e.tmp
-$ search e.tmp "symbol:"/out=f.tmp
-$ define/user sys$output nl:
-$ edito/edt/command=sys$input f.tmp
-sub/symbol: "/symbol_vector=(/whole
-sub/"/=DATA)/whole
-exit
-$ sort/nodupl d.tmp,f.tmp 'p2'
-$ delete a.tmp;*,b.tmp;*,c.tmp;*,d.tmp;*,e.tmp;*,f.tmp;*
-$ if f$search("x.tmp") .nes. "" -
-	then $ delete x.tmp;*
-$!
-$ EXIT_AA:
-$ if V then set verify
+$ EXIT_M2S:
+$ close/nolog map
+$ close/nolog libopt
 $ endsubroutine
-$!------------------------------------------------------------------------------
diff --git a/third_party/zlib/minigzip.c b/third_party/zlib/minigzip.c
deleted file mode 100644
index 4524b96..0000000
--- a/third_party/zlib/minigzip.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/* minigzip.c -- simulate gzip using the zlib compression library
- * Copyright (C) 1995-2005 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/*
- * minigzip is a minimal implementation of the gzip utility. This is
- * only an example of using zlib and isn't meant to replace the
- * full-featured gzip. No attempt is made to deal with file systems
- * limiting names to 14 or 8+3 characters, etc... Error checking is
- * very limited. So use minigzip only for testing; use gzip for the
- * real thing. On MSDOS, use only on file names without extension
- * or in pipe mode.
- */
-
-/* @(#) $Id$ */
-
-#include <stdio.h>
-#include "zlib.h"
-
-#ifdef STDC
-#  include <string.h>
-#  include <stdlib.h>
-#endif
-
-#ifdef USE_MMAP
-#  include <sys/types.h>
-#  include <sys/mman.h>
-#  include <sys/stat.h>
-#endif
-
-#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
-#  include <fcntl.h>
-#  include <io.h>
-#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
-#else
-#  define SET_BINARY_MODE(file)
-#endif
-
-#ifdef VMS
-#  define unlink delete
-#  define GZ_SUFFIX "-gz"
-#endif
-#ifdef RISCOS
-#  define unlink remove
-#  define GZ_SUFFIX "-gz"
-#  define fileno(file) file->__file
-#endif
-#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
-#  include <unix.h> /* for fileno */
-#endif
-
-#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
-  extern int unlink OF((const char *));
-#endif
-
-#ifndef GZ_SUFFIX
-#  define GZ_SUFFIX ".gz"
-#endif
-#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
-
-#define BUFLEN      16384
-#define MAX_NAME_LEN 1024
-
-#ifdef MAXSEG_64K
-#  define local static
-   /* Needed for systems with limitation on stack size. */
-#else
-#  define local
-#endif
-
-char *prog;
-
-void error            OF((const char *msg));
-void gz_compress      OF((FILE   *in, gzFile out));
-#ifdef USE_MMAP
-int  gz_compress_mmap OF((FILE   *in, gzFile out));
-#endif
-void gz_uncompress    OF((gzFile in, FILE   *out));
-void file_compress    OF((char  *file, char *mode));
-void file_uncompress  OF((char  *file));
-int  main             OF((int argc, char *argv[]));
-
-/* ===========================================================================
- * Display error message and exit
- */
-void error(msg)
-    const char *msg;
-{
-    fprintf(stderr, "%s: %s\n", prog, msg);
-    exit(1);
-}
-
-/* ===========================================================================
- * Compress input to output then close both files.
- */
-
-void gz_compress(in, out)
-    FILE   *in;
-    gzFile out;
-{
-    local char buf[BUFLEN];
-    int len;
-    int err;
-
-#ifdef USE_MMAP
-    /* Try first compressing with mmap. If mmap fails (minigzip used in a
-     * pipe), use the normal fread loop.
-     */
-    if (gz_compress_mmap(in, out) == Z_OK) return;
-#endif
-    for (;;) {
-        len = (int)fread(buf, 1, sizeof(buf), in);
-        if (ferror(in)) {
-            perror("fread");
-            exit(1);
-        }
-        if (len == 0) break;
-
-        if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
-    }
-    fclose(in);
-    if (gzclose(out) != Z_OK) error("failed gzclose");
-}
-
-#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech at eso.org> */
-
-/* Try compressing the input file at once using mmap. Return Z_OK if
- * if success, Z_ERRNO otherwise.
- */
-int gz_compress_mmap(in, out)
-    FILE   *in;
-    gzFile out;
-{
-    int len;
-    int err;
-    int ifd = fileno(in);
-    caddr_t buf;    /* mmap'ed buffer for the entire input file */
-    off_t buf_len;  /* length of the input file */
-    struct stat sb;
-
-    /* Determine the size of the file, needed for mmap: */
-    if (fstat(ifd, &sb) < 0) return Z_ERRNO;
-    buf_len = sb.st_size;
-    if (buf_len <= 0) return Z_ERRNO;
-
-    /* Now do the actual mmap: */
-    buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
-    if (buf == (caddr_t)(-1)) return Z_ERRNO;
-
-    /* Compress the whole file at once: */
-    len = gzwrite(out, (char *)buf, (unsigned)buf_len);
-
-    if (len != (int)buf_len) error(gzerror(out, &err));
-
-    munmap(buf, buf_len);
-    fclose(in);
-    if (gzclose(out) != Z_OK) error("failed gzclose");
-    return Z_OK;
-}
-#endif /* USE_MMAP */
-
-/* ===========================================================================
- * Uncompress input to output then close both files.
- */
-void gz_uncompress(in, out)
-    gzFile in;
-    FILE   *out;
-{
-    local char buf[BUFLEN];
-    int len;
-    int err;
-
-    for (;;) {
-        len = gzread(in, buf, sizeof(buf));
-        if (len < 0) error (gzerror(in, &err));
-        if (len == 0) break;
-
-        if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
-            error("failed fwrite");
-        }
-    }
-    if (fclose(out)) error("failed fclose");
-
-    if (gzclose(in) != Z_OK) error("failed gzclose");
-}
-
-
-/* ===========================================================================
- * Compress the given file: create a corresponding .gz file and remove the
- * original.
- */
-void file_compress(file, mode)
-    char  *file;
-    char  *mode;
-{
-    local char outfile[MAX_NAME_LEN];
-    FILE  *in;
-    gzFile out;
-
-    strcpy(outfile, file);
-    strcat(outfile, GZ_SUFFIX);
-
-    in = fopen(file, "rb");
-    if (in == NULL) {
-        perror(file);
-        exit(1);
-    }
-    out = gzopen(outfile, mode);
-    if (out == NULL) {
-        fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
-        exit(1);
-    }
-    gz_compress(in, out);
-
-    unlink(file);
-}
-
-
-/* ===========================================================================
- * Uncompress the given file and remove the original.
- */
-void file_uncompress(file)
-    char  *file;
-{
-    local char buf[MAX_NAME_LEN];
-    char *infile, *outfile;
-    FILE  *out;
-    gzFile in;
-    uInt len = (uInt)strlen(file);
-
-    strcpy(buf, file);
-
-    if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
-        infile = file;
-        outfile = buf;
-        outfile[len-3] = '\0';
-    } else {
-        outfile = file;
-        infile = buf;
-        strcat(infile, GZ_SUFFIX);
-    }
-    in = gzopen(infile, "rb");
-    if (in == NULL) {
-        fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
-        exit(1);
-    }
-    out = fopen(outfile, "wb");
-    if (out == NULL) {
-        perror(file);
-        exit(1);
-    }
-
-    gz_uncompress(in, out);
-
-    unlink(infile);
-}
-
-
-/* ===========================================================================
- * Usage:  minigzip [-d] [-f] [-h] [-r] [-1 to -9] [files...]
- *   -d : decompress
- *   -f : compress with Z_FILTERED
- *   -h : compress with Z_HUFFMAN_ONLY
- *   -r : compress with Z_RLE
- *   -1 to -9 : compression level
- */
-
-int main(argc, argv)
-    int argc;
-    char *argv[];
-{
-    int uncompr = 0;
-    gzFile file;
-    char outmode[20];
-
-    strcpy(outmode, "wb6 ");
-
-    prog = argv[0];
-    argc--, argv++;
-
-    while (argc > 0) {
-      if (strcmp(*argv, "-d") == 0)
-        uncompr = 1;
-      else if (strcmp(*argv, "-f") == 0)
-        outmode[3] = 'f';
-      else if (strcmp(*argv, "-h") == 0)
-        outmode[3] = 'h';
-      else if (strcmp(*argv, "-r") == 0)
-        outmode[3] = 'R';
-      else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
-               (*argv)[2] == 0)
-        outmode[2] = (*argv)[1];
-      else
-        break;
-      argc--, argv++;
-    }
-    if (outmode[3] == ' ')
-        outmode[3] = 0;
-    if (argc == 0) {
-        SET_BINARY_MODE(stdin);
-        SET_BINARY_MODE(stdout);
-        if (uncompr) {
-            file = gzdopen(fileno(stdin), "rb");
-            if (file == NULL) error("can't gzdopen stdin");
-            gz_uncompress(file, stdout);
-        } else {
-            file = gzdopen(fileno(stdout), outmode);
-            if (file == NULL) error("can't gzdopen stdout");
-            gz_compress(stdin, file);
-        }
-    } else {
-        do {
-            if (uncompr) {
-                file_uncompress(*argv);
-            } else {
-                file_compress(*argv, outmode);
-            }
-        } while (argv++, --argc);
-    }
-    return 0;
-}
diff --git a/third_party/zlib/msdos/Makefile.bor b/third_party/zlib/msdos/Makefile.bor
index 8f8132d..3d12a2c 100644
--- a/third_party/zlib/msdos/Makefile.bor
+++ b/third_party/zlib/msdos/Makefile.bor
@@ -41,10 +41,10 @@ LDFLAGS=-m$(MODEL) -f-
 # variables
 ZLIB_LIB = zlib_$(MODEL).lib
 
-OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
-OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
-OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
-OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj
+OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj
+OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
 
 
 # targets
@@ -61,7 +61,13 @@ crc32.obj: crc32.c zlib.h zconf.h crc32.h
 
 deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
 
-gzio.obj: gzio.c zutil.h zlib.h zconf.h
+gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h
+
+gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h
+
+gzread.obj: gzread.c zlib.h zconf.h gzguts.h
+
+gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h
 
 infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
  inffast.h inffixed.h
@@ -80,9 +86,9 @@ uncompr.obj: uncompr.c zlib.h zconf.h
 
 zutil.obj: zutil.c zutil.h zlib.h zconf.h
 
-example.obj: example.c zlib.h zconf.h
+example.obj: test/example.c zlib.h zconf.h
 
-minigzip.obj: minigzip.c zlib.h zconf.h
+minigzip.obj: test/minigzip.c zlib.h zconf.h
 
 
 # the command line is cut to fit in the MS-DOS 128 byte limit:
diff --git a/third_party/zlib/msdos/Makefile.dj2 b/third_party/zlib/msdos/Makefile.dj2
index 283d1d9..29b0395 100644
--- a/third_party/zlib/msdos/Makefile.dj2
+++ b/third_party/zlib/msdos/Makefile.dj2
@@ -51,8 +51,8 @@ AR=ar rcs
 prefix=/usr/local
 exec_prefix = $(prefix)
 
-OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
-       zutil.o inflate.o infback.o inftrees.o inffast.o
+OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \
+       uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
 
 OBJA =
 # to use the asm code: make OBJA=match.o
diff --git a/third_party/zlib/msdos/Makefile.emx b/third_party/zlib/msdos/Makefile.emx
index ed4c31f..9c1b57a 100644
--- a/third_party/zlib/msdos/Makefile.emx
+++ b/third_party/zlib/msdos/Makefile.emx
@@ -33,8 +33,8 @@ AR=ar rcs
 prefix=/usr/local
 exec_prefix = $(prefix)
 
-OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
-       zutil.o inflate.o infback.o inftrees.o inffast.o
+OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \
+       uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
 
 TEST_OBJS = example.o minigzip.o
 
diff --git a/third_party/zlib/msdos/Makefile.msc b/third_party/zlib/msdos/Makefile.msc
index b8fc665..ae83786 100644
--- a/third_party/zlib/msdos/Makefile.msc
+++ b/third_party/zlib/msdos/Makefile.msc
@@ -37,8 +37,8 @@ LDFLAGS=/noi/e/st:0x1500/noe/farcall/packcode
 # variables
 ZLIB_LIB = zlib_$(MODEL).lib
 
-OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
-OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj
+OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
 
 
 # targets
@@ -55,7 +55,13 @@ crc32.obj: crc32.c zlib.h zconf.h crc32.h
 
 deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
 
-gzio.obj: gzio.c zutil.h zlib.h zconf.h
+gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h
+
+gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h
+
+gzread.obj: gzread.c zlib.h zconf.h gzguts.h
+
+gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h
 
 infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
  inffast.h inffixed.h
@@ -74,10 +80,10 @@ uncompr.obj: uncompr.c zlib.h zconf.h
 
 zutil.obj: zutil.c zutil.h zlib.h zconf.h
 
-example.obj: example.c zlib.h zconf.h
+example.obj: test/example.c zlib.h zconf.h
 	$(CC) -c $(CFLAGS) $*.c
 
-minigzip.obj: minigzip.c zlib.h zconf.h
+minigzip.obj: test/minigzip.c zlib.h zconf.h
 	$(CC) -c $(CFLAGS) $*.c
 
 
diff --git a/third_party/zlib/msdos/Makefile.tc b/third_party/zlib/msdos/Makefile.tc
index 480750a..5aec82a 100644
--- a/third_party/zlib/msdos/Makefile.tc
+++ b/third_party/zlib/msdos/Makefile.tc
@@ -26,10 +26,10 @@ LDFLAGS=-m$(MODEL) -f-
 # variables
 ZLIB_LIB = zlib_$(MODEL).lib
 
-OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
-OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
-OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
-OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj
+OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj
+OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
 
 
 # targets
@@ -46,7 +46,13 @@ crc32.obj: crc32.c zlib.h zconf.h crc32.h
 
 deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
 
-gzio.obj: gzio.c zutil.h zlib.h zconf.h
+gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h
+
+gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h
+
+gzread.obj: gzread.c zlib.h zconf.h gzguts.h
+
+gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h
 
 infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
  inffast.h inffixed.h
@@ -65,9 +71,9 @@ uncompr.obj: uncompr.c zlib.h zconf.h
 
 zutil.obj: zutil.c zutil.h zlib.h zconf.h
 
-example.obj: example.c zlib.h zconf.h
+example.obj: test/example.c zlib.h zconf.h
 
-minigzip.obj: minigzip.c zlib.h zconf.h
+minigzip.obj: test/minigzip.c zlib.h zconf.h
 
 
 # the command line is cut to fit in the MS-DOS 128 byte limit:
diff --git a/third_party/zlib/old/zlib.html b/third_party/zlib/old/zlib.html
deleted file mode 100644
index 8c1b190..0000000
--- a/third_party/zlib/old/zlib.html
+++ /dev/null
@@ -1,971 +0,0 @@
-<html>
-<head>
- <title>
- zlib general purpose compression library version 1.1.4
- </title>
-</head>
-<body bgcolor="White" text="Black" vlink="Red" alink="Navy" link="Red">
-<!-- background="zlibbg.gif" -->
-
-<h1> zlib 1.1.4 Manual </h1>
-<hr>
-<a name="Contents"><h2>Contents</h2>
-<ol type="I">
-<li> <a href="#Prologue">Prologue</a>
-<li> <a href="#Introduction">Introduction</a>
-<li> <a href="#Utility functions">Utility functions</a>
-<li> <a href="#Basic functions">Basic functions</a>
-<li> <a href="#Advanced functions">Advanced functions</a>
-<li> <a href="#Constants">Constants</a>
-<li> <a href="#struct z_stream_s">struct z_stream_s</a>
-<li> <a href="#Checksum functions">Checksum functions</a>
-<li> <a href="#Misc">Misc</a>
-</ol>
-<hr>
-<a name="Prologue"><h2> Prologue </h2>
-  'zlib' general purpose compression library version 1.1.4, March 11th, 2002
-  <p>
-  Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler
-  <p>
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-  <p>
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-  <ol>
-   <li> The origin of this software must not be misrepresented ; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-   <li> Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-   <li> This notice may not be removed or altered from any source distribution.
-  </ol>
-
-  <dl>
-  <dt>Jean-loup Gailly
-  <dd><a href="mailto:jloup at gzip.org">jloup at gzip.org</a>
-  <dt>Mark Adler
-  <dd><a href="mailto:madler at alumni.caltech.edu">madler at alumni.caltech.edu</a>
-  </dl>
-
-  The data format used by the zlib library is described by RFCs (Request for
-  Comments) 1950 to 1952 in the files
-  <a href="ftp://ds.internic.net/rfc/rfc1950.txt">
-  ftp://ds.internic.net/rfc/rfc1950.txt </a>
-  (zlib format),
-  <a href="ftp://ds.internic.net/rfc/rfc1951.txt">
-  rfc1951.txt </a>
-  (<a href="#deflate">deflate</a> format) and
-  <a href="ftp://ds.internic.net/rfc/rfc1952.txt">
-  rfc1952.txt </a>
-  (gzip format).
-  <p>
-  This manual is converted from zlib.h by
-  <a href="mailto:piaip at csie.ntu.edu.tw"> piaip </a>
-  <p>
-  Visit <a href="http://ftp.cdrom.com/pub/infozip/zlib/">
-  http://ftp.cdrom.com/pub/infozip/zlib/</a>
-  for the official zlib web page.
-  <p>
-
-<hr>
-<a name="Introduction"><h2> Introduction </h2>
-     The 'zlib' compression library provides in-memory compression and
-  decompression functions, including integrity checks of the uncompressed
-  data.  This version of the library supports only one compression method
-  (deflation) but other algorithms will be added later and will have the same
-  stream interface.
-  <p>
-
-     Compression can be done in a single step if the buffers are large
-  enough (for example if an input file is mmap'ed), or can be done by
-  repeated calls of the compression function.  In the latter case, the
-  application must provide more input and/or consume the output
-  (providing more output space) before each call.
-  <p>
-
-     The library also supports reading and writing files in gzip (.gz) format
-  with an interface similar to that of stdio.
-  <p>
-
-     The library does not install any signal handler. The decoder checks
-  the consistency of the compressed data, so the library should never
-  crash even in case of corrupted input.
-  <p>
-
-<hr>
-<a name="Utility functions"><h2> Utility functions </h2>
-     The following utility functions are implemented on top of the
-   <a href="#Basic functions">basic stream-oriented functions</a>.
-   To simplify the interface, some
-   default options are assumed (compression level and memory usage,
-   standard memory allocation functions). The source code of these
-   utility functions can easily be modified if you need special options.
-<h3> Function list </h3>
-<ul>
-<li> int  <a href="#compress">compress</a> (Bytef *dest,   uLongf *destLen, const Bytef *source, uLong sourceLen);
-<li> int  <a href="#compress2">compress2</a> (Bytef *dest,   uLongf *destLen, const Bytef *source, uLong sourceLen, int level);
-<li> int  <a href="#uncompress">uncompress</a> (Bytef *dest,   uLongf *destLen, const Bytef *source, uLong sourceLen);
-<li> typedef voidp gzFile;
-<li>  gzFile  <a href="#gzopen">gzopen</a>  (const char *path, const char *mode);
-<li> gzFile  <a href="#gzdopen">gzdopen</a>  (int fd, const char *mode);
-<li> int  <a href="#gzsetparams">gzsetparams</a> (gzFile file, int level, int strategy);
-<li> int     <a href="#gzread">gzread</a>  (gzFile file, voidp buf, unsigned len);
-<li> int     <a href="#gzwrite">gzwrite</a> (gzFile file, const voidp buf, unsigned len);
-<li> int VA   <a href="#gzprintf">gzprintf</a> (gzFile file, const char *format, ...);
-<li> int  <a href="#gzputs">gzputs</a> (gzFile file, const char *s);
-<li> char *  <a href="#gzgets">gzgets</a> (gzFile file, char *buf, int len);
-<li> int     <a href="#gzputc">gzputc</a> (gzFile file, int c);
-<li> int     <a href="#gzgetc">gzgetc</a> (gzFile file);
-<li> int     <a href="#gzflush">gzflush</a> (gzFile file, int flush);
-<li> z_off_t     <a href="#gzseek">gzseek</a> (gzFile file, z_off_t offset, int whence);
-<li> z_off_t     <a href="#gztell">gztell</a> (gzFile file);
-<li> int     <a href="#gzrewind">gzrewind</a> (gzFile file);
-<li> int  <a href="#gzeof">gzeof</a> (gzFile file);
-<li> int     <a href="#gzclose">gzclose</a> (gzFile file);
-<li> const char *  <a href="#gzerror">gzerror</a> (gzFile file, int *errnum);
-</ul>
-<h3> Function description </h3>
-<dl>
-<font color="Blue"><dt> int  <a name="compress">compress</a> (Bytef *dest,   uLongf *destLen, const Bytef *source, uLong sourceLen);</font>
-<dd>
-     Compresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer. Upon entry, destLen is the total
-   size of the destination buffer, which must be at least 0.1% larger than
-   sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
-   compressed buffer.<p>
-     This function can be used to <a href="#compress">compress</a> a whole file at once if the
-   input file is mmap'ed.<p>
-     <a href="#compress">compress</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not
-   enough memory, <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a> if there was not enough room in the output
-   buffer.<p>
-
-<font color="Blue"><dt> int  <a name="compress2">compress2</a> (Bytef *dest,   uLongf *destLen, const Bytef *source, uLong sourceLen, int level);</font>
-<dd>
-     Compresses the source buffer into the destination buffer. The level
-   parameter has the same meaning as in <a href="#deflateInit">deflateInit</a>.  sourceLen is the byte
-   length of the source buffer. Upon entry, destLen is the total size of the
-   destination buffer, which must be at least 0.1% larger than sourceLen plus
-   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
-   <p>
-
-     <a href="#compress2">compress2</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not enough
-   memory, <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a> if there was not enough room in the output buffer,
-   <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the level parameter is invalid.
-   <p>
-
-<font color="Blue"><dt> int  <a name="uncompress">uncompress</a> (Bytef *dest,   uLongf *destLen, const Bytef *source, uLong sourceLen);</font>
-<dd>
-     Decompresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer. Upon entry, destLen is the total
-   size of the destination buffer, which must be large enough to hold the
-   entire uncompressed data. (The size of the uncompressed data must have
-   been saved previously by the compressor and transmitted to the decompressor
-   by some mechanism outside the scope of this compression library.)
-   Upon exit, destLen is the actual size of the compressed buffer. <p>
-     This function can be used to decompress a whole file at once if the
-   input file is mmap'ed.
-   <p>
-
-     <a href="#uncompress">uncompress</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not
-   enough memory, <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a> if there was not enough room in the output
-   buffer, or <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a> if the input data was corrupted.
-   <p>
-
-<dt> typedef voidp gzFile;
-<dd> <p>
-
-<font color="Blue"><dt>  gzFile  <a name="gzopen">gzopen</a>  (const char *path, const char *mode);</font>
-<dd>
-     Opens a gzip (.gz) file for reading or writing. The mode parameter
-   is as in fopen ("rb" or "wb") but can also include a compression level
-   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
-   Huffman only compression as in "wb1h". (See the description
-   of <a href="#deflateInit2">deflateInit2</a> for more information about the strategy parameter.)
-   <p>
-
-     <a href="#gzopen">gzopen</a> can be used to read a file which is not in gzip format ; in this
-   case <a href="#gzread">gzread</a> will directly read from the file without decompression.
-   <p>
-
-     <a href="#gzopen">gzopen</a> returns NULL if the file could not be opened or if there was
-   insufficient memory to allocate the (de)compression <a href="#state">state</a> ; errno
-   can be checked to distinguish the two cases (if errno is zero, the
-   zlib error is <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a>).
-   <p>
-
-<font color="Blue"><dt> gzFile  <a name="gzdopen">gzdopen</a>  (int fd, const char *mode);</font>
-<dd>
-     <a href="#gzdopen">gzdopen</a>() associates a gzFile with the file descriptor fd.  File
-   descriptors are obtained from calls like open, dup, creat, pipe or
-   fileno (in the file has been previously opened with fopen).
-   The mode parameter is as in <a href="#gzopen">gzopen</a>.
-   <p>
-     The next call of <a href="#gzclose">gzclose</a> on the returned gzFile will also close the
-   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
-   descriptor fd. If you want to keep fd open, use <a href="#gzdopen">gzdopen</a>(dup(fd), mode).
-   <p>
-     <a href="#gzdopen">gzdopen</a> returns NULL if there was insufficient memory to allocate
-   the (de)compression <a href="#state">state</a>.
-   <p>
-
-<font color="Blue"><dt> int  <a name="gzsetparams">gzsetparams</a> (gzFile file, int level, int strategy);</font>
-<dd>
-     Dynamically update the compression level or strategy. See the description
-   of <a href="#deflateInit2">deflateInit2</a> for the meaning of these parameters.
-   <p>
-     <a href="#gzsetparams">gzsetparams</a> returns <a href="#Z_OK">Z_OK</a> if success, or <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the file was not
-   opened for writing.
-   <p>
-
-<font color="Blue"><dt> int     <a name="gzread">gzread</a>  (gzFile file, voidp buf, unsigned len);</font>
-<dd>
-     Reads the given number of uncompressed bytes from the compressed file.
-   If the input file was not in gzip format, <a href="#gzread">gzread</a> copies the given number
-   of bytes into the buffer.
-   <p>
-     <a href="#gzread">gzread</a> returns the number of uncompressed bytes actually read (0 for
-   end of file, -1 for error).
-   <p>
-
-<font color="Blue"><dt> int     <a name="gzwrite">gzwrite</a> (gzFile file, const voidp buf, unsigned len);</font>
-<dd>
-     Writes the given number of uncompressed bytes into the compressed file.
-   <a href="#gzwrite">gzwrite</a> returns the number of uncompressed bytes actually written
-   (0 in case of error).
-   <p>
-
-<font color="Blue"><dt> int VA   <a name="gzprintf">gzprintf</a> (gzFile file, const char *format, ...);</font>
-<dd>
-     Converts, formats, and writes the args to the compressed file under
-   control of the format string, as in fprintf. <a href="#gzprintf">gzprintf</a> returns the number of
-   uncompressed bytes actually written (0 in case of error).
-   <p>
-
-<font color="Blue"><dt> int  <a name="gzputs">gzputs</a> (gzFile file, const char *s);</font>
-<dd>
-      Writes the given null-terminated string to the compressed file, excluding
-   the terminating null character.
-   <p>
-      <a href="#gzputs">gzputs</a> returns the number of characters written, or -1 in case of error.
-      <p>
-
-<font color="Blue"><dt> char *  <a name="gzgets">gzgets</a> (gzFile file, char *buf, int len);</font>
-<dd>
-      Reads bytes from the compressed file until len-1 characters are read, or
-   a newline character is read and transferred to buf, or an end-of-file
-   condition is encountered.  The string is then terminated with a null
-   character.
-   <p>
-      <a href="#gzgets">gzgets</a> returns buf, or <a href="#Z_NULL">Z_NULL</a> in case of error.
-      <p>
-
-<font color="Blue"><dt> int     <a name="gzputc">gzputc</a> (gzFile file, int c);</font>
-<dd>
-      Writes c, converted to an unsigned char, into the compressed file.
-   <a href="#gzputc">gzputc</a> returns the value that was written, or -1 in case of error.
-   <p>
-
-<font color="Blue"><dt> int     <a name="gzgetc">gzgetc</a> (gzFile file);</font>
-<dd>
-      Reads one byte from the compressed file. <a href="#gzgetc">gzgetc</a> returns this byte
-   or -1 in case of end of file or error.
-   <p>
-
-<font color="Blue"><dt> int     <a name="gzflush">gzflush</a> (gzFile file, int flush);</font>
-<dd>
-     Flushes all pending output into the compressed file. The parameter
-   flush is as in the <a href="#deflate">deflate</a>() function. The return value is the zlib
-   error number (see function <a href="#gzerror">gzerror</a> below). <a href="#gzflush">gzflush</a> returns <a href="#Z_OK">Z_OK</a> if
-   the flush parameter is <a href="#Z_FINISH">Z_FINISH</a> and all output could be flushed.
-   <p>
-     <a href="#gzflush">gzflush</a> should be called only when strictly necessary because it can
-   degrade compression.
-   <p>
-
-<font color="Blue"><dt> z_off_t     <a name="gzseek">gzseek</a> (gzFile file, z_off_t offset, int whence);</font>
-<dd>
-      Sets the starting position for the next <a href="#gzread">gzread</a> or <a href="#gzwrite">gzwrite</a> on the
-   given compressed file. The offset represents a number of bytes in the
-   uncompressed data stream. The whence parameter is defined as in lseek(2);
-   the value SEEK_END is not supported.
-   <p>
-     If the file is opened for reading, this function is emulated but can be
-   extremely slow. If the file is opened for writing, only forward seeks are
-   supported ; <a href="#gzseek">gzseek</a> then compresses a sequence of zeroes up to the new
-   starting position.
-   <p>
-      <a href="#gzseek">gzseek</a> returns the resulting offset location as measured in bytes from
-   the beginning of the uncompressed stream, or -1 in case of error, in
-   particular if the file is opened for writing and the new starting position
-   would be before the current position.
-   <p>
-
-<font color="Blue"><dt> int     <a name="gzrewind">gzrewind</a> (gzFile file);</font>
-<dd>
-     Rewinds the given file. This function is supported only for reading.
-     <p>
-   <a href="#gzrewind">gzrewind</a>(file) is equivalent to (int)<a href="#gzseek">gzseek</a>(file, 0L, SEEK_SET)
-   <p>
-
-<font color="Blue"><dt> z_off_t     <a name="gztell">gztell</a> (gzFile file);</font>
-<dd>
-     Returns the starting position for the next <a href="#gzread">gzread</a> or <a href="#gzwrite">gzwrite</a> on the
-   given compressed file. This position represents a number of bytes in the
-   uncompressed data stream.
-   <p>
-
-   <a href="#gztell">gztell</a>(file) is equivalent to <a href="#gzseek">gzseek</a>(file, 0L, SEEK_CUR)
-   <p>
-
-<font color="Blue"><dt> int  <a name="gzeof">gzeof</a> (gzFile file);</font>
-<dd>
-     Returns 1 when EOF has previously been detected reading the given
-   input stream, otherwise zero.
-   <p>
-
-<font color="Blue"><dt> int     <a name="gzclose">gzclose</a> (gzFile file);</font>
-<dd>
-     Flushes all pending output if necessary, closes the compressed file
-   and deallocates all the (de)compression <a href="#state">state</a>. The return value is the zlib
-   error number (see function <a href="#gzerror">gzerror</a> below).
-   <p>
-
-<font color="Blue"><dt> const char *  <a name="gzerror">gzerror</a> (gzFile file, int *errnum);</font>
-<dd>
-     Returns the error message for the last error which occurred on the
-   given compressed file. errnum is set to zlib error number. If an
-   error occurred in the file system and not in the compression library,
-   errnum is set to <a href="#Z_ERRNO">Z_ERRNO</a> and the application may consult errno
-   to get the exact error code.
-   <p>
-</dl>
-<hr>
-<a name="Basic functions"><h2> Basic functions </h2>
-<h3> Function list </h3>
-<ul>
-<li>  const char *  <a href="#zlibVersion">zlibVersion</a> (void);
-<li>  int  <a href="#deflateInit">deflateInit</a> (<a href="#z_streamp">z_streamp</a> strm, int level);
-<li>  int  <a href="#deflate">deflate</a> (<a href="#z_streamp">z_streamp</a> strm, int flush);
-<li>  int  <a href="#deflateEnd">deflateEnd</a> (<a href="#z_streamp">z_streamp</a> strm);
-<li>  int  <a href="#inflateInit">inflateInit</a> (<a href="#z_streamp">z_streamp</a> strm);
-<li>  int  <a href="#inflate">inflate</a> (<a href="#z_streamp">z_streamp</a> strm, int flush);
-<li>  int  <a href="#inflateEnd">inflateEnd</a> (<a href="#z_streamp">z_streamp</a> strm);
-</ul>
-
-<h3> Function description </h3>
-<dl>
-<font color="Blue"><dt>  const char *  <a name="zlibVersion">zlibVersion</a> (void);</font>
-<dd> The application can compare <a href="#zlibVersion">zlibVersion</a> and ZLIB_VERSION for consistency.
-   If the first character differs, the library code actually used is
-   not compatible with the zlib.h header file used by the application.
-   This check is automatically made by <a href="#deflateInit">deflateInit</a> and <a href="#inflateInit">inflateInit</a>.
-   <p>
-
-<font color="Blue"><dt> int  <a name="deflateInit">deflateInit</a> (<a href="#z_streamp">z_streamp</a> strm, int level);</font>
-<dd>
-     Initializes the internal stream <a href="#state">state</a> for compression. The fields
-   <a href="#zalloc">zalloc</a>, <a href="#zfree">zfree</a> and <a href="#opaque">opaque</a> must be initialized before by the caller.
-   If <a href="#zalloc">zalloc</a> and <a href="#zfree">zfree</a> are set to <a href="#Z_NULL">Z_NULL</a>, <a href="#deflateInit">deflateInit</a> updates them to
-   use default allocation functions.
-   <p>
-
-     The compression level must be <a href="#Z_DEFAULT_COMPRESSION">Z_DEFAULT_COMPRESSION</a>, or between 0 and 9:
-   1 gives best speed, 9 gives best compression, 0 gives no compression at
-   all (the input data is simply copied a block at a time).
-   <p>
-
-   <a href="#Z_DEFAULT_COMPRESSION">Z_DEFAULT_COMPRESSION</a> requests a default compromise between speed and
-   compression (currently equivalent to level 6).
-   <p>
-
-     <a href="#deflateInit">deflateInit</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not
-   enough memory, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if level is not a valid compression level,
-   <a href="#Z_VERSION_ERROR">Z_VERSION_ERROR</a> if the zlib library version (<a href="#zlib_version">zlib_version</a>) is incompatible
-   with the version assumed by the caller (ZLIB_VERSION).
-   <a href="#msg">msg</a> is set to null if there is no error message.  <a href="#deflateInit">deflateInit</a> does not
-   perform any compression: this will be done by <a href="#deflate">deflate</a>().
-   <p>
-
-<font color="Blue"><dt>  int  <a name="deflate">deflate</a> (<a href="#z_streamp">z_streamp</a> strm, int flush);</font>
-<dd>
-    <a href="#deflate">deflate</a> compresses as much data as possible, and stops when the input
-  buffer becomes empty or the output buffer becomes full. It may introduce some
-  output latency (reading input without producing any output) except when
-  forced to flush.<p>
-
-    The detailed semantics are as follows. <a href="#deflate">deflate</a> performs one or both of the
-  following actions:
-
-  <ul>
-  <li> Compress more input starting at <a href="#next_in">next_in</a> and update <a href="#next_in">next_in</a> and <a href="#avail_in">avail_in</a>
-    accordingly. If not all input can be processed (because there is not
-    enough room in the output buffer), <a href="#next_in">next_in</a> and <a href="#avail_in">avail_in</a> are updated and
-    processing will resume at this point for the next call of <a href="#deflate">deflate</a>().
-
-  <li>
-    Provide more output starting at <a href="#next_out">next_out</a> and update <a href="#next_out">next_out</a> and <a href="#avail_out">avail_out</a>
-    accordingly. This action is forced if the parameter flush is non zero.
-    Forcing flush frequently degrades the compression ratio, so this parameter
-    should be set only when necessary (in interactive applications).
-    Some output may be provided even if flush is not set.
-  </ul> <p>
-
-  Before the call of <a href="#deflate">deflate</a>(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming
-  more output, and updating <a href="#avail_in">avail_in</a> or <a href="#avail_out">avail_out</a> accordingly ; <a href="#avail_out">avail_out</a>
-  should never be zero before the call. The application can consume the
-  compressed output when it wants, for example when the output buffer is full
-  (<a href="#avail_out">avail_out</a> == 0), or after each call of <a href="#deflate">deflate</a>(). If <a href="#deflate">deflate</a> returns <a href="#Z_OK">Z_OK</a>
-  and with zero <a href="#avail_out">avail_out</a>, it must be called again after making room in the
-  output buffer because there might be more output pending.
-  <p>
-
-    If the parameter flush is set to <a href="#Z_SYNC_FLUSH">Z_SYNC_FLUSH</a>, all pending output is
-  flushed to the output buffer and the output is aligned on a byte boundary, so
-  that the decompressor can get all input data available so far. (In particular
-  <a href="#avail_in">avail_in</a> is zero after the call if enough output space has been provided
-  before the call.)  Flushing may degrade compression for some compression
-  algorithms and so it should be used only when necessary.
-  <p>
-
-    If flush is set to <a href="#Z_FULL_FLUSH">Z_FULL_FLUSH</a>, all output is flushed as with
-  <a href="#Z_SYNC_FLUSH">Z_SYNC_FLUSH</a>, and the compression <a href="#state">state</a> is reset so that decompression can
-  restart from this point if previous compressed data has been damaged or if
-  random access is desired. Using <a href="#Z_FULL_FLUSH">Z_FULL_FLUSH</a> too often can seriously degrade
-  the compression.
-  <p>
-
-    If <a href="#deflate">deflate</a> returns with <a href="#avail_out">avail_out</a> == 0, this function must be called again
-  with the same value of the flush parameter and more output space (updated
-  <a href="#avail_out">avail_out</a>), until the flush is complete (<a href="#deflate">deflate</a> returns with non-zero
-  <a href="#avail_out">avail_out</a>).
-  <p>
-
-    If the parameter flush is set to <a href="#Z_FINISH">Z_FINISH</a>, pending input is processed,
-  pending output is flushed and <a href="#deflate">deflate</a> returns with <a href="#Z_STREAM_END">Z_STREAM_END</a> if there
-  was enough output space ; if <a href="#deflate">deflate</a> returns with <a href="#Z_OK">Z_OK</a>, this function must be
-  called again with <a href="#Z_FINISH">Z_FINISH</a> and more output space (updated <a href="#avail_out">avail_out</a>) but no
-  more input data, until it returns with <a href="#Z_STREAM_END">Z_STREAM_END</a> or an error. After
-  <a href="#deflate">deflate</a> has returned <a href="#Z_STREAM_END">Z_STREAM_END</a>, the only possible operations on the
-  stream are <a href="#deflateReset">deflateReset</a> or <a href="#deflateEnd">deflateEnd</a>.
-  <p>
-
-    <a href="#Z_FINISH">Z_FINISH</a> can be used immediately after <a href="#deflateInit">deflateInit</a> if all the compression
-  is to be done in a single step. In this case, <a href="#avail_out">avail_out</a> must be at least
-  0.1% larger than <a href="#avail_in">avail_in</a> plus 12 bytes.  If <a href="#deflate">deflate</a> does not return
-  <a href="#Z_STREAM_END">Z_STREAM_END</a>, then it must be called again as described above.
-  <p>
-
-    <a href="#deflate">deflate</a>() sets strm-&gt <a href="#adler">adler</a> to the <a href="#adler32">adler32</a> checksum of all input read
-  so far (that is, <a href="#total_in">total_in</a> bytes).
-  <p>
-
-    <a href="#deflate">deflate</a>() may update <a href="#data_type">data_type</a> if it can make a good guess about
-  the input data type (<a href="#Z_ASCII">Z_ASCII</a> or <a href="#Z_BINARY">Z_BINARY</a>). In doubt, the data is considered
-  binary. This field is only for information purposes and does not affect
-  the compression algorithm in any manner.
-  <p>
-
-    <a href="#deflate">deflate</a>() returns <a href="#Z_OK">Z_OK</a> if some progress has been made (more input
-  processed or more output produced), <a href="#Z_STREAM_END">Z_STREAM_END</a> if all input has been
-  consumed and all output has been produced (only when flush is set to
-  <a href="#Z_FINISH">Z_FINISH</a>), <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the stream <a href="#state">state</a> was inconsistent (for example
-  if <a href="#next_in">next_in</a> or <a href="#next_out">next_out</a> was NULL), <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a> if no progress is possible
-  (for example <a href="#avail_in">avail_in</a> or <a href="#avail_out">avail_out</a> was zero).
-  <p>
-
-<font color="Blue"><dt>  int  <a name="deflateEnd">deflateEnd</a> (<a href="#z_streamp">z_streamp</a> strm);</font>
-<dd>
-     All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any
-   pending output.
-   <p>
-
-     <a href="#deflateEnd">deflateEnd</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the
-   stream <a href="#state">state</a> was inconsistent, <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a> if the stream was freed
-   prematurely (some input or output was discarded). In the error case,
-   <a href="#msg">msg</a> may be set but then points to a static string (which must not be
-   deallocated).
-   <p>
-
-<font color="Blue"><dt>  int  <a name="inflateInit">inflateInit</a> (<a href="#z_streamp">z_streamp</a> strm);</font>
-<dd>
-	Initializes the internal stream <a href="#state">state</a> for decompression. The fields
-   <a href="#next_in">next_in</a>, <a href="#avail_in">avail_in</a>, <a href="#zalloc">zalloc</a>, <a href="#zfree">zfree</a> and <a href="#opaque">opaque</a> must be initialized before by
-   the caller. If <a href="#next_in">next_in</a> is not <a href="#Z_NULL">Z_NULL</a> and <a href="#avail_in">avail_in</a> is large enough (the exact
-   value depends on the compression method), <a href="#inflateInit">inflateInit</a> determines the
-   compression method from the zlib header and allocates all data structures
-   accordingly ; otherwise the allocation will be deferred to the first call of
-   <a href="#inflate">inflate</a>.  If <a href="#zalloc">zalloc</a> and <a href="#zfree">zfree</a> are set to <a href="#Z_NULL">Z_NULL</a>, <a href="#inflateInit">inflateInit</a> updates them to
-   use default allocation functions.
-   <p>
-
-     <a href="#inflateInit">inflateInit</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not enough
-   memory, <a href="#Z_VERSION_ERROR">Z_VERSION_ERROR</a> if the zlib library version is incompatible with the
-   version assumed by the caller.  <a href="#msg">msg</a> is set to null if there is no error
-   message. <a href="#inflateInit">inflateInit</a> does not perform any decompression apart from reading
-   the zlib header if present: this will be done by <a href="#inflate">inflate</a>().  (So <a href="#next_in">next_in</a> and
-   <a href="#avail_in">avail_in</a> may be modified, but <a href="#next_out">next_out</a> and <a href="#avail_out">avail_out</a> are unchanged.)
-   <p>
-
-<font color="Blue"><dt>  int  <a name="inflate">inflate</a> (<a href="#z_streamp">z_streamp</a> strm, int flush);</font>
-<dd>
-    <a href="#inflate">inflate</a> decompresses as much data as possible, and stops when the input
-  buffer becomes empty or the output buffer becomes full. It may some
-  introduce some output latency (reading input without producing any output)
-  except when forced to flush.
-  <p>
-
-  The detailed semantics are as follows. <a href="#inflate">inflate</a> performs one or both of the
-  following actions:
-
-  <ul>
-  <li> Decompress more input starting at <a href="#next_in">next_in</a> and update <a href="#next_in">next_in</a> and <a href="#avail_in">avail_in</a>
-    accordingly. If not all input can be processed (because there is not
-    enough room in the output buffer), <a href="#next_in">next_in</a> is updated and processing
-    will resume at this point for the next call of <a href="#inflate">inflate</a>().
-
-  <li> Provide more output starting at <a href="#next_out">next_out</a> and update <a href="#next_out">next_out</a> and
-    <a href="#avail_out">avail_out</a> accordingly.  <a href="#inflate">inflate</a>() provides as much output as possible,
-    until there is no more input data or no more space in the output buffer
-    (see below about the flush parameter).
-  </ul> <p>
-
-  Before the call of <a href="#inflate">inflate</a>(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming
-  more output, and updating the next_* and avail_* values accordingly.
-  The application can consume the uncompressed output when it wants, for
-  example when the output buffer is full (<a href="#avail_out">avail_out</a> == 0), or after each
-  call of <a href="#inflate">inflate</a>(). If <a href="#inflate">inflate</a> returns <a href="#Z_OK">Z_OK</a> and with zero <a href="#avail_out">avail_out</a>, it
-  must be called again after making room in the output buffer because there
-  might be more output pending.
-  <p>
-
-    If the parameter flush is set to <a href="#Z_SYNC_FLUSH">Z_SYNC_FLUSH</a>, <a href="#inflate">inflate</a> flushes as much
-  output as possible to the output buffer. The flushing behavior of <a href="#inflate">inflate</a> is
-  not specified for values of the flush parameter other than <a href="#Z_SYNC_FLUSH">Z_SYNC_FLUSH</a>
-  and <a href="#Z_FINISH">Z_FINISH</a>, but the current implementation actually flushes as much output
-  as possible anyway.
-  <p>
-
-    <a href="#inflate">inflate</a>() should normally be called until it returns <a href="#Z_STREAM_END">Z_STREAM_END</a> or an
-  error. However if all decompression is to be performed in a single step
-  (a single call of <a href="#inflate">inflate</a>), the parameter flush should be set to
-  <a href="#Z_FINISH">Z_FINISH</a>. In this case all pending input is processed and all pending
-  output is flushed ; <a href="#avail_out">avail_out</a> must be large enough to hold all the
-  uncompressed data. (The size of the uncompressed data may have been saved
-  by the compressor for this purpose.) The next operation on this stream must
-  be <a href="#inflateEnd">inflateEnd</a> to deallocate the decompression <a href="#state">state</a>. The use of <a href="#Z_FINISH">Z_FINISH</a>
-  is never required, but can be used to inform <a href="#inflate">inflate</a> that a faster routine
-  may be used for the single <a href="#inflate">inflate</a>() call.
-  <p>
-
-     If a preset dictionary is needed at this point (see <a href="#inflateSetDictionary">inflateSetDictionary</a>
-  below), <a href="#inflate">inflate</a> sets strm-<a href="#adler">adler</a> to the <a href="#adler32">adler32</a> checksum of the
-  dictionary chosen by the compressor and returns <a href="#Z_NEED_DICT">Z_NEED_DICT</a> ; otherwise
-  it sets strm-&gt <a href="#adler">adler</a> to the <a href="#adler32">adler32</a> checksum of all output produced
-  so far (that is, <a href="#total_out">total_out</a> bytes) and returns <a href="#Z_OK">Z_OK</a>, <a href="#Z_STREAM_END">Z_STREAM_END</a> or
-  an error code as described below. At the end of the stream, <a href="#inflate">inflate</a>()
-  checks that its computed <a href="#adler32">adler32</a> checksum is equal to that saved by the
-  compressor and returns <a href="#Z_STREAM_END">Z_STREAM_END</a> only if the checksum is correct.
-  <p>
-
-    <a href="#inflate">inflate</a>() returns <a href="#Z_OK">Z_OK</a> if some progress has been made (more input processed
-  or more output produced), <a href="#Z_STREAM_END">Z_STREAM_END</a> if the end of the compressed data has
-  been reached and all uncompressed output has been produced, <a href="#Z_NEED_DICT">Z_NEED_DICT</a> if a
-  preset dictionary is needed at this point, <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a> if the input data was
-  corrupted (input stream not conforming to the zlib format or incorrect
-  <a href="#adler32">adler32</a> checksum), <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the stream structure was inconsistent
-  (for example if <a href="#next_in">next_in</a> or <a href="#next_out">next_out</a> was NULL), <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not
-  enough memory, <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a> if no progress is possible or if there was not
-  enough room in the output buffer when <a href="#Z_FINISH">Z_FINISH</a> is used. In the <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a>
-  case, the application may then call <a href="#inflateSync">inflateSync</a> to look for a good
-  compression block.
-  <p>
-
-<font color="Blue"><dt>  int  <a name="inflateEnd">inflateEnd</a> (<a href="#z_streamp">z_streamp</a> strm);</font>
-<dd>
-     All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any
-   pending output.
-   <p>
-
-     <a href="#inflateEnd">inflateEnd</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the stream <a href="#state">state</a>
-   was inconsistent. In the error case, <a href="#msg">msg</a> may be set but then points to a
-   static string (which must not be deallocated).
-</dl>
-<hr>
-<a name="Advanced functions"><h2> Advanced functions </h2>
-    The following functions are needed only in some special applications.
-<h3> Function list </h3>
-<ul>
-<li>  int  <a href="#deflateInit2">deflateInit2</a> (<a href="#z_streamp">z_streamp</a> strm,
-<li> int  <a href="#deflateSetDictionary">deflateSetDictionary</a> (<a href="#z_streamp">z_streamp</a> strm, const Bytef *dictionary, uInt  dictLength);
-<li> int  <a href="#deflateCopy">deflateCopy</a> (<a href="#z_streamp">z_streamp</a> dest, <a href="#z_streamp">z_streamp</a> source);
-<li> int  <a href="#deflateReset">deflateReset</a> (<a href="#z_streamp">z_streamp</a> strm);
-<li> int  <a href="#deflateParams">deflateParams</a> (<a href="#z_streamp">z_streamp</a> strm, int level, int strategy);
-<li> int  <a href="#inflateInit2">inflateInit2</a> (<a href="#z_streamp">z_streamp</a> strm, int  windowBits);
-<li>  int  <a href="#inflateSetDictionary">inflateSetDictionary</a> (<a href="#z_streamp">z_streamp</a> strm, const Bytef *dictionary, uInt  dictLength);
-<li> int  <a href="#inflateSync">inflateSync</a> (<a href="#z_streamp">z_streamp</a> strm);
-<li> int  <a href="#inflateReset">inflateReset</a> (<a href="#z_streamp">z_streamp</a> strm);
-
-</ul>
-<h3> Function description </h3>
-<dl>
-<font color="Blue"><dt>  int  <a name="deflateInit2">deflateInit2</a> (<a href="#z_streamp">z_streamp</a> strm, int  level, int  method, int  windowBits, int  memLevel, int  strategy);</font>
-
-<dd> This is another version of <a href="#deflateInit">deflateInit</a> with more compression options. The
-   fields <a href="#next_in">next_in</a>, <a href="#zalloc">zalloc</a>, <a href="#zfree">zfree</a> and <a href="#opaque">opaque</a> must be initialized before by
-   the caller.<p>
-
-     The method parameter is the compression method. It must be <a href="#Z_DEFLATED">Z_DEFLATED</a> in
-   this version of the library.<p>
-
-     The windowBits parameter is the base two logarithm of the window size
-   (the size of the history buffer).  It should be in the range 8..15 for this
-   version of the library. Larger values of this parameter result in better
-   compression at the expense of memory usage. The default value is 15 if
-   <a href="#deflateInit">deflateInit</a> is used instead.<p>
-
-     The memLevel parameter specifies how much memory should be allocated
-   for the internal compression <a href="#state">state</a>. memLevel=1 uses minimum memory but
-   is slow and reduces compression ratio ; memLevel=9 uses maximum memory
-   for optimal speed. The default value is 8. See zconf.h for total memory
-   usage as a function of windowBits and memLevel.<p>
-
-     The strategy parameter is used to tune the compression algorithm. Use the
-   value <a href="#Z_DEFAULT_STRATEGY">Z_DEFAULT_STRATEGY</a> for normal data, <a href="#Z_FILTERED">Z_FILTERED</a> for data produced by a
-   filter (or predictor), or <a href="#Z_HUFFMAN_ONLY">Z_HUFFMAN_ONLY</a> to force Huffman encoding only (no
-   string match).  Filtered data consists mostly of small values with a
-   somewhat random distribution. In this case, the compression algorithm is
-   tuned to <a href="#compress">compress</a> them better. The effect of <a href="#Z_FILTERED">Z_FILTERED</a> is to force more
-   Huffman coding and less string matching ; it is somewhat intermediate
-   between Z_DEFAULT and <a href="#Z_HUFFMAN_ONLY">Z_HUFFMAN_ONLY</a>. The strategy parameter only affects
-   the compression ratio but not the correctness of the compressed output even
-   if it is not set appropriately.<p>
-
-      <a href="#deflateInit2">deflateInit2</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not enough
-   memory, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if a parameter is invalid (such as an invalid
-   method). <a href="#msg">msg</a> is set to null if there is no error message.  <a href="#deflateInit2">deflateInit2</a> does
-   not perform any compression: this will be done by <a href="#deflate">deflate</a>().<p>
-
-<font color="Blue"><dt> int  <a name="deflateSetDictionary">deflateSetDictionary</a> (<a href="#z_streamp">z_streamp</a> strm, const Bytef *dictionary, uInt  dictLength);</font>
-<dd>
-     Initializes the compression dictionary from the given byte sequence
-   without producing any compressed output. This function must be called
-   immediately after <a href="#deflateInit">deflateInit</a>, <a href="#deflateInit2">deflateInit2</a> or <a href="#deflateReset">deflateReset</a>, before any
-   call of <a href="#deflate">deflate</a>. The compressor and decompressor must use exactly the same
-   dictionary (see <a href="#inflateSetDictionary">inflateSetDictionary</a>).<p>
-
-     The dictionary should consist of strings (byte sequences) that are likely
-   to be encountered later in the data to be compressed, with the most commonly
-   used strings preferably put towards the end of the dictionary. Using a
-   dictionary is most useful when the data to be compressed is short and can be
-   predicted with good accuracy ; the data can then be compressed better than
-   with the default empty dictionary.<p>
-
-     Depending on the size of the compression data structures selected by
-   <a href="#deflateInit">deflateInit</a> or <a href="#deflateInit2">deflateInit2</a>, a part of the dictionary may in effect be
-   discarded, for example if the dictionary is larger than the window size in
-   <a href="#deflate">deflate</a> or deflate2. Thus the strings most likely to be useful should be
-   put at the end of the dictionary, not at the front.<p>
-
-     Upon return of this function, strm-&gt <a href="#adler">adler</a> is set to the Adler32 value
-   of the dictionary ; the decompressor may later use this value to determine
-   which dictionary has been used by the compressor. (The Adler32 value
-   applies to the whole dictionary even if only a subset of the dictionary is
-   actually used by the compressor.)<p>
-
-     <a href="#deflateSetDictionary">deflateSetDictionary</a> returns <a href="#Z_OK">Z_OK</a> if success, or <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if a
-   parameter is invalid (such as NULL dictionary) or the stream <a href="#state">state</a> is
-   inconsistent (for example if <a href="#deflate">deflate</a> has already been called for this stream
-   or if the compression method is bsort). <a href="#deflateSetDictionary">deflateSetDictionary</a> does not
-   perform any compression: this will be done by <a href="#deflate">deflate</a>().<p>
-
-<font color="Blue"><dt> int  <a name="deflateCopy">deflateCopy</a> (<a href="#z_streamp">z_streamp</a> dest, <a href="#z_streamp">z_streamp</a> source);</font>
-<dd>
-     Sets the destination stream as a complete copy of the source stream.<p>
-
-     This function can be useful when several compression strategies will be
-   tried, for example when there are several ways of pre-processing the input
-   data with a filter. The streams that will be discarded should then be freed
-   by calling <a href="#deflateEnd">deflateEnd</a>.  Note that <a href="#deflateCopy">deflateCopy</a> duplicates the internal
-   compression <a href="#state">state</a> which can be quite large, so this strategy is slow and
-   can consume lots of memory.<p>
-
-     <a href="#deflateCopy">deflateCopy</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not
-   enough memory, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the source stream <a href="#state">state</a> was inconsistent
-   (such as <a href="#zalloc">zalloc</a> being NULL). <a href="#msg">msg</a> is left unchanged in both source and
-   destination.<p>
-
-<font color="Blue"><dt> int  <a name="deflateReset">deflateReset</a> (<a href="#z_streamp">z_streamp</a> strm);</font>
-<dd>     This function is equivalent to <a href="#deflateEnd">deflateEnd</a> followed by <a href="#deflateInit">deflateInit</a>,
-   but does not free and reallocate all the internal compression <a href="#state">state</a>.
-   The stream will keep the same compression level and any other attributes
-   that may have been set by <a href="#deflateInit2">deflateInit2</a>.<p>
-
-      <a href="#deflateReset">deflateReset</a> returns <a href="#Z_OK">Z_OK</a> if success, or <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the source
-   stream <a href="#state">state</a> was inconsistent (such as <a href="#zalloc">zalloc</a> or <a href="#state">state</a> being NULL).<p>
-
-<font color="Blue"><dt> int  <a name="deflateParams">deflateParams</a> (<a href="#z_streamp">z_streamp</a> strm, int level, int strategy);</font>
-<dd>
-     Dynamically update the compression level and compression strategy.  The
-   interpretation of level and strategy is as in <a href="#deflateInit2">deflateInit2</a>.  This can be
-   used to switch between compression and straight copy of the input data, or
-   to switch to a different kind of input data requiring a different
-   strategy. If the compression level is changed, the input available so far
-   is compressed with the old level (and may be flushed); the new level will
-   take effect only at the next call of <a href="#deflate">deflate</a>().<p>
-
-     Before the call of <a href="#deflateParams">deflateParams</a>, the stream <a href="#state">state</a> must be set as for
-   a call of <a href="#deflate">deflate</a>(), since the currently available input may have to
-   be compressed and flushed. In particular, strm-&gt <a href="#avail_out">avail_out</a> must be
-   non-zero.<p>
-
-     <a href="#deflateParams">deflateParams</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the source
-   stream <a href="#state">state</a> was inconsistent or if a parameter was invalid, <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a>
-   if strm-&gtavail_out was zero.<p>
-
-<font color="Blue"><dt> int  <a name="inflateInit2">inflateInit2</a> (<a href="#z_streamp">z_streamp</a> strm, int  windowBits);</font>
-
-<dd>     This is another version of <a href="#inflateInit">inflateInit</a> with an extra parameter. The
-   fields <a href="#next_in">next_in</a>, <a href="#avail_in">avail_in</a>, <a href="#zalloc">zalloc</a>, <a href="#zfree">zfree</a> and <a href="#opaque">opaque</a> must be initialized
-   before by the caller.<p>
-
-     The windowBits parameter is the base two logarithm of the maximum window
-   size (the size of the history buffer).  It should be in the range 8..15 for
-   this version of the library. The default value is 15 if <a href="#inflateInit">inflateInit</a> is used
-   instead. If a compressed stream with a larger window size is given as
-   input, <a href="#inflate">inflate</a>() will return with the error code <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a> instead of
-   trying to allocate a larger window.<p>
-
-      <a href="#inflateInit2">inflateInit2</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_MEM_ERROR">Z_MEM_ERROR</a> if there was not enough
-   memory, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if a parameter is invalid (such as a negative
-   memLevel). <a href="#msg">msg</a> is set to null if there is no error message.  <a href="#inflateInit2">inflateInit2</a>
-   does not perform any decompression apart from reading the zlib header if
-   present: this will be done by <a href="#inflate">inflate</a>(). (So <a href="#next_in">next_in</a> and <a href="#avail_in">avail_in</a> may be
-   modified, but <a href="#next_out">next_out</a> and <a href="#avail_out">avail_out</a> are unchanged.)<p>
-
-<font color="Blue"><dt>  int  <a name="inflateSetDictionary">inflateSetDictionary</a> (<a href="#z_streamp">z_streamp</a> strm, const Bytef *dictionary, uInt  dictLength);</font>
-<dd>
-     Initializes the decompression dictionary from the given uncompressed byte
-   sequence. This function must be called immediately after a call of <a href="#inflate">inflate</a>
-   if this call returned <a href="#Z_NEED_DICT">Z_NEED_DICT</a>. The dictionary chosen by the compressor
-   can be determined from the Adler32 value returned by this call of
-   <a href="#inflate">inflate</a>. The compressor and decompressor must use exactly the same
-   dictionary (see <a href="#deflateSetDictionary">deflateSetDictionary</a>).<p>
-
-     <a href="#inflateSetDictionary">inflateSetDictionary</a> returns <a href="#Z_OK">Z_OK</a> if success, <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if a
-   parameter is invalid (such as NULL dictionary) or the stream <a href="#state">state</a> is
-   inconsistent, <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a> if the given dictionary doesn't match the
-   expected one (incorrect Adler32 value). <a href="#inflateSetDictionary">inflateSetDictionary</a> does not
-   perform any decompression: this will be done by subsequent calls of
-   <a href="#inflate">inflate</a>().<p>
-
-<font color="Blue"><dt> int  <a name="inflateSync">inflateSync</a> (<a href="#z_streamp">z_streamp</a> strm);</font>
-
-<dd>    Skips invalid compressed data until a full flush point (see above the
-  description of <a href="#deflate">deflate</a> with <a href="#Z_FULL_FLUSH">Z_FULL_FLUSH</a>) can be found, or until all
-  available input is skipped. No output is provided.<p>
-
-    <a href="#inflateSync">inflateSync</a> returns <a href="#Z_OK">Z_OK</a> if a full flush point has been found, <a href="#Z_BUF_ERROR">Z_BUF_ERROR</a>
-  if no more input was provided, <a href="#Z_DATA_ERROR">Z_DATA_ERROR</a> if no flush point has been found,
-  or <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the stream structure was inconsistent. In the success
-  case, the application may save the current current value of <a href="#total_in">total_in</a> which
-  indicates where valid compressed data was found. In the error case, the
-  application may repeatedly call <a href="#inflateSync">inflateSync</a>, providing more input each time,
-  until success or end of the input data.<p>
-
-<font color="Blue"><dt> int  <a name="inflateReset">inflateReset</a> (<a href="#z_streamp">z_streamp</a> strm);</font>
-<dd>
-     This function is equivalent to <a href="#inflateEnd">inflateEnd</a> followed by <a href="#inflateInit">inflateInit</a>,
-   but does not free and reallocate all the internal decompression <a href="#state">state</a>.
-   The stream will keep attributes that may have been set by <a href="#inflateInit2">inflateInit2</a>.
-   <p>
-
-      <a href="#inflateReset">inflateReset</a> returns <a href="#Z_OK">Z_OK</a> if success, or <a href="#Z_STREAM_ERROR">Z_STREAM_ERROR</a> if the source
-   stream <a href="#state">state</a> was inconsistent (such as <a href="#zalloc">zalloc</a> or <a href="#state">state</a> being NULL).
-   <p>
-</dl>
-
-<hr>
-<a name="Checksum functions"><h2> Checksum functions </h2>
-     These functions are not related to compression but are exported
-   anyway because they might be useful in applications using the
-   compression library.
-<h3> Function list </h3>
-<ul>
-<li> uLong  <a href="#adler32">adler32</a> (uLong <a href="#adler">adler</a>, const Bytef *buf, uInt len);
-<li> uLong  <a href="#crc32">crc32</a>   (uLong crc, const Bytef *buf, uInt len);
-</ul>
-<h3> Function description </h3>
-<dl>
-<font color="Blue"><dt> uLong  <a name="adler32">adler32</a> (uLong <a href="#adler">adler</a>, const Bytef *buf, uInt len);</font>
-<dd>
-     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
-   return the updated checksum. If buf is NULL, this function returns
-   the required initial value for the checksum.
-   <p>
-   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
-   much faster. Usage example:
-   <pre>
-
-     uLong <a href="#adler">adler</a> = <a href="#adler32">adler32</a>(0L, <a href="#Z_NULL">Z_NULL</a>, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       <a href="#adler">adler</a> = <a href="#adler32">adler32</a>(<a href="#adler">adler</a>, buffer, length);
-     }
-     if (<a href="#adler">adler</a> != original_adler) error();
-   </pre>
-
-<font color="Blue"><dt> uLong  <a name="crc32">crc32</a>   (uLong crc, const Bytef *buf, uInt len);</font>
-<dd>
-     Update a running crc with the bytes buf[0..len-1] and return the updated
-   crc. If buf is NULL, this function returns the required initial value
-   for the crc. Pre- and post-conditioning (one's complement) is performed
-   within this function so it shouldn't be done by the application.
-   Usage example:
-   <pre>
-
-     uLong crc = <a href="#crc32">crc32</a>(0L, <a href="#Z_NULL">Z_NULL</a>, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       crc = <a href="#crc32">crc32</a>(crc, buffer, length);
-     }
-     if (crc != original_crc) error();
-   </pre>
-</dl>
-<hr>
-<a name="struct z_stream_s"><h2> struct z_stream_s </h2>
-<font color="Blue">
-<a name="z_stream_s">
-<pre>
-typedef struct z_stream_s {
-    Bytef    *<a name="next_in">next_in</a>;  /* next input byte */
-    uInt     <a name="avail_in">avail_in</a>;  /* number of bytes available at <a href="#next_in">next_in</a> */
-    uLong    <a name="total_in">total_in</a>;  /* total nb of input bytes read so far */
-
-    Bytef    *<a name="next_out">next_out</a>; /* next output byte should be put there */
-    uInt     <a name="avail_out">avail_out</a>; /* remaining free space at <a href="#next_out">next_out</a> */
-    uLong    <a name="total_out">total_out</a>; /* total nb of bytes output so far */
-
-    char     *<a name="msg">msg</a>;      /* last error message, NULL if no error */
-    struct internal_state FAR *<a name="state">state</a>; /* not visible by applications */
-
-    alloc_func <a name="zalloc">zalloc</a>;  /* used to allocate the internal <a href="#state">state</a> */
-    free_func  <a name="zfree">zfree</a>;   /* used to free the internal <a href="#state">state</a> */
-    voidpf     <a name="opaque">opaque</a>;  /* private data object passed to <a href="#zalloc">zalloc</a> and <a href="#zfree">zfree</a> */
-
-    int     <a name="data_type">data_type</a>;  /* best guess about the data type: ascii or binary */
-    uLong   <a name="adler">adler</a>;      /* <a href="#adler32">adler32</a> value of the uncompressed data */
-    uLong   <a name="reserved">reserved</a>;   /* <a href="#reserved">reserved</a> for future use */
-} <a href="#z_stream_s">z_stream</a> ;
-
-typedef <a href="#z_stream_s">z_stream</a> FAR * <a name="z_streamp">z_streamp</a>;  ÿ
-</pre>
-</font>
-   The application must update <a href="#next_in">next_in</a> and <a href="#avail_in">avail_in</a> when <a href="#avail_in">avail_in</a> has
-   dropped to zero. It must update <a href="#next_out">next_out</a> and <a href="#avail_out">avail_out</a> when <a href="#avail_out">avail_out</a>
-   has dropped to zero. The application must initialize <a href="#zalloc">zalloc</a>, <a href="#zfree">zfree</a> and
-   <a href="#opaque">opaque</a> before calling the init function. All other fields are set by the
-   compression library and must not be updated by the application. <p>
-
-   The <a href="#opaque">opaque</a> value provided by the application will be passed as the first
-   parameter for calls of <a href="#zalloc">zalloc</a> and <a href="#zfree">zfree</a>. This can be useful for custom
-   memory management. The compression library attaches no meaning to the
-   <a href="#opaque">opaque</a> value. <p>
-
-   <a href="#zalloc">zalloc</a> must return <a href="#Z_NULL">Z_NULL</a> if there is not enough memory for the object.
-   If zlib is used in a multi-threaded application, <a href="#zalloc">zalloc</a> and <a href="#zfree">zfree</a> must be
-   thread safe. <p>
-
-   On 16-bit systems, the functions <a href="#zalloc">zalloc</a> and <a href="#zfree">zfree</a> must be able to allocate
-   exactly 65536 bytes, but will not be required to allocate more than this
-   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
-   pointers returned by <a href="#zalloc">zalloc</a> for objects of exactly 65536 bytes *must*
-   have their offset normalized to zero. The default allocation function
-   provided by this library ensures this (see zutil.c). To reduce memory
-   requirements and avoid any allocation of 64K objects, at the expense of
-   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
-   <p>
-
-   The fields <a href="#total_in">total_in</a> and <a href="#total_out">total_out</a> can be used for statistics or
-   progress reports. After compression, <a href="#total_in">total_in</a> holds the total size of
-   the uncompressed data and may be saved for use in the decompressor
-   (particularly if the decompressor wants to decompress everything in
-   a single step). <p>
-
-<hr>
-<a name="Constants"><h2> Constants </h2>
-<font color="Blue">
-<pre>
-#define <a name="Z_NO_FLUSH">Z_NO_FLUSH</a>      0
-#define <a name="Z_PARTIAL_FLUSH">Z_PARTIAL_FLUSH</a> 1
-	/* will be removed, use <a href="#Z_SYNC_FLUSH">Z_SYNC_FLUSH</a> instead */
-#define <a name="Z_SYNC_FLUSH">Z_SYNC_FLUSH</a>    2
-#define <a name="Z_FULL_FLUSH">Z_FULL_FLUSH</a>    3
-#define <a name="Z_FINISH">Z_FINISH</a>        4
-/* Allowed flush values ; see <a href="#deflate">deflate</a>() below for details */
-
-#define <a name="Z_OK">Z_OK</a>            0
-#define <a name="Z_STREAM_END">Z_STREAM_END</a>    1
-#define <a name="Z_NEED_DICT">Z_NEED_DICT</a>     2
-#define <a name="Z_ERRNO">Z_ERRNO</a>        (-1)
-#define <a name="Z_STREAM_ERROR">Z_STREAM_ERROR</a> (-2)
-#define <a name="Z_DATA_ERROR">Z_DATA_ERROR</a>   (-3)
-#define <a name="Z_MEM_ERROR">Z_MEM_ERROR</a>    (-4)
-#define <a name="Z_BUF_ERROR">Z_BUF_ERROR</a>    (-5)
-#define <a name="Z_VERSION_ERROR">Z_VERSION_ERROR</a> (-6)
-/* Return codes for the compression/decompression functions. Negative
- * values are errors, positive values are used for special but normal events.
- */
-
-#define <a name="Z_NO_COMPRESSION">Z_NO_COMPRESSION</a>         0
-#define <a name="Z_BEST_SPEED">Z_BEST_SPEED</a>             1
-#define <a name="Z_BEST_COMPRESSION">Z_BEST_COMPRESSION</a>       9
-#define <a name="Z_DEFAULT_COMPRESSION">Z_DEFAULT_COMPRESSION</a>  (-1)
-/* compression levels */
-
-#define <a name="Z_FILTERED">Z_FILTERED</a>            1
-#define <a name="Z_HUFFMAN_ONLY">Z_HUFFMAN_ONLY</a>        2
-#define <a name="Z_DEFAULT_STRATEGY">Z_DEFAULT_STRATEGY</a>    0
-/* compression strategy ; see <a href="#deflateInit2">deflateInit2</a>() below for details */
-
-#define <a name="Z_BINARY">Z_BINARY</a>   0
-#define <a name="Z_ASCII">Z_ASCII</a>    1
-#define <a name="Z_UNKNOWN">Z_UNKNOWN</a>  2
-/* Possible values of the <a href="#data_type">data_type</a> field */
-
-#define <a name="Z_DEFLATED">Z_DEFLATED</a>   8
-/* The <a href="#deflate">deflate</a> compression method (the only one supported in this version) */
-
-#define <a name="Z_NULL">Z_NULL</a>  0  /* for initializing <a href="#zalloc">zalloc</a>, <a href="#zfree">zfree</a>, <a href="#opaque">opaque</a> */
-
-#define <a name="zlib_version">zlib_version</a> <a href="#zlibVersion">zlibVersion</a>()
-/* for compatibility with versions less than 1.0.2 */
-</pre>
-</font>
-
-<hr>
-<a name="Misc"><h2> Misc </h2>
- <a href="#deflateInit">deflateInit</a> and <a href="#inflateInit">inflateInit</a> are macros to allow checking the zlib version
- and the compiler's view of <a href="#z_stream_s">z_stream</a>.
- <p>
- Other functions:
- <dl>
- <font color="Blue"><dt> const char   *  <a name="zError">zError</a>           (int err);</font>
- <font color="Blue"><dt> int             <a name="inflateSyncPoint">inflateSyncPoint</a> (<a href="#z_streamp">z_streamp</a> z);</font>
- <font color="Blue"><dt> const uLongf *  <a name="get_crc_table">get_crc_table</a>    (void);</font>
- </dl>
- <hr>
- <font size="-1">
- Last update: Wed Oct 13 20:42:34 1999<br>
- piapi at csie.ntu.edu.tw
- </font>
-
-</body>
-</html>
diff --git a/third_party/zlib/projects/README.projects b/third_party/zlib/projects/README.projects
deleted file mode 100644
index 1c029e4..0000000
--- a/third_party/zlib/projects/README.projects
+++ /dev/null
@@ -1,41 +0,0 @@
-This directory contains project files for building zlib under various
-Integrated Development Environments (IDE).
-
-If you wish to submit a new project to this directory, you should comply
-to the following requirements.  Otherwise (e.g. if you wish to integrate
-a custom piece of code that changes the zlib interface or its behavior),
-please consider submitting the project to the contrib directory.
-
-
-Requirements
-============
-
-- The project must build zlib using the source files from the official
-  zlib source distribution, exclusively.
-
-- If the project produces redistributable builds (e.g. shared objects
-  or DLL files), these builds must be compatible to those produced by
-  makefiles, if such makefiles exist in the zlib distribution.
-  In particular, if the project produces a DLL build for the Win32
-  platform, this build must comply to the officially-ammended Win32 DLL
-  Application Binary Interface (ABI), described in win32/DLL_FAQ.txt.
-
-- The project may provide additional build targets, which depend on
-  3rd-party (unofficially-supported) software, present in the contrib
-  directory.  For example, it is possible to provide an "ASM build",
-  besides the officially-supported build, and have ASM source files
-  among its dependencies.
-
-- If there are significant differences between the project files created
-  by different versions of an IDE (e.g. Visual C++ 6.0 vs. 7.0), the name
-  of the project directory should contain the version number of the IDE
-  for which the project is intended (e.g. "visualc6" for Visual C++ 6.0,
-  or "visualc7" for Visual C++ 7.0 and 7.1).
-
-
-Current projects
-================
-
-visualc6/   by Simon-Pierre Cadieux <methodex at methodex.ca>
-            and Cosmin Truta <cosmint at cs.ubbcluj.ro>
-        Project for Microsoft Visual C++ 6.0
diff --git a/third_party/zlib/projects/visualc6/README.txt b/third_party/zlib/projects/visualc6/README.txt
deleted file mode 100644
index d0296c2..0000000
--- a/third_party/zlib/projects/visualc6/README.txt
+++ /dev/null
@@ -1,73 +0,0 @@
-Microsoft Developer Studio Project Files, Format Version 6.00 for zlib.
-
-Copyright (C) 2000-2004 Simon-Pierre Cadieux.
-Copyright (C) 2004 Cosmin Truta.
-For conditions of distribution and use, see copyright notice in zlib.h.
-
-
-This project builds the zlib binaries as follows:
-
-* Win32_DLL_Release\zlib1.dll       DLL build
-* Win32_DLL_Debug\zlib1d.dll        DLL build (debug version)
-* Win32_DLL_ASM_Release\zlib1.dll   DLL build using ASM code
-* Win32_DLL_ASM_Debug\zlib1d.dll    DLL build using ASM code (debug version)
-* Win32_LIB_Release\zlib.lib        static build
-* Win32_LIB_Debug\zlibd.lib         static build (debug version)
-* Win32_LIB_ASM_Release\zlib.lib    static build using ASM code
-* Win32_LIB_ASM_Debug\zlibd.lib     static build using ASM code (debug version)
-
-
-For more information regarding the DLL builds, please see the DLL FAQ
-in ..\..\win32\DLL_FAQ.txt.
-
-
-To build and test:
-
-1) On the main menu, select "File | Open Workspace".
-   Open "zlib.dsw".
-
-2) Select "Build | Set Active Configuration".
-   Choose the configuration you wish to build.
-
-3) Select "Build | Clean".
-
-4) Select "Build | Build ... (F7)".  Ignore warning messages about
-   not being able to find certain include files (e.g. alloc.h).
-
-5) If you built one of the sample programs (example or minigzip),
-   select "Build | Execute ... (Ctrl+F5)".
-
-
-To use:
-
-1) Select "Project | Settings (Alt+F7)".
-   Make note of the configuration names used in your project.
-   Usually, these names are "Win32 Release" and "Win32 Debug".
-
-2) In the Workspace window, select the "FileView" tab.
-   Right-click on the root item "Workspace '...'".
-   Select "Insert Project into Workspace".
-   Switch on the checkbox "Dependency of:", and select the name
-   of your project.  Open "zlib.dsp".
-
-3) Select "Build | Configurations".
-   For each configuration of your project:
-   3.1) Choose the zlib configuration you wish to use.
-   3.2) Click on "Add".
-   3.3) Set the new zlib configuration name to the name used by
-        the configuration from the current iteration.
-
-4) Select "Build | Set Active Configuration".
-   Choose the configuration you wish to build.
-
-5) Select "Build | Build ... (F7)".
-
-6) If you built an executable program, select
-   "Build | Execute ... (Ctrl+F5)".
-
-
-Note:
-
-To build the ASM-enabled code, you need Microsoft Assembler
-(ML.EXE).  You can get it by downloading and installing the
-latest Processor Pack for Visual C++ 6.0.
diff --git a/third_party/zlib/projects/visualc6/example.dsp b/third_party/zlib/projects/visualc6/example.dsp
deleted file mode 100644
index e072a37..0000000
--- a/third_party/zlib/projects/visualc6/example.dsp
+++ /dev/null
@@ -1,278 +0,0 @@
-# Microsoft Developer Studio Project File - Name="example" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=example - Win32 LIB Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "example.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "example.mak" CFG="example - Win32 LIB Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "example - Win32 DLL Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "example - Win32 DLL Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE "example - Win32 DLL ASM Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "example - Win32 DLL ASM Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE "example - Win32 LIB Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "example - Win32 LIB Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE "example - Win32 LIB ASM Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "example - Win32 LIB ASM Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "example - Win32 DLL Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "example___Win32_DLL_Release"
-# PROP BASE Intermediate_Dir "example___Win32_DLL_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Win32_DLL_Release"
-# PROP Intermediate_Dir "Win32_DLL_Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "example - Win32 DLL Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "example___Win32_DLL_Debug"
-# PROP BASE Intermediate_Dir "example___Win32_DLL_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Win32_DLL_Debug"
-# PROP Intermediate_Dir "Win32_DLL_Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ELSEIF  "$(CFG)" == "example - Win32 DLL ASM Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "example___Win32_DLL_ASM_Release"
-# PROP BASE Intermediate_Dir "example___Win32_DLL_ASM_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Win32_DLL_ASM_Release"
-# PROP Intermediate_Dir "Win32_DLL_ASM_Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "example - Win32 DLL ASM Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "example___Win32_DLL_ASM_Debug"
-# PROP BASE Intermediate_Dir "example___Win32_DLL_ASM_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Win32_DLL_ASM_Debug"
-# PROP Intermediate_Dir "Win32_DLL_ASM_Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ELSEIF  "$(CFG)" == "example - Win32 LIB Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "example___Win32_LIB_Release"
-# PROP BASE Intermediate_Dir "example___Win32_LIB_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Win32_LIB_Release"
-# PROP Intermediate_Dir "Win32_LIB_Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "example - Win32 LIB Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "example___Win32_LIB_Debug"
-# PROP BASE Intermediate_Dir "example___Win32_LIB_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Win32_LIB_Debug"
-# PROP Intermediate_Dir "Win32_LIB_Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ELSEIF  "$(CFG)" == "example - Win32 LIB ASM Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "example___Win32_LIB_ASM_Release"
-# PROP BASE Intermediate_Dir "example___Win32_LIB_ASM_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Win32_LIB_ASM_Release"
-# PROP Intermediate_Dir "Win32_LIB_ASM_Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "example - Win32 LIB ASM Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "example___Win32_LIB_ASM_Debug"
-# PROP BASE Intermediate_Dir "example___Win32_LIB_ASM_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Win32_LIB_ASM_Debug"
-# PROP Intermediate_Dir "Win32_LIB_ASM_Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "example - Win32 DLL Release"
-# Name "example - Win32 DLL Debug"
-# Name "example - Win32 DLL ASM Release"
-# Name "example - Win32 DLL ASM Debug"
-# Name "example - Win32 LIB Release"
-# Name "example - Win32 LIB Debug"
-# Name "example - Win32 LIB ASM Release"
-# Name "example - Win32 LIB ASM Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\..\example.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=..\..\zconf.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\zlib.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/third_party/zlib/projects/visualc6/minigzip.dsp b/third_party/zlib/projects/visualc6/minigzip.dsp
deleted file mode 100644
index f32024e..0000000
--- a/third_party/zlib/projects/visualc6/minigzip.dsp
+++ /dev/null
@@ -1,278 +0,0 @@
-# Microsoft Developer Studio Project File - Name="minigzip" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=minigzip - Win32 LIB Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "minigzip.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "minigzip.mak" CFG="minigzip - Win32 LIB Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "minigzip - Win32 DLL Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "minigzip - Win32 DLL Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE "minigzip - Win32 DLL ASM Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "minigzip - Win32 DLL ASM Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE "minigzip - Win32 LIB Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "minigzip - Win32 LIB Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE "minigzip - Win32 LIB ASM Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "minigzip - Win32 LIB ASM Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "minigzip - Win32 DLL Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "minigzip___Win32_DLL_Release"
-# PROP BASE Intermediate_Dir "minigzip___Win32_DLL_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Win32_DLL_Release"
-# PROP Intermediate_Dir "Win32_DLL_Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "minigzip - Win32 DLL Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "minigzip___Win32_DLL_Debug"
-# PROP BASE Intermediate_Dir "minigzip___Win32_DLL_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Win32_DLL_Debug"
-# PROP Intermediate_Dir "Win32_DLL_Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ELSEIF  "$(CFG)" == "minigzip - Win32 DLL ASM Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "minigzip___Win32_DLL_ASM_Release"
-# PROP BASE Intermediate_Dir "minigzip___Win32_DLL_ASM_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Win32_DLL_ASM_Release"
-# PROP Intermediate_Dir "Win32_DLL_ASM_Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "minigzip - Win32 DLL ASM Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "minigzip___Win32_DLL_ASM_Debug"
-# PROP BASE Intermediate_Dir "minigzip___Win32_DLL_ASM_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Win32_DLL_ASM_Debug"
-# PROP Intermediate_Dir "Win32_DLL_ASM_Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ELSEIF  "$(CFG)" == "minigzip - Win32 LIB Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "minigzip___Win32_LIB_Release"
-# PROP BASE Intermediate_Dir "minigzip___Win32_LIB_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Win32_LIB_Release"
-# PROP Intermediate_Dir "Win32_LIB_Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "minigzip - Win32 LIB Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "minigzip___Win32_LIB_Debug"
-# PROP BASE Intermediate_Dir "minigzip___Win32_LIB_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Win32_LIB_Debug"
-# PROP Intermediate_Dir "Win32_LIB_Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ELSEIF  "$(CFG)" == "minigzip - Win32 LIB ASM Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "minigzip___Win32_LIB_ASM_Release"
-# PROP BASE Intermediate_Dir "minigzip___Win32_LIB_ASM_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Win32_LIB_ASM_Release"
-# PROP Intermediate_Dir "Win32_LIB_ASM_Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "minigzip - Win32 LIB ASM Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "minigzip___Win32_LIB_ASM_Debug"
-# PROP BASE Intermediate_Dir "minigzip___Win32_LIB_ASM_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Win32_LIB_ASM_Debug"
-# PROP Intermediate_Dir "Win32_LIB_ASM_Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT BASE CPP /YX
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT CPP /YX
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "minigzip - Win32 DLL Release"
-# Name "minigzip - Win32 DLL Debug"
-# Name "minigzip - Win32 DLL ASM Release"
-# Name "minigzip - Win32 DLL ASM Debug"
-# Name "minigzip - Win32 LIB Release"
-# Name "minigzip - Win32 LIB Debug"
-# Name "minigzip - Win32 LIB ASM Release"
-# Name "minigzip - Win32 LIB ASM Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\..\minigzip.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=..\..\zconf.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\zlib.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/third_party/zlib/projects/visualc6/zlib.dsp b/third_party/zlib/projects/visualc6/zlib.dsp
deleted file mode 100644
index 0fe0604..0000000
--- a/third_party/zlib/projects/visualc6/zlib.dsp
+++ /dev/null
@@ -1,609 +0,0 @@
-# Microsoft Developer Studio Project File - Name="zlib" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=zlib - Win32 LIB Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "zlib.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "zlib.mak" CFG="zlib - Win32 LIB Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "zlib - Win32 DLL Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "zlib - Win32 DLL Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "zlib - Win32 DLL ASM Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "zlib - Win32 DLL ASM Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "zlib - Win32 LIB Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "zlib - Win32 LIB Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE "zlib - Win32 LIB ASM Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "zlib - Win32 LIB ASM Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-
-!IF  "$(CFG)" == "zlib - Win32 DLL Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "zlib___Win32_DLL_Release"
-# PROP BASE Intermediate_Dir "zlib___Win32_DLL_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Win32_DLL_Release"
-# PROP Intermediate_Dir "Win32_DLL_Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-CPP=cl.exe
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT BASE CPP /YX /Yc /Yu
-# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-MTL=midl.exe
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 /nologo /dll /machine:I386 /out:"Win32_DLL_Release\zlib1.dll"
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "zlib___Win32_DLL_Debug"
-# PROP BASE Intermediate_Dir "zlib___Win32_DLL_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Win32_DLL_Debug"
-# PROP Intermediate_Dir "Win32_DLL_Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-CPP=cl.exe
-# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT BASE CPP /YX /Yc /Yu
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT CPP /YX /Yc /Yu
-MTL=midl.exe
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /dll /debug /machine:I386 /out:"Win32_DLL_Debug\zlib1d.dll" /pdbtype:sept
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "zlib___Win32_DLL_ASM_Release"
-# PROP BASE Intermediate_Dir "zlib___Win32_DLL_ASM_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Win32_DLL_ASM_Release"
-# PROP Intermediate_Dir "Win32_DLL_ASM_Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-CPP=cl.exe
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT BASE CPP /YX /Yc /Yu
-# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "ASMV" /D "ASMINF" /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-MTL=midl.exe
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 /nologo /dll /machine:I386 /out:"Win32_DLL_ASM_Release\zlib1.dll"
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "zlib___Win32_DLL_ASM_Debug"
-# PROP BASE Intermediate_Dir "zlib___Win32_DLL_ASM_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Win32_DLL_ASM_Debug"
-# PROP Intermediate_Dir "Win32_DLL_ASM_Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-CPP=cl.exe
-# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT BASE CPP /YX /Yc /Yu
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "ASMV" /D "ASMINF" /FD /GZ /c
-# SUBTRACT CPP /YX /Yc /Yu
-MTL=midl.exe
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /dll /debug /machine:I386 /out:"Win32_DLL_ASM_Debug\zlib1d.dll" /pdbtype:sept
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "zlib___Win32_LIB_Release"
-# PROP BASE Intermediate_Dir "zlib___Win32_LIB_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Win32_LIB_Release"
-# PROP Intermediate_Dir "Win32_LIB_Release"
-# PROP Target_Dir ""
-CPP=cl.exe
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT BASE CPP /YX /Yc /Yu
-# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-RSC=rc.exe
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "zlib___Win32_LIB_Debug"
-# PROP BASE Intermediate_Dir "zlib___Win32_LIB_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Win32_LIB_Debug"
-# PROP Intermediate_Dir "Win32_LIB_Debug"
-# PROP Target_Dir ""
-CPP=cl.exe
-# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT BASE CPP /YX /Yc /Yu
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT CPP /YX /Yc /Yu
-RSC=rc.exe
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"Win32_LIB_Debug\zlibd.lib"
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "zlib___Win32_LIB_ASM_Release"
-# PROP BASE Intermediate_Dir "zlib___Win32_LIB_ASM_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Win32_LIB_ASM_Release"
-# PROP Intermediate_Dir "Win32_LIB_ASM_Release"
-# PROP Target_Dir ""
-CPP=cl.exe
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /FD /c
-# SUBTRACT BASE CPP /YX /Yc /Yu
-# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "ASMV" /D "ASMINF" /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-RSC=rc.exe
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "zlib___Win32_LIB_ASM_Debug"
-# PROP BASE Intermediate_Dir "zlib___Win32_LIB_ASM_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Win32_LIB_ASM_Debug"
-# PROP Intermediate_Dir "Win32_LIB_ASM_Debug"
-# PROP Target_Dir ""
-CPP=cl.exe
-# ADD BASE CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /FD /GZ /c
-# SUBTRACT BASE CPP /YX /Yc /Yu
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "ASMV" /D "ASMINF" /FD /GZ /c
-# SUBTRACT CPP /YX /Yc /Yu
-RSC=rc.exe
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"Win32_LIB_ASM_Debug\zlibd.lib"
-
-!ENDIF 
-
-# Begin Target
-
-# Name "zlib - Win32 DLL Release"
-# Name "zlib - Win32 DLL Debug"
-# Name "zlib - Win32 DLL ASM Release"
-# Name "zlib - Win32 DLL ASM Debug"
-# Name "zlib - Win32 LIB Release"
-# Name "zlib - Win32 LIB Debug"
-# Name "zlib - Win32 LIB ASM Release"
-# Name "zlib - Win32 LIB ASM Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\..\adler32.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\compress.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\crc32.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\deflate.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\gzio.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\infback.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\inffast.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\inflate.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\inftrees.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\trees.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\uncompr.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\win32\zlib.def
-
-!IF  "$(CFG)" == "zlib - Win32 DLL Release"
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL Debug"
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Release"
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Debug"
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Release"
-
-# PROP Exclude_From_Build 1
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Debug"
-
-# PROP Exclude_From_Build 1
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Release"
-
-# PROP Exclude_From_Build 1
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Debug"
-
-# PROP Exclude_From_Build 1
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\zutil.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=..\..\crc32.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\deflate.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\inffast.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\inffixed.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\inflate.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\inftrees.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\trees.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\zconf.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\zlib.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\zutil.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# Begin Source File
-
-SOURCE=..\..\win32\zlib1.rc
-# End Source File
-# End Group
-# Begin Group "Assembler Files (Unsupported)"
-
-# PROP Default_Filter "asm;obj;c;cpp;cxx;h;hpp;hxx"
-# Begin Source File
-
-SOURCE=..\..\contrib\masmx86\gvmat32.asm
-
-!IF  "$(CFG)" == "zlib - Win32 DLL Release"
-
-# PROP Exclude_From_Build 1
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL Debug"
-
-# PROP Exclude_From_Build 1
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Release"
-
-# Begin Custom Build - Assembling...
-IntDir=.\Win32_DLL_ASM_Release
-InputPath=..\..\contrib\masmx86\gvmat32.asm
-InputName=gvmat32
-
-"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	ml.exe /nologo /c /coff /Cx /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
-
-# End Custom Build
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Debug"
-
-# Begin Custom Build - Assembling...
-IntDir=.\Win32_DLL_ASM_Debug
-InputPath=..\..\contrib\masmx86\gvmat32.asm
-InputName=gvmat32
-
-"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
-
-# End Custom Build
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Release"
-
-# PROP Exclude_From_Build 1
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Debug"
-
-# PROP Exclude_From_Build 1
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Release"
-
-# Begin Custom Build - Assembling...
-IntDir=.\Win32_LIB_ASM_Release
-InputPath=..\..\contrib\masmx86\gvmat32.asm
-InputName=gvmat32
-
-"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	ml.exe /nologo /c /coff /Cx /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
-
-# End Custom Build
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Debug"
-
-# Begin Custom Build - Assembling...
-IntDir=.\Win32_LIB_ASM_Debug
-InputPath=..\..\contrib\masmx86\gvmat32.asm
-InputName=gvmat32
-
-"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
-
-# End Custom Build
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\contrib\masmx86\gvmat32c.c
-
-!IF  "$(CFG)" == "zlib - Win32 DLL Release"
-
-# PROP Exclude_From_Build 1
-# ADD CPP /I "..\.."
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL Debug"
-
-# PROP Exclude_From_Build 1
-# ADD CPP /I "..\.."
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Release"
-
-# ADD CPP /I "..\.."
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Debug"
-
-# ADD CPP /I "..\.."
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Release"
-
-# PROP Exclude_From_Build 1
-# ADD CPP /I "..\.."
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Debug"
-
-# PROP Exclude_From_Build 1
-# ADD CPP /I "..\.."
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Release"
-
-# ADD CPP /I "..\.."
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Debug"
-
-# ADD CPP /I "..\.."
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\contrib\masmx86\inffas32.asm
-
-!IF  "$(CFG)" == "zlib - Win32 DLL Release"
-
-# PROP Exclude_From_Build 1
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL Debug"
-
-# PROP Exclude_From_Build 1
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Release"
-
-# Begin Custom Build - Assembling...
-IntDir=.\Win32_DLL_ASM_Release
-InputPath=..\..\contrib\masmx86\inffas32.asm
-InputName=inffas32
-
-"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	ml.exe /nologo /c /coff /Cx /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
-
-# End Custom Build
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 DLL ASM Debug"
-
-# Begin Custom Build - Assembling...
-IntDir=.\Win32_DLL_ASM_Debug
-InputPath=..\..\contrib\masmx86\inffas32.asm
-InputName=inffas32
-
-"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
-
-# End Custom Build
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Release"
-
-# PROP Exclude_From_Build 1
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB Debug"
-
-# PROP Exclude_From_Build 1
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Release"
-
-# Begin Custom Build - Assembling...
-IntDir=.\Win32_LIB_ASM_Release
-InputPath=..\..\contrib\masmx86\inffas32.asm
-InputName=inffas32
-
-"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	ml.exe /nologo /c /coff /Cx /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
-
-# End Custom Build
-
-!ELSEIF  "$(CFG)" == "zlib - Win32 LIB ASM Debug"
-
-# Begin Custom Build - Assembling...
-IntDir=.\Win32_LIB_ASM_Debug
-InputPath=..\..\contrib\masmx86\inffas32.asm
-InputName=inffas32
-
-"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
-	ml.exe /nologo /c /coff /Cx /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
-
-# End Custom Build
-
-!ENDIF 
-
-# End Source File
-# End Group
-# Begin Source File
-
-SOURCE=.\README.txt
-# End Source File
-# End Target
-# End Project
diff --git a/third_party/zlib/projects/visualc6/zlib.dsw b/third_party/zlib/projects/visualc6/zlib.dsw
deleted file mode 100644
index 3a771fc..0000000
--- a/third_party/zlib/projects/visualc6/zlib.dsw
+++ /dev/null
@@ -1,59 +0,0 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "example"=.\example.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-    Begin Project Dependency
-    Project_Dep_Name zlib
-    End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "minigzip"=.\minigzip.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-    Begin Project Dependency
-    Project_Dep_Name zlib
-    End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "zlib"=.\zlib.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
diff --git a/third_party/zlib/qnx/package.qpg b/third_party/zlib/qnx/package.qpg
index 8a4a47c..aebf6e3 100644
--- a/third_party/zlib/qnx/package.qpg
+++ b/third_party/zlib/qnx/package.qpg
@@ -25,10 +25,10 @@
       <QPG:Files>
          <QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/>
          <QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/>
-         <QPG:Add file="../libz.so.1.2.3" install="/opt/lib/" user="root:bin" permission="644"/>
-         <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.3"/>
-         <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.3"/>
-         <QPG:Add file="../libz.so.1.2.3" install="/opt/lib/" component="slib"/>
+         <QPG:Add file="../libz.so.1.2.8" install="/opt/lib/" user="root:bin" permission="644"/>
+         <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.8"/>
+         <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.8"/>
+         <QPG:Add file="../libz.so.1.2.8" install="/opt/lib/" component="slib"/>
       </QPG:Files>
 
       <QPG:PackageFilter>
@@ -63,7 +63,7 @@
             </QPM:ProductDescription>
 
             <QPM:ReleaseDescription>
-               <QPM:ReleaseVersion>1.2.3</QPM:ReleaseVersion>
+               <QPM:ReleaseVersion>1.2.8</QPM:ReleaseVersion>
                <QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
                <QPM:ReleaseStability>Stable</QPM:ReleaseStability>
                <QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor>
diff --git a/third_party/zlib/trees.c b/third_party/zlib/trees.c
index eb55679..1fd7759 100644
--- a/third_party/zlib/trees.c
+++ b/third_party/zlib/trees.c
@@ -1,5 +1,6 @@
 /* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-2005 Jean-loup Gailly
+ * Copyright (C) 1995-2012 Jean-loup Gailly
+ * detect_data_type() function provided freely by Cosmin Truta, 2006
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -73,11 +74,6 @@ local const uch bl_order[BL_CODES]
  * probability, to avoid transmitting the lengths for unused bit length codes.
  */
 
-#define Buf_size (8 * 2*sizeof(char))
-/* Number of bits used within bi_buf. (bi_buf might be implemented on
- * more than 16 bits on some systems.)
- */
-
 /* ===========================================================================
  * Local data. These are initialized only once.
  */
@@ -152,7 +148,7 @@ local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
                               int blcodes));
 local void compress_block OF((deflate_state *s, const ct_data *ltree,
                               const ct_data *dtree));
-local void set_data_type  OF((deflate_state *s));
+local int  detect_data_type OF((deflate_state *s));
 local unsigned bi_reverse OF((unsigned value, int length));
 local void bi_windup      OF((deflate_state *s));
 local void bi_flush       OF((deflate_state *s));
@@ -203,12 +199,12 @@ local void send_bits(s, value, length)
      * unused bits in value.
      */
     if (s->bi_valid > (int)Buf_size - length) {
-        s->bi_buf |= (value << s->bi_valid);
+        s->bi_buf |= (ush)value << s->bi_valid;
         put_short(s, s->bi_buf);
         s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
         s->bi_valid += length - Buf_size;
     } else {
-        s->bi_buf |= value << s->bi_valid;
+        s->bi_buf |= (ush)value << s->bi_valid;
         s->bi_valid += length;
     }
 }
@@ -218,12 +214,12 @@ local void send_bits(s, value, length)
 { int len = length;\
   if (s->bi_valid > (int)Buf_size - len) {\
     int val = value;\
-    s->bi_buf |= (val << s->bi_valid);\
+    s->bi_buf |= (ush)val << s->bi_valid;\
     put_short(s, s->bi_buf);\
     s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
     s->bi_valid += len - Buf_size;\
   } else {\
-    s->bi_buf |= (value) << s->bi_valid;\
+    s->bi_buf |= (ush)(value) << s->bi_valid;\
     s->bi_valid += len;\
   }\
 }
@@ -250,11 +246,13 @@ local void tr_static_init()
     if (static_init_done) return;
 
     /* For some embedded targets, global variables are not initialized: */
+#ifdef NO_INIT_GLOBAL_POINTERS
     static_l_desc.static_tree = static_ltree;
     static_l_desc.extra_bits = extra_lbits;
     static_d_desc.static_tree = static_dtree;
     static_d_desc.extra_bits = extra_dbits;
     static_bl_desc.extra_bits = extra_blbits;
+#endif
 
     /* Initialize the mapping length (0..255) -> length code (0..28) */
     length = 0;
@@ -348,13 +346,14 @@ void gen_trees_header()
                 static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
     }
 
-    fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n");
+    fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
     for (i = 0; i < DIST_CODE_LEN; i++) {
         fprintf(header, "%2u%s", _dist_code[i],
                 SEPARATOR(i, DIST_CODE_LEN-1, 20));
     }
 
-    fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+    fprintf(header,
+        "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
     for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
         fprintf(header, "%2u%s", _length_code[i],
                 SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
@@ -379,7 +378,7 @@ void gen_trees_header()
 /* ===========================================================================
  * Initialize the tree data structures for a new zlib stream.
  */
-void _tr_init(s)
+void ZLIB_INTERNAL _tr_init(s)
     deflate_state *s;
 {
     tr_static_init();
@@ -395,7 +394,6 @@ void _tr_init(s)
 
     s->bi_buf = 0;
     s->bi_valid = 0;
-    s->last_eob_len = 8; /* enough lookahead for inflate */
 #ifdef DEBUG
     s->compressed_len = 0L;
     s->bits_sent = 0L;
@@ -864,13 +862,13 @@ local void send_all_trees(s, lcodes, dcodes, blcodes)
 /* ===========================================================================
  * Send a stored block
  */
-void _tr_stored_block(s, buf, stored_len, eof)
+void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
     deflate_state *s;
     charf *buf;       /* input block */
     ulg stored_len;   /* length of input block */
-    int eof;          /* true if this is the last block for a file */
+    int last;         /* one if this is the last block for a file */
 {
-    send_bits(s, (STORED_BLOCK<<1)+eof, 3);  /* send block type */
+    send_bits(s, (STORED_BLOCK<<1)+last, 3);    /* send block type */
 #ifdef DEBUG
     s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
     s->compressed_len += (stored_len + 4) << 3;
@@ -879,17 +877,19 @@ void _tr_stored_block(s, buf, stored_len, eof)
 }
 
 /* ===========================================================================
+ * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
+ */
+void ZLIB_INTERNAL _tr_flush_bits(s)
+    deflate_state *s;
+{
+    bi_flush(s);
+}
+
+/* ===========================================================================
  * Send one empty static block to give enough lookahead for inflate.
  * This takes 10 bits, of which 7 may remain in the bit buffer.
- * The current inflate code requires 9 bits of lookahead. If the
- * last two codes for the previous block (real code plus EOB) were coded
- * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
- * the last real code. In this case we send two empty static blocks instead
- * of one. (There are no problems if the previous block is stored or fixed.)
- * To simplify the code, we assume the worst case of last real code encoded
- * on one bit only.
  */
-void _tr_align(s)
+void ZLIB_INTERNAL _tr_align(s)
     deflate_state *s;
 {
     send_bits(s, STATIC_TREES<<1, 3);
@@ -898,31 +898,17 @@ void _tr_align(s)
     s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
 #endif
     bi_flush(s);
-    /* Of the 10 bits for the empty block, we have already sent
-     * (10 - bi_valid) bits. The lookahead for the last real code (before
-     * the EOB of the previous block) was thus at least one plus the length
-     * of the EOB plus what we have just sent of the empty static block.
-     */
-    if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
-        send_bits(s, STATIC_TREES<<1, 3);
-        send_code(s, END_BLOCK, static_ltree);
-#ifdef DEBUG
-        s->compressed_len += 10L;
-#endif
-        bi_flush(s);
-    }
-    s->last_eob_len = 7;
 }
 
 /* ===========================================================================
  * Determine the best encoding for the current block: dynamic trees, static
  * trees or store, and output the encoded block to the zip file.
  */
-void _tr_flush_block(s, buf, stored_len, eof)
+void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
     deflate_state *s;
     charf *buf;       /* input block, or NULL if too old */
     ulg stored_len;   /* length of input block */
-    int eof;          /* true if this is the last block for a file */
+    int last;         /* one if this is the last block for a file */
 {
     ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
     int max_blindex = 0;  /* index of last bit length code of non zero freq */
@@ -931,8 +917,8 @@ void _tr_flush_block(s, buf, stored_len, eof)
     if (s->level > 0) {
 
         /* Check if the file is binary or text */
-        if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN)
-            set_data_type(s);
+        if (s->strm->data_type == Z_UNKNOWN)
+            s->strm->data_type = detect_data_type(s);
 
         /* Construct the literal and distance trees */
         build_tree(s, (tree_desc *)(&(s->l_desc)));
@@ -978,23 +964,25 @@ void _tr_flush_block(s, buf, stored_len, eof)
          * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
          * transform a block into a stored block.
          */
-        _tr_stored_block(s, buf, stored_len, eof);
+        _tr_stored_block(s, buf, stored_len, last);
 
 #ifdef FORCE_STATIC
     } else if (static_lenb >= 0) { /* force static trees */
 #else
     } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
 #endif
-        send_bits(s, (STATIC_TREES<<1)+eof, 3);
-        compress_block(s, static_ltree, static_dtree);
+        send_bits(s, (STATIC_TREES<<1)+last, 3);
+        compress_block(s, (const ct_data *)static_ltree,
+                       (const ct_data *)static_dtree);
 #ifdef DEBUG
         s->compressed_len += 3 + s->static_len;
 #endif
     } else {
-        send_bits(s, (DYN_TREES<<1)+eof, 3);
+        send_bits(s, (DYN_TREES<<1)+last, 3);
         send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
                        max_blindex+1);
-        compress_block(s, s->dyn_ltree, s->dyn_dtree);
+        compress_block(s, (const ct_data *)s->dyn_ltree,
+                       (const ct_data *)s->dyn_dtree);
 #ifdef DEBUG
         s->compressed_len += 3 + s->opt_len;
 #endif
@@ -1005,21 +993,21 @@ void _tr_flush_block(s, buf, stored_len, eof)
      */
     init_block(s);
 
-    if (eof) {
+    if (last) {
         bi_windup(s);
 #ifdef DEBUG
         s->compressed_len += 7;  /* align on byte boundary */
 #endif
     }
     Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
-           s->compressed_len-7*eof));
+           s->compressed_len-7*last));
 }
 
 /* ===========================================================================
  * Save the match info and tally the frequency counts. Return true if
  * the current block must be flushed.
  */
-int _tr_tally (s, dist, lc)
+int ZLIB_INTERNAL _tr_tally (s, dist, lc)
     deflate_state *s;
     unsigned dist;  /* distance of matched string */
     unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
@@ -1114,28 +1102,48 @@ local void compress_block(s, ltree, dtree)
     } while (lx < s->last_lit);
 
     send_code(s, END_BLOCK, ltree);
-    s->last_eob_len = ltree[END_BLOCK].Len;
 }
 
 /* ===========================================================================
- * Set the data type to BINARY or TEXT, using a crude approximation:
- * set it to Z_TEXT if all symbols are either printable characters (33 to 255)
- * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise.
+ * Check if the data type is TEXT or BINARY, using the following algorithm:
+ * - TEXT if the two conditions below are satisfied:
+ *    a) There are no non-portable control characters belonging to the
+ *       "black list" (0..6, 14..25, 28..31).
+ *    b) There is at least one printable character belonging to the
+ *       "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * - BINARY otherwise.
+ * - The following partially-portable control characters form a
+ *   "gray list" that is ignored in this detection algorithm:
+ *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
  * IN assertion: the fields Freq of dyn_ltree are set.
  */
-local void set_data_type(s)
+local int detect_data_type(s)
     deflate_state *s;
 {
+    /* black_mask is the bit mask of black-listed bytes
+     * set bits 0..6, 14..25, and 28..31
+     * 0xf3ffc07f = binary 11110011111111111100000001111111
+     */
+    unsigned long black_mask = 0xf3ffc07fUL;
     int n;
 
-    for (n = 0; n < 9; n++)
+    /* Check for non-textual ("black-listed") bytes. */
+    for (n = 0; n <= 31; n++, black_mask >>= 1)
+        if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
+            return Z_BINARY;
+
+    /* Check for textual ("white-listed") bytes. */
+    if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
+            || s->dyn_ltree[13].Freq != 0)
+        return Z_TEXT;
+    for (n = 32; n < LITERALS; n++)
         if (s->dyn_ltree[n].Freq != 0)
-            break;
-    if (n == 9)
-        for (n = 14; n < 32; n++)
-            if (s->dyn_ltree[n].Freq != 0)
-                break;
-    s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY;
+            return Z_TEXT;
+
+    /* There are no "black-listed" or "white-listed" bytes:
+     * this stream either is empty or has tolerated ("gray-listed") bytes only.
+     */
+    return Z_BINARY;
 }
 
 /* ===========================================================================
@@ -1201,7 +1209,6 @@ local void copy_block(s, buf, len, header)
     int      header;  /* true if block header must be written */
 {
     bi_windup(s);        /* align on byte boundary */
-    s->last_eob_len = 8; /* enough lookahead for inflate */
 
     if (header) {
         put_short(s, (ush)len);
diff --git a/third_party/zlib/trees.h b/third_party/zlib/trees.h
index 72facf9..d35639d 100644
--- a/third_party/zlib/trees.h
+++ b/third_party/zlib/trees.h
@@ -70,7 +70,7 @@ local const ct_data static_dtree[D_CODES] = {
 {{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
 };
 
-const uch _dist_code[DIST_CODE_LEN] = {
+const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
  0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
@@ -99,7 +99,7 @@ const uch _dist_code[DIST_CODE_LEN] = {
 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
 };
 
-const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
+const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
  0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
diff --git a/third_party/zlib/uncompr.c b/third_party/zlib/uncompr.c
index a052f22..242e949 100644
--- a/third_party/zlib/uncompr.c
+++ b/third_party/zlib/uncompr.c
@@ -1,11 +1,12 @@
 /* uncompr.c -- decompress a memory buffer
- * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * Copyright (C) 1995-2003, 2010 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 /* @(#) $Id$ */
 
-#include "zutil.h"
+#define ZLIB_INTERNAL
+#include "zlib.h"
 
 /* ===========================================================================
      Decompresses the source buffer into the destination buffer.  sourceLen is
@@ -15,8 +16,6 @@
    been saved previously by the compressor and transmitted to the decompressor
    by some mechanism outside the scope of this compression library.)
    Upon exit, destLen is the actual size of the compressed buffer.
-     This function can be used to decompress a whole file at once if the
-   input file is mmap'ed.
 
      uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
    enough memory, Z_BUF_ERROR if there was not enough room in the output
@@ -31,7 +30,7 @@ int ZEXPORT uncompress (dest, destLen, source, sourceLen)
     z_stream stream;
     int err;
 
-    stream.next_in = source;
+    stream.next_in = (z_const Bytef *)source;
     stream.avail_in = (uInt)sourceLen;
     /* Check for source > 64K on 16-bit machine: */
     if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
diff --git a/third_party/zlib/win32/DLL_FAQ.txt b/third_party/zlib/win32/DLL_FAQ.txt
index fb18e07..12c0090 100644
--- a/third_party/zlib/win32/DLL_FAQ.txt
+++ b/third_party/zlib/win32/DLL_FAQ.txt
@@ -16,7 +16,7 @@ in the zlib distribution, or at the following location:
 
     Pointers to a precompiled ZLIB1.DLL can be found in the zlib
     web site at:
-      http://www.zlib.org/
+      http://www.zlib.net/
 
     Applications that link to ZLIB1.DLL can rely on the following
     specification:
@@ -350,9 +350,9 @@ in the zlib distribution, or at the following location:
     your build is unofficial.  You should give it a different file
     name, and/or install it in a private directory that can be
     accessed by your application only, and is not visible to the
-    others (e.g. it's not in the SYSTEM or the SYSTEM32 directory,
-    and it's not in the PATH).  Otherwise, your build may clash
-    with applications that link to the official build.
+    others (i.e. it's neither in the PATH, nor in the SYSTEM or
+    SYSTEM32 directories).  Otherwise, your build may clash with
+    applications that link to the official build.
 
     For example, in Cygwin, zlib is linked to the Cygwin runtime
     CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL.
diff --git a/third_party/zlib/win32/Makefile.bor b/third_party/zlib/win32/Makefile.bor
index b802519..d152bbb 100644
--- a/third_party/zlib/win32/Makefile.bor
+++ b/third_party/zlib/win32/Makefile.bor
@@ -1,9 +1,6 @@
 # Makefile for zlib
 # Borland C++ for Win32
 #
-# Updated for zlib 1.2.x by Cosmin Truta, 11-Mar-2003
-# Last updated: 28-Aug-2003
-#
 # Usage:
 #  make -f win32/Makefile.bor
 #  make -f win32/Makefile.bor LOCAL_ZLIB=-DASMV OBJA=match.obj OBJPA=+match.obj
@@ -27,11 +24,11 @@ LDFLAGS = $(LOC)
 # variables
 ZLIB_LIB = zlib.lib
 
-OBJ1  = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
-OBJ2  = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj
+OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
 #OBJA =
-OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
-OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj
+OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
 #OBJPA=
 
 
@@ -52,7 +49,13 @@ crc32.obj: crc32.c zlib.h zconf.h crc32.h
 
 deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
 
-gzio.obj: gzio.c zutil.h zlib.h zconf.h
+gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h
+
+gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h
+
+gzread.obj: gzread.c zlib.h zconf.h gzguts.h
+
+gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h
 
 infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
  inffast.h inffixed.h
@@ -71,9 +74,9 @@ uncompr.obj: uncompr.c zlib.h zconf.h
 
 zutil.obj: zutil.c zutil.h zlib.h zconf.h
 
-example.obj: example.c zlib.h zconf.h
+example.obj: test/example.c zlib.h zconf.h
 
-minigzip.obj: minigzip.c zlib.h zconf.h
+minigzip.obj: test/minigzip.c zlib.h zconf.h
 
 
 # For the sake of the old Borland make,
@@ -99,8 +102,8 @@ minigzip.exe: minigzip.obj $(ZLIB_LIB)
 
 # cleanup
 clean:
+	-del $(ZLIB_LIB)
 	-del *.obj
-	-del *.lib
 	-del *.exe
 	-del *.tds
 	-del zlib.bak
diff --git a/third_party/zlib/win32/Makefile.emx b/third_party/zlib/win32/Makefile.emx
deleted file mode 100644
index 7b08424c..0000000
--- a/third_party/zlib/win32/Makefile.emx
+++ /dev/null
@@ -1,69 +0,0 @@
-# Makefile for zlib.  Modified for emx/rsxnt by Chr. Spieler, 6/16/98.
-# Copyright (C) 1995-1998 Jean-loup Gailly.
-# For conditions of distribution and use, see copyright notice in zlib.h
-
-# To compile, or to compile and test, type:
-#
-#   make -fmakefile.emx;  make test -fmakefile.emx
-#
-
-CC=gcc -Zwin32
-
-#CFLAGS=-MMD -O
-#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
-#CFLAGS=-MMD -g -DDEBUG
-CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
-             -Wstrict-prototypes -Wmissing-prototypes
-
-# If cp.exe is available, replace "copy /Y" with "cp -fp" .
-CP=copy /Y
-# If gnu install.exe is available, replace $(CP) with ginstall.
-INSTALL=$(CP)
-# The default value of RM is "rm -f."  If "rm.exe" is found, comment out:
-RM=del
-LDLIBS=-L. -lzlib
-LD=$(CC) -s -o
-LDSHARED=$(CC)
-
-INCL=zlib.h zconf.h
-LIBS=zlib.a
-
-AR=ar rcs
-
-prefix=/usr/local
-exec_prefix = $(prefix)
-
-OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
-       zutil.o inflate.o infback.o inftrees.o inffast.o
-
-TEST_OBJS = example.o minigzip.o
-
-all: example.exe minigzip.exe
-
-test: all
-	./example
-	echo hello world | .\minigzip | .\minigzip -d
-
-%.o : %.c
-	$(CC) $(CFLAGS) -c $< -o $@
-
-zlib.a: $(OBJS)
-	$(AR) $@ $(OBJS)
-
-%.exe : %.o $(LIBS)
-	$(LD) $@ $< $(LDLIBS)
-
-
-.PHONY : clean
-
-clean:
-	$(RM) *.d
-	$(RM) *.o
-	$(RM) *.exe
-	$(RM) zlib.a
-	$(RM) foo.gz
-
-DEPS := $(wildcard *.d)
-ifneq ($(DEPS),)
-include $(DEPS)
-endif
diff --git a/third_party/zlib/win32/Makefile.gcc b/third_party/zlib/win32/Makefile.gcc
index 62a8430..6d1ded6 100644
--- a/third_party/zlib/win32/Makefile.gcc
+++ b/third_party/zlib/win32/Makefile.gcc
@@ -1,23 +1,29 @@
 # Makefile for zlib, derived from Makefile.dj2.
 # Modified for mingw32 by C. Spieler, 6/16/98.
 # Updated for zlib 1.2.x by Christian Spieler and Cosmin Truta, Mar-2003.
-# Last updated: 1-Aug-2003.
+# Last updated: Mar 2012.
 # Tested under Cygwin and MinGW.
 
 # Copyright (C) 1995-2003 Jean-loup Gailly.
 # For conditions of distribution and use, see copyright notice in zlib.h
 
-# To compile, or to compile and test, type:
+# To compile, or to compile and test, type from the top level zlib directory:
 #
-#   make -fmakefile.gcc;  make test testdll -fmakefile.gcc
+#   make -fwin32/Makefile.gcc;  make test testdll -fwin32/Makefile.gcc
 #
 # To use the asm code, type:
 #   cp contrib/asm?86/match.S ./match.S
-#   make LOC=-DASMV OBJA=match.o -fmakefile.gcc
+#   make LOC=-DASMV OBJA=match.o -fwin32/Makefile.gcc
 #
 # To install libz.a, zconf.h and zlib.h in the system directories, type:
 #
-#   make install -fmakefile.gcc
+#   make install -fwin32/Makefile.gcc
+#
+# BINARY_PATH, INCLUDE_PATH and LIBRARY_PATH must be set.
+#
+# To install the shared lib, append SHARED_MODE=1 to the make command :
+#
+#   make install -fwin32/Makefile.gcc SHARED_MODE=1
 
 # Note:
 # If the platform is *not* MinGW (e.g. it is Cygwin or UWIN),
@@ -25,45 +31,53 @@
 
 STATICLIB = libz.a
 SHAREDLIB = zlib1.dll
-IMPLIB    = libzdll.a
+IMPLIB    = libz.dll.a
+
+#
+# Set to 1 if shared object needs to be installed
+#
+SHARED_MODE=0
 
 #LOC = -DASMV
 #LOC = -DDEBUG -g
 
-CC = gcc
+PREFIX =
+CC = $(PREFIX)gcc
 CFLAGS = $(LOC) -O3 -Wall
 
 AS = $(CC)
 ASFLAGS = $(LOC) -Wall
 
 LD = $(CC)
-LDFLAGS = $(LOC) -s
+LDFLAGS = $(LOC)
 
-AR = ar
+AR = $(PREFIX)ar
 ARFLAGS = rcs
 
-RC = windres
+RC = $(PREFIX)windres
 RCFLAGS = --define GCC_WINDRES
 
+STRIP = $(PREFIX)strip
+
 CP = cp -fp
 # If GNU install is available, replace $(CP) with install.
 INSTALL = $(CP)
 RM = rm -f
 
-prefix = /usr/local
+prefix ?= /usr/local
 exec_prefix = $(prefix)
 
-OBJS = adler32.o compress.o crc32.o deflate.o gzio.o infback.o \
-       inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o
+OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \
+       gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o
 OBJA =
 
-all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) example minigzip example_d minigzip_d
+all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) example.exe minigzip.exe example_d.exe minigzip_d.exe
 
-test: example minigzip
+test: example.exe minigzip.exe
 	./example
 	echo hello world | ./minigzip | ./minigzip -d
 
-testdll: example_d minigzip_d
+testdll: example_d.exe minigzip_d.exe
 	./example_d
 	echo hello world | ./minigzip_d | ./minigzip_d -d
 
@@ -79,43 +93,69 @@ $(STATICLIB): $(OBJS) $(OBJA)
 $(IMPLIB): $(SHAREDLIB)
 
 $(SHAREDLIB): win32/zlib.def $(OBJS) $(OBJA) zlibrc.o
-	dllwrap --driver-name $(CC) --def win32/zlib.def \
-	  --implib $(IMPLIB) -o $@ $(OBJS) $(OBJA) zlibrc.o
-	strip $@
+	$(CC) -shared -Wl,--out-implib,$(IMPLIB) $(LDFLAGS) \
+	-o $@ win32/zlib.def $(OBJS) $(OBJA) zlibrc.o
+	$(STRIP) $@
 
-example: example.o $(STATICLIB)
+example.exe: example.o $(STATICLIB)
 	$(LD) $(LDFLAGS) -o $@ example.o $(STATICLIB)
+	$(STRIP) $@
 
-minigzip: minigzip.o $(STATICLIB)
+minigzip.exe: minigzip.o $(STATICLIB)
 	$(LD) $(LDFLAGS) -o $@ minigzip.o $(STATICLIB)
+	$(STRIP) $@
 
-example_d: example.o $(IMPLIB)
+example_d.exe: example.o $(IMPLIB)
 	$(LD) $(LDFLAGS) -o $@ example.o $(IMPLIB)
+	$(STRIP) $@
 
-minigzip_d: minigzip.o $(IMPLIB)
+minigzip_d.exe: minigzip.o $(IMPLIB)
 	$(LD) $(LDFLAGS) -o $@ minigzip.o $(IMPLIB)
+	$(STRIP) $@
 
-zlibrc.o: win32/zlib1.rc
-	$(RC) $(RCFLAGS) -o $@ win32/zlib1.rc
+example.o: test/example.c zlib.h zconf.h
+	$(CC) $(CFLAGS) -I. -c -o $@ test/example.c
 
+minigzip.o: test/minigzip.c zlib.h zconf.h
+	$(CC) $(CFLAGS) -I. -c -o $@ test/minigzip.c
 
-# INCLUDE_PATH and LIBRARY_PATH must be set.
+zlibrc.o: win32/zlib1.rc
+	$(RC) $(RCFLAGS) -o $@ win32/zlib1.rc
 
 .PHONY: install uninstall clean
 
-install: zlib.h zconf.h $(LIB)
-	- at if not exist $(INCLUDE_PATH)/nul mkdir $(INCLUDE_PATH)
-	- at if not exist $(LIBRARY_PATH)/nul mkdir $(LIBRARY_PATH)
-	-$(INSTALL) zlib.h $(INCLUDE_PATH)
-	-$(INSTALL) zconf.h $(INCLUDE_PATH)
-	-$(INSTALL) $(STATICLIB) $(LIBRARY_PATH)
-	-$(INSTALL) $(IMPLIB) $(LIBRARY_PATH)
+install: zlib.h zconf.h $(STATICLIB) $(IMPLIB)
+	@if test -z "$(DESTDIR)$(INCLUDE_PATH)" -o -z "$(DESTDIR)$(LIBRARY_PATH)" -o -z "$(DESTDIR)$(BINARY_PATH)"; then \
+		echo INCLUDE_PATH, LIBRARY_PATH, and BINARY_PATH must be specified; \
+		exit 1; \
+	fi
+	- at mkdir -p '$(DESTDIR)$(INCLUDE_PATH)'
+	- at mkdir -p '$(DESTDIR)$(LIBRARY_PATH)' '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig
+	-if [ "$(SHARED_MODE)" = "1" ]; then \
+		mkdir -p '$(DESTDIR)$(BINARY_PATH)'; \
+		$(INSTALL) $(SHAREDLIB) '$(DESTDIR)$(BINARY_PATH)'; \
+		$(INSTALL) $(IMPLIB) '$(DESTDIR)$(LIBRARY_PATH)'; \
+	fi
+	-$(INSTALL) zlib.h '$(DESTDIR)$(INCLUDE_PATH)'
+	-$(INSTALL) zconf.h '$(DESTDIR)$(INCLUDE_PATH)'
+	-$(INSTALL) $(STATICLIB) '$(DESTDIR)$(LIBRARY_PATH)'
+	sed \
+		-e 's|@prefix@|${prefix}|g' \
+		-e 's|@exec_prefix@|${exec_prefix}|g' \
+		-e 's|@libdir@|$(LIBRARY_PATH)|g' \
+		-e 's|@sharedlibdir@|$(LIBRARY_PATH)|g' \
+		-e 's|@includedir@|$(INCLUDE_PATH)|g' \
+		-e 's|@VERSION@|'`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' zlib.h`'|g' \
+		zlib.pc.in > '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig/zlib.pc
 
 uninstall:
-	-$(RM) $(INCLUDE_PATH)/zlib.h
-	-$(RM) $(INCLUDE_PATH)/zconf.h
-	-$(RM) $(LIBRARY_PATH)/$(STATICLIB)
-	-$(RM) $(LIBRARY_PATH)/$(IMPLIB)
+	-if [ "$(SHARED_MODE)" = "1" ]; then \
+		$(RM) '$(DESTDIR)$(BINARY_PATH)'/$(SHAREDLIB); \
+		$(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(IMPLIB); \
+	fi
+	-$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zlib.h
+	-$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zconf.h
+	-$(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(STATICLIB)
 
 clean:
 	-$(RM) $(STATICLIB)
@@ -129,13 +169,14 @@ adler32.o: zlib.h zconf.h
 compress.o: zlib.h zconf.h
 crc32.o: crc32.h zlib.h zconf.h
 deflate.o: deflate.h zutil.h zlib.h zconf.h
-example.o: zlib.h zconf.h
-gzio.o: zutil.h zlib.h zconf.h
+gzclose.o: zlib.h zconf.h gzguts.h
+gzlib.o: zlib.h zconf.h gzguts.h
+gzread.o: zlib.h zconf.h gzguts.h
+gzwrite.o: zlib.h zconf.h gzguts.h
 inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
 inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
 infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
 inftrees.o: zutil.h zlib.h zconf.h inftrees.h
-minigzip.o: zlib.h zconf.h
 trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
 uncompr.o: zlib.h zconf.h
 zutil.o: zutil.h zlib.h zconf.h
diff --git a/third_party/zlib/win32/Makefile.msc b/third_party/zlib/win32/Makefile.msc
index 528ecaa..67b77317 100644
--- a/third_party/zlib/win32/Makefile.msc
+++ b/third_party/zlib/win32/Makefile.msc
@@ -1,22 +1,21 @@
-# Makefile for zlib -- Microsoft (Visual) C
-#
-# Authors:
-#   Cosmin Truta, 11-Mar-2003
-#   Christian Spieler, 19-Mar-2003
-#
-# Last updated:
-#   Cosmin Truta, 27-Aug-2003
+# Makefile for zlib using Microsoft (Visual) C
+# zlib is copyright (C) 1995-2006 Jean-loup Gailly and Mark Adler
 #
 # Usage:
-#   nmake -f win32/Makefile.msc            (standard build)
-#   nmake -f win32/Makefile.msc LOC=-DFOO  (nonstandard build)
-#   nmake -f win32/Makefile.msc LOC=-DASMV OBJA=match.obj  (use ASM code)
-
+#   nmake -f win32/Makefile.msc                          (standard build)
+#   nmake -f win32/Makefile.msc LOC=-DFOO                (nonstandard build)
+#   nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" \
+#         OBJA="inffas32.obj match686.obj"               (use ASM code, x86)
+#   nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -I." \
+#         OBJA="inffasx64.obj gvmat64.obj inffas8664.obj"  (use ASM code, x64)
+
+# The toplevel directory of the source tree.
+#
+TOP = .
 
 # optional build flags
 LOC =
 
-
 # variables
 STATICLIB = zlib.lib
 SHAREDLIB = zlib1.dll
@@ -27,14 +26,15 @@ AS = ml
 LD = link
 AR = lib
 RC = rc
-CFLAGS  = -nologo -MD -O2 $(LOC)
-ASFLAGS = -coff
-LDFLAGS = -nologo -release
+CFLAGS  = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC)
+WFLAGS  = -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
+ASFLAGS = -coff -Zi $(LOC)
+LDFLAGS = -nologo -debug -incremental:no -opt:ref
 ARFLAGS = -nologo
 RCFLAGS = /dWIN32 /r
 
-OBJS = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj \
-       inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJS = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj \
+       gzwrite.obj infback.obj inflate.obj inftrees.obj inffast.obj trees.obj uncompr.obj zutil.obj
 OBJA =
 
 
@@ -47,62 +47,97 @@ $(STATICLIB): $(OBJS) $(OBJA)
 
 $(IMPLIB): $(SHAREDLIB)
 
-$(SHAREDLIB): win32/zlib.def $(OBJS) $(OBJA) zlib1.res
-	$(LD) $(LDFLAGS) -def:win32/zlib.def -dll -implib:$(IMPLIB) \
-	  -out:$@ $(OBJS) $(OBJA) zlib1.res
+$(SHAREDLIB): $(TOP)/win32/zlib.def $(OBJS) $(OBJA) zlib1.res
+	$(LD) $(LDFLAGS) -def:$(TOP)/win32/zlib.def -dll -implib:$(IMPLIB) \
+	  -out:$@ -base:0x5A4C0000 $(OBJS) $(OBJA) zlib1.res
+	if exist $@.manifest \
+	  mt -nologo -manifest $@.manifest -outputresource:$@;2
 
 example.exe: example.obj $(STATICLIB)
 	$(LD) $(LDFLAGS) example.obj $(STATICLIB)
+	if exist $@.manifest \
+	  mt -nologo -manifest $@.manifest -outputresource:$@;1
 
 minigzip.exe: minigzip.obj $(STATICLIB)
 	$(LD) $(LDFLAGS) minigzip.obj $(STATICLIB)
+	if exist $@.manifest \
+	  mt -nologo -manifest $@.manifest -outputresource:$@;1
 
 example_d.exe: example.obj $(IMPLIB)
 	$(LD) $(LDFLAGS) -out:$@ example.obj $(IMPLIB)
+	if exist $@.manifest \
+	  mt -nologo -manifest $@.manifest -outputresource:$@;1
 
 minigzip_d.exe: minigzip.obj $(IMPLIB)
 	$(LD) $(LDFLAGS) -out:$@ minigzip.obj $(IMPLIB)
+	if exist $@.manifest \
+	  mt -nologo -manifest $@.manifest -outputresource:$@;1
+
+{$(TOP)}.c.obj:
+	$(CC) -c $(WFLAGS) $(CFLAGS) $<
+
+{$(TOP)/test}.c.obj:
+	$(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $<
+
+{$(TOP)/contrib/masmx64}.c.obj:
+	$(CC) -c $(WFLAGS) $(CFLAGS) $<
 
-.c.obj:
-	$(CC) -c $(CFLAGS) $<
+{$(TOP)/contrib/masmx64}.asm.obj:
+	$(AS) -c $(ASFLAGS) $<
 
-.asm.obj:
+{$(TOP)/contrib/masmx86}.asm.obj:
 	$(AS) -c $(ASFLAGS) $<
 
-adler32.obj: adler32.c zlib.h zconf.h
+adler32.obj: $(TOP)/adler32.c $(TOP)/zlib.h $(TOP)/zconf.h
+
+compress.obj: $(TOP)/compress.c $(TOP)/zlib.h $(TOP)/zconf.h
+
+crc32.obj: $(TOP)/crc32.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/crc32.h
+
+deflate.obj: $(TOP)/deflate.c $(TOP)/deflate.h $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h
+
+gzclose.obj: $(TOP)/gzclose.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
+
+gzlib.obj: $(TOP)/gzlib.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
+
+gzread.obj: $(TOP)/gzread.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
+
+gzwrite.obj: $(TOP)/gzwrite.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
 
-compress.obj: compress.c zlib.h zconf.h
+infback.obj: $(TOP)/infback.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \
+             $(TOP)/inffast.h $(TOP)/inffixed.h
 
-crc32.obj: crc32.c zlib.h zconf.h crc32.h
+inffast.obj: $(TOP)/inffast.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \
+             $(TOP)/inffast.h
 
-deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+inflate.obj: $(TOP)/inflate.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \
+             $(TOP)/inffast.h $(TOP)/inffixed.h
 
-gzio.obj: gzio.c zutil.h zlib.h zconf.h
+inftrees.obj: $(TOP)/inftrees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h
 
-infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
-             inffast.h inffixed.h
+trees.obj: $(TOP)/trees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/deflate.h $(TOP)/trees.h
 
-inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
-             inffast.h
+uncompr.obj: $(TOP)/uncompr.c $(TOP)/zlib.h $(TOP)/zconf.h
 
-inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
-             inffast.h inffixed.h
+zutil.obj: $(TOP)/zutil.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h
 
-inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+gvmat64.obj: $(TOP)/contrib\masmx64\gvmat64.asm
 
-trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+inffasx64.obj: $(TOP)/contrib\masmx64\inffasx64.asm
 
-uncompr.obj: uncompr.c zlib.h zconf.h
+inffas8664.obj: $(TOP)/contrib\masmx64\inffas8664.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h \
+		$(TOP)/inftrees.h $(TOP)/inflate.h $(TOP)/inffast.h
 
-zutil.obj: zutil.c zutil.h zlib.h zconf.h
+inffas32.obj: $(TOP)/contrib\masmx86\inffas32.asm
 
-example.obj: example.c zlib.h zconf.h
+match686.obj: $(TOP)/contrib\masmx86\match686.asm
 
-minigzip.obj: minigzip.c zlib.h zconf.h
+example.obj: $(TOP)/test/example.c $(TOP)/zlib.h $(TOP)/zconf.h
 
-zlib1.res: win32/zlib1.rc
-	$(RC) $(RCFLAGS) /fo$@ win32/zlib1.rc
+minigzip.obj: $(TOP)/test/minigzip.c $(TOP)/zlib.h $(TOP)/zconf.h
 
+zlib1.res: $(TOP)/win32/zlib1.rc
+	$(RC) $(RCFLAGS) /fo$@ $(TOP)/win32/zlib1.rc
 
 # testing
 test: example.exe minigzip.exe
@@ -123,4 +158,6 @@ clean:
 	-del *.res
 	-del *.exp
 	-del *.exe
+	-del *.pdb
+	-del *.manifest
 	-del foo.gz
diff --git a/third_party/zlib/win32/zlib.def b/third_party/zlib/win32/zlib.def
index a47cbc1..face655 100644
--- a/third_party/zlib/win32/zlib.def
+++ b/third_party/zlib/win32/zlib.def
@@ -1,6 +1,4 @@
-LIBRARY
 ; zlib data compression library
-
 EXPORTS
 ; basic functions
     zlibVersion
@@ -13,12 +11,20 @@ EXPORTS
     deflateCopy
     deflateReset
     deflateParams
+    deflateTune
     deflateBound
+    deflatePending
     deflatePrime
+    deflateSetHeader
     inflateSetDictionary
+    inflateGetDictionary
     inflateSync
     inflateCopy
     inflateReset
+    inflateReset2
+    inflatePrime
+    inflateMark
+    inflateGetHeader
     inflateBack
     inflateBackEnd
     zlibCompileFlags
@@ -29,10 +35,12 @@ EXPORTS
     uncompress
     gzopen
     gzdopen
+    gzbuffer
     gzsetparams
     gzread
     gzwrite
     gzprintf
+    gzvprintf
     gzputs
     gzgets
     gzputc
@@ -42,19 +50,37 @@ EXPORTS
     gzseek
     gzrewind
     gztell
+    gzoffset
     gzeof
+    gzdirect
     gzclose
+    gzclose_r
+    gzclose_w
     gzerror
     gzclearerr
+; large file functions
+    gzopen64
+    gzseek64
+    gztell64
+    gzoffset64
+    adler32_combine64
+    crc32_combine64
 ; checksum functions
     adler32
     crc32
+    adler32_combine
+    crc32_combine
 ; various hacks, don't look :)
     deflateInit_
     deflateInit2_
     inflateInit_
     inflateInit2_
     inflateBackInit_
+    gzgetc_
+    zError
     inflateSyncPoint
     get_crc_table
-    zError
+    inflateUndermine
+    inflateResetKeep
+    deflateResetKeep
+    gzopen_w
diff --git a/third_party/zlib/win32/zlib1.rc b/third_party/zlib/win32/zlib1.rc
index 99025c9..5c0feed 100644
--- a/third_party/zlib/win32/zlib1.rc
+++ b/third_party/zlib/win32/zlib1.rc
@@ -1,19 +1,20 @@
-#include <windows.h>
+#include <winver.h>
+#include "../zlib.h"
 
 #ifdef GCC_WINDRES
 VS_VERSION_INFO		VERSIONINFO
 #else
 VS_VERSION_INFO		VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
 #endif
-  FILEVERSION		1,2,2,0
-  PRODUCTVERSION	1,2,2,0
+  FILEVERSION		ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0
+  PRODUCTVERSION	ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0
   FILEFLAGSMASK		VS_FFI_FILEFLAGSMASK
 #ifdef _DEBUG
   FILEFLAGS		1
 #else
   FILEFLAGS		0
 #endif
-  FILEOS		VOS_DOS_WINDOWS32
+  FILEOS		VOS__WINDOWS32
   FILETYPE		VFT_DLL
   FILESUBTYPE		0	// not used
 BEGIN
@@ -23,13 +24,13 @@ BEGIN
     //language ID = U.S. English, char set = Windows, Multilingual
     BEGIN
       VALUE "FileDescription",	"zlib data compression library\0"
-      VALUE "FileVersion",	"1.2.3\0"
+      VALUE "FileVersion",	ZLIB_VERSION "\0"
       VALUE "InternalName",	"zlib1.dll\0"
-      VALUE "LegalCopyright",	"(C) 1995-2004 Jean-loup Gailly & Mark Adler\0"
+      VALUE "LegalCopyright",	"(C) 1995-2013 Jean-loup Gailly & Mark Adler\0"
       VALUE "OriginalFilename",	"zlib1.dll\0"
       VALUE "ProductName",	"zlib\0"
-      VALUE "ProductVersion",	"1.2.3\0"
-      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
+      VALUE "ProductVersion",	ZLIB_VERSION "\0"
+      VALUE "Comments",		"For more information visit http://www.zlib.net/\0"
     END
   END
   BLOCK "VarFileInfo"
diff --git a/third_party/zlib/zconf.h b/third_party/zlib/zconf.h
index 3742ad4..9987a77 100644
--- a/third_party/zlib/zconf.h
+++ b/third_party/zlib/zconf.h
@@ -1,65 +1,155 @@
 /* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * Copyright (C) 1995-2013 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 /* @(#) $Id$ */
 
-#include "replace.h"
-#define Z_PREFIX
-
 #ifndef ZCONF_H
 #define ZCONF_H
 
 /*
  * If you *really* need a unique prefix for all types and library functions,
  * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
  */
-#ifdef Z_PREFIX
-#  define deflateInit_          z_deflateInit_
+#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */
+#  define Z_PREFIX_SET
+
+/* all linked symbols */
+#  define _dist_code            z__dist_code
+#  define _length_code          z__length_code
+#  define _tr_align             z__tr_align
+#  define _tr_flush_bits        z__tr_flush_bits
+#  define _tr_flush_block       z__tr_flush_block
+#  define _tr_init              z__tr_init
+#  define _tr_stored_block      z__tr_stored_block
+#  define _tr_tally             z__tr_tally
+#  define adler32               z_adler32
+#  define adler32_combine       z_adler32_combine
+#  define adler32_combine64     z_adler32_combine64
+#  ifndef Z_SOLO
+#    define compress              z_compress
+#    define compress2             z_compress2
+#    define compressBound         z_compressBound
+#  endif
+#  define crc32                 z_crc32
+#  define crc32_combine         z_crc32_combine
+#  define crc32_combine64       z_crc32_combine64
 #  define deflate               z_deflate
+#  define deflateBound          z_deflateBound
+#  define deflateCopy           z_deflateCopy
 #  define deflateEnd            z_deflateEnd
-#  define inflateInit_          z_inflateInit_
-#  define inflate               z_inflate
-#  define inflateEnd            z_inflateEnd
 #  define deflateInit2_         z_deflateInit2_
-#  define deflateSetDictionary  z_deflateSetDictionary
-#  define deflateCopy           z_deflateCopy
-#  define deflateReset          z_deflateReset
+#  define deflateInit_          z_deflateInit_
 #  define deflateParams         z_deflateParams
-#  define deflateBound          z_deflateBound
+#  define deflatePending        z_deflatePending
 #  define deflatePrime          z_deflatePrime
+#  define deflateReset          z_deflateReset
+#  define deflateResetKeep      z_deflateResetKeep
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateSetHeader      z_deflateSetHeader
+#  define deflateTune           z_deflateTune
+#  define deflate_copyright     z_deflate_copyright
+#  define get_crc_table         z_get_crc_table
+#  ifndef Z_SOLO
+#    define gz_error              z_gz_error
+#    define gz_intmax             z_gz_intmax
+#    define gz_strwinerror        z_gz_strwinerror
+#    define gzbuffer              z_gzbuffer
+#    define gzclearerr            z_gzclearerr
+#    define gzclose               z_gzclose
+#    define gzclose_r             z_gzclose_r
+#    define gzclose_w             z_gzclose_w
+#    define gzdirect              z_gzdirect
+#    define gzdopen               z_gzdopen
+#    define gzeof                 z_gzeof
+#    define gzerror               z_gzerror
+#    define gzflush               z_gzflush
+#    define gzgetc                z_gzgetc
+#    define gzgetc_               z_gzgetc_
+#    define gzgets                z_gzgets
+#    define gzoffset              z_gzoffset
+#    define gzoffset64            z_gzoffset64
+#    define gzopen                z_gzopen
+#    define gzopen64              z_gzopen64
+#    ifdef _WIN32
+#      define gzopen_w              z_gzopen_w
+#    endif
+#    define gzprintf              z_gzprintf
+#    define gzvprintf             z_gzvprintf
+#    define gzputc                z_gzputc
+#    define gzputs                z_gzputs
+#    define gzread                z_gzread
+#    define gzrewind              z_gzrewind
+#    define gzseek                z_gzseek
+#    define gzseek64              z_gzseek64
+#    define gzsetparams           z_gzsetparams
+#    define gztell                z_gztell
+#    define gztell64              z_gztell64
+#    define gzungetc              z_gzungetc
+#    define gzwrite               z_gzwrite
+#  endif
+#  define inflate               z_inflate
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define inflateBackInit_      z_inflateBackInit_
+#  define inflateCopy           z_inflateCopy
+#  define inflateEnd            z_inflateEnd
+#  define inflateGetHeader      z_inflateGetHeader
 #  define inflateInit2_         z_inflateInit2_
+#  define inflateInit_          z_inflateInit_
+#  define inflateMark           z_inflateMark
+#  define inflatePrime          z_inflatePrime
+#  define inflateReset          z_inflateReset
+#  define inflateReset2         z_inflateReset2
 #  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateGetDictionary  z_inflateGetDictionary
 #  define inflateSync           z_inflateSync
 #  define inflateSyncPoint      z_inflateSyncPoint
-#  define inflateCopy           z_inflateCopy
-#  define inflateReset          z_inflateReset
-#  define inflateBack           z_inflateBack
-#  define inflateBackEnd        z_inflateBackEnd
-#  define compress              z_compress
-#  define compress2             z_compress2
-#  define compressBound         z_compressBound
-#  define uncompress            z_uncompress
-#  define adler32               z_adler32
-#  define crc32                 z_crc32
-#  define get_crc_table         z_get_crc_table
+#  define inflateUndermine      z_inflateUndermine
+#  define inflateResetKeep      z_inflateResetKeep
+#  define inflate_copyright     z_inflate_copyright
+#  define inflate_fast          z_inflate_fast
+#  define inflate_table         z_inflate_table
+#  ifndef Z_SOLO
+#    define uncompress            z_uncompress
+#  endif
 #  define zError                z_zError
+#  ifndef Z_SOLO
+#    define zcalloc               z_zcalloc
+#    define zcfree                z_zcfree
+#  endif
+#  define zlibCompileFlags      z_zlibCompileFlags
+#  define zlibVersion           z_zlibVersion
 
+/* all zlib typedefs in zlib.h and zconf.h */
+#  define Byte                  z_Byte
+#  define Bytef                 z_Bytef
 #  define alloc_func            z_alloc_func
+#  define charf                 z_charf
 #  define free_func             z_free_func
+#  ifndef Z_SOLO
+#    define gzFile                z_gzFile
+#  endif
+#  define gz_header             z_gz_header
+#  define gz_headerp            z_gz_headerp
 #  define in_func               z_in_func
+#  define intf                  z_intf
 #  define out_func              z_out_func
-#  define Byte                  z_Byte
 #  define uInt                  z_uInt
-#  define uLong                 z_uLong
-#  define Bytef                 z_Bytef
-#  define charf                 z_charf
-#  define intf                  z_intf
 #  define uIntf                 z_uIntf
+#  define uLong                 z_uLong
 #  define uLongf                z_uLongf
-#  define voidpf                z_voidpf
 #  define voidp                 z_voidp
+#  define voidpc                z_voidpc
+#  define voidpf                z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+#  define gz_header_s           z_gz_header_s
+#  define internal_state        z_internal_state
+
 #endif
 
 #if defined(__MSDOS__) && !defined(MSDOS)
@@ -128,6 +218,12 @@
 #  endif
 #endif
 
+#if defined(ZLIB_CONST) && !defined(z_const)
+#  define z_const const
+#else
+#  define z_const
+#endif
+
 /* Some Mac compilers merge all .h files incorrectly: */
 #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
 #  define NO_DUMMY_DECL
@@ -174,6 +270,14 @@
 #  endif
 #endif
 
+#ifndef Z_ARG /* function prototypes for stdarg */
+#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#    define Z_ARG(args)  args
+#  else
+#    define Z_ARG(args)  ()
+#  endif
+#endif
+
 /* The following definitions for FAR are needed only for MSDOS mixed
  * model programming (small or medium model with some far allocations).
  * This was tested only with MSC; for other MSDOS compilers you may have
@@ -287,49 +391,121 @@ typedef uLong FAR uLongf;
    typedef Byte       *voidp;
 #endif
 
-#if 0           /* HAVE_UNISTD_H -- this line is updated by ./configure */
-#  include <sys/types.h> /* for off_t */
-#  include <unistd.h>    /* for SEEK_* and off_t */
-#  ifdef VMS
-#    include <unixio.h>   /* for off_t */
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+#  include <limits.h>
+#  if (UINT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned
+#  elif (ULONG_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned long
+#  elif (USHRT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned short
+#  endif
+#endif
+
+#ifdef Z_U4
+   typedef Z_U4 z_crc_t;
+#else
+   typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */
+#  define Z_HAVE_UNISTD_H
+#endif
+
+#ifdef HAVE_STDARG_H    /* may be set to #if 1 by ./configure */
+#  define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+#  ifndef Z_SOLO
+#    include <sys/types.h>      /* for off_t */
+#  endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifndef Z_SOLO
+#    include <stdarg.h>         /* for va_list */
 #  endif
-#  define z_off_t off_t
 #endif
-#ifndef SEEK_SET
+
+#ifdef _WIN32
+#  ifndef Z_SOLO
+#    include <stddef.h>         /* for wchar_t */
+#  endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+#  undef _LARGEFILE64_SOURCE
+#endif
+
+#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
+#  define Z_HAVE_UNISTD_H
+#endif
+#ifndef Z_SOLO
+#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
+#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+#    ifdef VMS
+#      include <unixio.h>       /* for off_t */
+#    endif
+#    ifndef z_off_t
+#      define z_off_t off_t
+#    endif
+#  endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+#  define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+#  define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+#  define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
 #  define SEEK_SET        0       /* Seek from beginning of file.  */
 #  define SEEK_CUR        1       /* Seek from current position.  */
 #  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
 #endif
+
 #ifndef z_off_t
 #  define z_off_t long
 #endif
 
-#if defined(__OS400__)
-#  define NO_vsnprintf
-#endif
-
-#if defined(__MVS__)
-#  define NO_vsnprintf
-#  ifdef FAR
-#    undef FAR
+#if !defined(_WIN32) && defined(Z_LARGE64)
+#  define z_off64_t off64_t
+#else
+#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+#    define z_off64_t __int64
+#  else
+#    define z_off64_t z_off_t
 #  endif
 #endif
 
 /* MVS linker does not support external names larger than 8 bytes */
 #if defined(__MVS__)
-#   pragma map(deflateInit_,"DEIN")
-#   pragma map(deflateInit2_,"DEIN2")
-#   pragma map(deflateEnd,"DEEND")
-#   pragma map(deflateBound,"DEBND")
-#   pragma map(inflateInit_,"ININ")
-#   pragma map(inflateInit2_,"ININ2")
-#   pragma map(inflateEnd,"INEND")
-#   pragma map(inflateSync,"INSY")
-#   pragma map(inflateSetDictionary,"INSEDI")
-#   pragma map(compressBound,"CMBND")
-#   pragma map(inflate_table,"INTABL")
-#   pragma map(inflate_fast,"INFA")
-#   pragma map(inflate_copyright,"INCOPY")
+  #pragma map(deflateInit_,"DEIN")
+  #pragma map(deflateInit2_,"DEIN2")
+  #pragma map(deflateEnd,"DEEND")
+  #pragma map(deflateBound,"DEBND")
+  #pragma map(inflateInit_,"ININ")
+  #pragma map(inflateInit2_,"ININ2")
+  #pragma map(inflateEnd,"INEND")
+  #pragma map(inflateSync,"INSY")
+  #pragma map(inflateSetDictionary,"INSEDI")
+  #pragma map(compressBound,"CMBND")
+  #pragma map(inflate_table,"INTABL")
+  #pragma map(inflate_fast,"INFA")
+  #pragma map(inflate_copyright,"INCOPY")
 #endif
 
 #endif /* ZCONF_H */
diff --git a/third_party/zlib/zconf.in.h b/third_party/zlib/zconf.in.h
deleted file mode 100644
index 03a9431..0000000
--- a/third_party/zlib/zconf.in.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2005 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* @(#) $Id$ */
-
-#ifndef ZCONF_H
-#define ZCONF_H
-
-/*
- * If you *really* need a unique prefix for all types and library functions,
- * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
- */
-#ifdef Z_PREFIX
-#  define deflateInit_          z_deflateInit_
-#  define deflate               z_deflate
-#  define deflateEnd            z_deflateEnd
-#  define inflateInit_          z_inflateInit_
-#  define inflate               z_inflate
-#  define inflateEnd            z_inflateEnd
-#  define deflateInit2_         z_deflateInit2_
-#  define deflateSetDictionary  z_deflateSetDictionary
-#  define deflateCopy           z_deflateCopy
-#  define deflateReset          z_deflateReset
-#  define deflateParams         z_deflateParams
-#  define deflateBound          z_deflateBound
-#  define deflatePrime          z_deflatePrime
-#  define inflateInit2_         z_inflateInit2_
-#  define inflateSetDictionary  z_inflateSetDictionary
-#  define inflateSync           z_inflateSync
-#  define inflateSyncPoint      z_inflateSyncPoint
-#  define inflateCopy           z_inflateCopy
-#  define inflateReset          z_inflateReset
-#  define inflateBack           z_inflateBack
-#  define inflateBackEnd        z_inflateBackEnd
-#  define compress              z_compress
-#  define compress2             z_compress2
-#  define compressBound         z_compressBound
-#  define uncompress            z_uncompress
-#  define adler32               z_adler32
-#  define crc32                 z_crc32
-#  define get_crc_table         z_get_crc_table
-#  define zError                z_zError
-
-#  define alloc_func            z_alloc_func
-#  define free_func             z_free_func
-#  define in_func               z_in_func
-#  define out_func              z_out_func
-#  define Byte                  z_Byte
-#  define uInt                  z_uInt
-#  define uLong                 z_uLong
-#  define Bytef                 z_Bytef
-#  define charf                 z_charf
-#  define intf                  z_intf
-#  define uIntf                 z_uIntf
-#  define uLongf                z_uLongf
-#  define voidpf                z_voidpf
-#  define voidp                 z_voidp
-#endif
-
-#if defined(__MSDOS__) && !defined(MSDOS)
-#  define MSDOS
-#endif
-#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
-#  define OS2
-#endif
-#if defined(_WINDOWS) && !defined(WINDOWS)
-#  define WINDOWS
-#endif
-#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
-#  ifndef WIN32
-#    define WIN32
-#  endif
-#endif
-#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
-#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
-#    ifndef SYS16BIT
-#      define SYS16BIT
-#    endif
-#  endif
-#endif
-
-/*
- * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
- * than 64k bytes at a time (needed on systems with 16-bit int).
- */
-#ifdef SYS16BIT
-#  define MAXSEG_64K
-#endif
-#ifdef MSDOS
-#  define UNALIGNED_OK
-#endif
-
-#ifdef __STDC_VERSION__
-#  ifndef STDC
-#    define STDC
-#  endif
-#  if __STDC_VERSION__ >= 199901L
-#    ifndef STDC99
-#      define STDC99
-#    endif
-#  endif
-#endif
-#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
-#  define STDC
-#endif
-#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
-#  define STDC
-#endif
-#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
-#  define STDC
-#endif
-#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
-#  define STDC
-#endif
-
-#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
-#  define STDC
-#endif
-
-#ifndef STDC
-#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
-#    define const       /* note: need a more gentle solution here */
-#  endif
-#endif
-
-/* Some Mac compilers merge all .h files incorrectly: */
-#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
-#  define NO_DUMMY_DECL
-#endif
-
-/* Maximum value for memLevel in deflateInit2 */
-#ifndef MAX_MEM_LEVEL
-#  ifdef MAXSEG_64K
-#    define MAX_MEM_LEVEL 8
-#  else
-#    define MAX_MEM_LEVEL 9
-#  endif
-#endif
-
-/* Maximum value for windowBits in deflateInit2 and inflateInit2.
- * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
- * created by gzip. (Files created by minigzip can still be extracted by
- * gzip.)
- */
-#ifndef MAX_WBITS
-#  define MAX_WBITS   15 /* 32K LZ77 window */
-#endif
-
-/* The memory requirements for deflate are (in bytes):
-            (1 << (windowBits+2)) +  (1 << (memLevel+9))
- that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
- plus a few kilobytes for small objects. For example, if you want to reduce
- the default memory requirements from 256K to 128K, compile with
-     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
- Of course this will generally degrade compression (there's no free lunch).
-
-   The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
- for small objects.
-*/
-
-                        /* Type declarations */
-
-#ifndef OF /* function prototypes */
-#  ifdef STDC
-#    define OF(args)  args
-#  else
-#    define OF(args)  ()
-#  endif
-#endif
-
-/* The following definitions for FAR are needed only for MSDOS mixed
- * model programming (small or medium model with some far allocations).
- * This was tested only with MSC; for other MSDOS compilers you may have
- * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
- * just define FAR to be empty.
- */
-#ifdef SYS16BIT
-#  if defined(M_I86SM) || defined(M_I86MM)
-     /* MSC small or medium model */
-#    define SMALL_MEDIUM
-#    ifdef _MSC_VER
-#      define FAR _far
-#    else
-#      define FAR far
-#    endif
-#  endif
-#  if (defined(__SMALL__) || defined(__MEDIUM__))
-     /* Turbo C small or medium model */
-#    define SMALL_MEDIUM
-#    ifdef __BORLANDC__
-#      define FAR _far
-#    else
-#      define FAR far
-#    endif
-#  endif
-#endif
-
-#if defined(WINDOWS) || defined(WIN32)
-   /* If building or using zlib as a DLL, define ZLIB_DLL.
-    * This is not mandatory, but it offers a little performance increase.
-    */
-#  ifdef ZLIB_DLL
-#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
-#      ifdef ZLIB_INTERNAL
-#        define ZEXTERN extern __declspec(dllexport)
-#      else
-#        define ZEXTERN extern __declspec(dllimport)
-#      endif
-#    endif
-#  endif  /* ZLIB_DLL */
-   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
-    * define ZLIB_WINAPI.
-    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
-    */
-#  ifdef ZLIB_WINAPI
-#    ifdef FAR
-#      undef FAR
-#    endif
-#    include <windows.h>
-     /* No need for _export, use ZLIB.DEF instead. */
-     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
-#    define ZEXPORT WINAPI
-#    ifdef WIN32
-#      define ZEXPORTVA WINAPIV
-#    else
-#      define ZEXPORTVA FAR CDECL
-#    endif
-#  endif
-#endif
-
-#if defined (__BEOS__)
-#  ifdef ZLIB_DLL
-#    ifdef ZLIB_INTERNAL
-#      define ZEXPORT   __declspec(dllexport)
-#      define ZEXPORTVA __declspec(dllexport)
-#    else
-#      define ZEXPORT   __declspec(dllimport)
-#      define ZEXPORTVA __declspec(dllimport)
-#    endif
-#  endif
-#endif
-
-#ifndef ZEXTERN
-#  define ZEXTERN extern
-#endif
-#ifndef ZEXPORT
-#  define ZEXPORT
-#endif
-#ifndef ZEXPORTVA
-#  define ZEXPORTVA
-#endif
-
-#ifndef FAR
-#  define FAR
-#endif
-
-#if !defined(__MACTYPES__)
-typedef unsigned char  Byte;  /* 8 bits */
-#endif
-typedef unsigned int   uInt;  /* 16 bits or more */
-typedef unsigned long  uLong; /* 32 bits or more */
-
-#ifdef SMALL_MEDIUM
-   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
-#  define Bytef Byte FAR
-#else
-   typedef Byte  FAR Bytef;
-#endif
-typedef char  FAR charf;
-typedef int   FAR intf;
-typedef uInt  FAR uIntf;
-typedef uLong FAR uLongf;
-
-#ifdef STDC
-   typedef void const *voidpc;
-   typedef void FAR   *voidpf;
-   typedef void       *voidp;
-#else
-   typedef Byte const *voidpc;
-   typedef Byte FAR   *voidpf;
-   typedef Byte       *voidp;
-#endif
-
-#if 0           /* HAVE_UNISTD_H -- this line is updated by ./configure */
-#  include <sys/types.h> /* for off_t */
-#  include <unistd.h>    /* for SEEK_* and off_t */
-#  ifdef VMS
-#    include <unixio.h>   /* for off_t */
-#  endif
-#  define z_off_t off_t
-#endif
-#ifndef SEEK_SET
-#  define SEEK_SET        0       /* Seek from beginning of file.  */
-#  define SEEK_CUR        1       /* Seek from current position.  */
-#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
-#endif
-#ifndef z_off_t
-#  define z_off_t long
-#endif
-
-#if defined(__OS400__)
-#  define NO_vsnprintf
-#endif
-
-#if defined(__MVS__)
-#  define NO_vsnprintf
-#  ifdef FAR
-#    undef FAR
-#  endif
-#endif
-
-/* MVS linker does not support external names larger than 8 bytes */
-#if defined(__MVS__)
-#   pragma map(deflateInit_,"DEIN")
-#   pragma map(deflateInit2_,"DEIN2")
-#   pragma map(deflateEnd,"DEEND")
-#   pragma map(deflateBound,"DEBND")
-#   pragma map(inflateInit_,"ININ")
-#   pragma map(inflateInit2_,"ININ2")
-#   pragma map(inflateEnd,"INEND")
-#   pragma map(inflateSync,"INSY")
-#   pragma map(inflateSetDictionary,"INSEDI")
-#   pragma map(compressBound,"CMBND")
-#   pragma map(inflate_table,"INTABL")
-#   pragma map(inflate_fast,"INFA")
-#   pragma map(inflate_copyright,"INCOPY")
-#endif
-
-#endif /* ZCONF_H */
diff --git a/third_party/zlib/zlib.h b/third_party/zlib/zlib.h
index aa7f082..3e0c767 100644
--- a/third_party/zlib/zlib.h
+++ b/third_party/zlib/zlib.h
@@ -1,7 +1,7 @@
 /* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 1.2.3, July 18th, 2005
+  version 1.2.8, April 28th, 2013
 
-  Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+  Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -24,8 +24,8 @@
 
 
   The data format used by the zlib library is described by RFCs (Request for
-  Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
-  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+  Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+  (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
 */
 
 #ifndef ZLIB_H
@@ -37,47 +37,44 @@
 extern "C" {
 #endif
 
-#define ZLIB_VERSION "1.2.3.1.Samba"
-#define ZLIB_VERNUM 0x1231
-/*
- * Modified for Samba by Stefan Metzmacher <metze at samba.org> 2008
- *
- * inflateReset2() added and compiler warnings fixed
- */
-
+#define ZLIB_VERSION "1.2.8"
+#define ZLIB_VERNUM 0x1280
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 2
+#define ZLIB_VER_REVISION 8
+#define ZLIB_VER_SUBREVISION 0
 
 /*
-     The 'zlib' compression library provides in-memory compression and
-  decompression functions, including integrity checks of the uncompressed
-  data.  This version of the library supports only one compression method
-  (deflation) but other algorithms will be added later and will have the same
-  stream interface.
-
-     Compression can be done in a single step if the buffers are large
-  enough (for example if an input file is mmap'ed), or can be done by
-  repeated calls of the compression function.  In the latter case, the
-  application must provide more input and/or consume the output
+    The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed data.
+  This version of the library supports only one compression method (deflation)
+  but other algorithms will be added later and will have the same stream
+  interface.
+
+    Compression can be done in a single step if the buffers are large enough,
+  or can be done by repeated calls of the compression function.  In the latter
+  case, the application must provide more input and/or consume the output
   (providing more output space) before each call.
 
-     The compressed data format used by default by the in-memory functions is
+    The compressed data format used by default by the in-memory functions is
   the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
   around a deflate stream, which is itself documented in RFC 1951.
 
-     The library also supports reading and writing files in gzip (.gz) format
+    The library also supports reading and writing files in gzip (.gz) format
   with an interface similar to that of stdio using the functions that start
   with "gz".  The gzip format is different from the zlib format.  gzip is a
   gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
 
-     This library can optionally read and write gzip streams in memory as well.
+    This library can optionally read and write gzip streams in memory as well.
 
-     The zlib format was designed to be compact and fast for use in memory
+    The zlib format was designed to be compact and fast for use in memory
   and on communications channels.  The gzip format was designed for single-
   file compression on file systems, has a larger header than zlib to maintain
   directory information, and uses a different, slower check method than zlib.
 
-     The library does not install any signal handler. The decoder checks
-  the consistency of the compressed data, so the library should never
-  crash even in case of corrupted input.
+    The library does not install any signal handler.  The decoder checks
+  the consistency of the compressed data, so the library should never crash
+  even in case of corrupted input.
 */
 
 typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
@@ -86,15 +83,15 @@ typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
 struct internal_state;
 
 typedef struct z_stream_s {
-    const Bytef *next_in; /* next input byte */
+    z_const Bytef *next_in;     /* next input byte */
     uInt     avail_in;  /* number of bytes available at next_in */
-    uLong    total_in;  /* total nb of input bytes read so far */
+    uLong    total_in;  /* total number of input bytes read so far */
 
     Bytef    *next_out; /* next output byte should be put there */
     uInt     avail_out; /* remaining free space at next_out */
-    uLong    total_out; /* total nb of bytes output so far */
+    uLong    total_out; /* total number of bytes output so far */
 
-    const char    *msg; /* last error message, NULL if no error */
+    z_const char *msg;  /* last error message, NULL if no error */
     struct internal_state FAR *state; /* not visible by applications */
 
     alloc_func zalloc;  /* used to allocate the internal state */
@@ -132,45 +129,45 @@ typedef struct gz_header_s {
 typedef gz_header FAR *gz_headerp;
 
 /*
-   The application must update next_in and avail_in when avail_in has
-   dropped to zero. It must update next_out and avail_out when avail_out
-   has dropped to zero. The application must initialize zalloc, zfree and
-   opaque before calling the init function. All other fields are set by the
-   compression library and must not be updated by the application.
-
-   The opaque value provided by the application will be passed as the first
-   parameter for calls of zalloc and zfree. This can be useful for custom
-   memory management. The compression library attaches no meaning to the
+     The application must update next_in and avail_in when avail_in has dropped
+   to zero.  It must update next_out and avail_out when avail_out has dropped
+   to zero.  The application must initialize zalloc, zfree and opaque before
+   calling the init function.  All other fields are set by the compression
+   library and must not be updated by the application.
+
+     The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree.  This can be useful for custom
+   memory management.  The compression library attaches no meaning to the
    opaque value.
 
-   zalloc must return Z_NULL if there is not enough memory for the object.
+     zalloc must return Z_NULL if there is not enough memory for the object.
    If zlib is used in a multi-threaded application, zalloc and zfree must be
    thread safe.
 
-   On 16-bit systems, the functions zalloc and zfree must be able to allocate
-   exactly 65536 bytes, but will not be required to allocate more than this
-   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
-   pointers returned by zalloc for objects of exactly 65536 bytes *must*
-   have their offset normalized to zero. The default allocation function
-   provided by this library ensures this (see zutil.c). To reduce memory
-   requirements and avoid any allocation of 64K objects, at the expense of
-   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
-
-   The fields total_in and total_out can be used for statistics or
-   progress reports. After compression, total_in holds the total size of
-   the uncompressed data and may be saved for use in the decompressor
-   (particularly if the decompressor wants to decompress everything in
-   a single step).
+     On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this if
+   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers
+   returned by zalloc for objects of exactly 65536 bytes *must* have their
+   offset normalized to zero.  The default allocation function provided by this
+   library ensures this (see zutil.c).  To reduce memory requirements and avoid
+   any allocation of 64K objects, at the expense of compression ratio, compile
+   the library with -DMAX_WBITS=14 (see zconf.h).
+
+     The fields total_in and total_out can be used for statistics or progress
+   reports.  After compression, total_in holds the total size of the
+   uncompressed data and may be saved for use in the decompressor (particularly
+   if the decompressor wants to decompress everything in a single step).
 */
 
                         /* constants */
 
 #define Z_NO_FLUSH      0
-#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_PARTIAL_FLUSH 1
 #define Z_SYNC_FLUSH    2
 #define Z_FULL_FLUSH    3
 #define Z_FINISH        4
 #define Z_BLOCK         5
+#define Z_TREES         6
 /* Allowed flush values; see deflate() and inflate() below for details */
 
 #define Z_OK            0
@@ -182,8 +179,8 @@ typedef gz_header FAR *gz_headerp;
 #define Z_MEM_ERROR    (-4)
 #define Z_BUF_ERROR    (-5)
 #define Z_VERSION_ERROR (-6)
-/* Return codes for the compression/decompression functions. Negative
- * values are errors, positive values are used for special but normal events.
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
  */
 
 #define Z_NO_COMPRESSION         0
@@ -213,129 +210,141 @@ typedef gz_header FAR *gz_headerp;
 #define zlib_version zlibVersion()
 /* for compatibility with versions < 1.0.2 */
 
-#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1)
-/** Use gcc attribute to check printf fns.  a1 is the 1-based index of
- * the parameter containing the format, and a2 the index of the first
- * argument. Note that some gcc 2.x versions don't handle this
- * properly **/
-#define _Z_PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
-#else
-#define _Z_PRINTF_ATTRIBUTE(a1, a2)
-#endif
 
                         /* basic functions */
 
 ZEXTERN const char * ZEXPORT zlibVersion OF((void));
 /* The application can compare zlibVersion and ZLIB_VERSION for consistency.
-   If the first character differs, the library code actually used is
-   not compatible with the zlib.h header file used by the application.
-   This check is automatically made by deflateInit and inflateInit.
+   If the first character differs, the library code actually used is not
+   compatible with the zlib.h header file used by the application.  This check
+   is automatically made by deflateInit and inflateInit.
  */
 
 /*
 ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
 
-     Initializes the internal stream state for compression. The fields
-   zalloc, zfree and opaque must be initialized before by the caller.
-   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
-   use default allocation functions.
+     Initializes the internal stream state for compression.  The fields
+   zalloc, zfree and opaque must be initialized before by the caller.  If
+   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+   allocation functions.
 
      The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
-   1 gives best speed, 9 gives best compression, 0 gives no compression at
-   all (the input data is simply copied a block at a time).
-   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
-   compression (currently equivalent to level 6).
+   1 gives best speed, 9 gives best compression, 0 gives no compression at all
+   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION
+   requests a default compromise between speed and compression (currently
+   equivalent to level 6).
 
-     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if level is not a valid compression level, or
    Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
-   with the version assumed by the caller (ZLIB_VERSION).
-   msg is set to null if there is no error message.  deflateInit does not
-   perform any compression: this will be done by deflate().
+   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null
+   if there is no error message.  deflateInit does not perform any compression:
+   this will be done by deflate().
 */
 
 
 ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
 /*
     deflate compresses as much data as possible, and stops when the input
-  buffer becomes empty or the output buffer becomes full. It may introduce some
-  output latency (reading input without producing any output) except when
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
   forced to flush.
 
-    The detailed semantics are as follows. deflate performs one or both of the
+    The detailed semantics are as follows.  deflate performs one or both of the
   following actions:
 
   - Compress more input starting at next_in and update next_in and avail_in
-    accordingly. If not all input can be processed (because there is not
+    accordingly.  If not all input can be processed (because there is not
     enough room in the output buffer), next_in and avail_in are updated and
     processing will resume at this point for the next call of deflate().
 
   - Provide more output starting at next_out and update next_out and avail_out
-    accordingly. This action is forced if the parameter flush is non zero.
+    accordingly.  This action is forced if the parameter flush is non zero.
     Forcing flush frequently degrades the compression ratio, so this parameter
-    should be set only when necessary (in interactive applications).
-    Some output may be provided even if flush is not set.
-
-  Before the call of deflate(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming
-  more output, and updating avail_in or avail_out accordingly; avail_out
-  should never be zero before the call. The application can consume the
-  compressed output when it wants, for example when the output buffer is full
-  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
-  and with zero avail_out, it must be called again after making room in the
-  output buffer because there might be more output pending.
+    should be set only when necessary (in interactive applications).  Some
+    output may be provided even if flush is not set.
+
+    Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating avail_in or avail_out accordingly; avail_out should
+  never be zero before the call.  The application can consume the compressed
+  output when it wants, for example when the output buffer is full (avail_out
+  == 0), or after each call of deflate().  If deflate returns Z_OK and with
+  zero avail_out, it must be called again after making room in the output
+  buffer because there might be more output pending.
 
     Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
-  decide how much data to accumualte before producing output, in order to
+  decide how much data to accumulate before producing output, in order to
   maximize compression.
 
     If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
   flushed to the output buffer and the output is aligned on a byte boundary, so
-  that the decompressor can get all input data available so far. (In particular
-  avail_in is zero after the call if enough output space has been provided
-  before the call.)  Flushing may degrade compression for some compression
-  algorithms and so it should be used only when necessary.
+  that the decompressor can get all input data available so far.  (In
+  particular avail_in is zero after the call if enough output space has been
+  provided before the call.) Flushing may degrade compression for some
+  compression algorithms and so it should be used only when necessary.  This
+  completes the current deflate block and follows it with an empty stored block
+  that is three bits plus filler bits to the next byte, followed by four bytes
+  (00 00 ff ff).
+
+    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+  output buffer, but the output is not aligned to a byte boundary.  All of the
+  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+  This completes the current deflate block and follows it with an empty fixed
+  codes block that is 10 bits long.  This assures that enough bytes are output
+  in order for the decompressor to finish the block before the empty fixed code
+  block.
+
+    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+  seven bits of the current block are held to be written as the next byte after
+  the next deflate block is completed.  In this case, the decompressor may not
+  be provided enough bits at this point in order to complete decompression of
+  the data provided so far to the compressor.  It may need to wait for the next
+  block to be emitted.  This is for advanced applications that need to control
+  the emission of deflate blocks.
 
     If flush is set to Z_FULL_FLUSH, all output is flushed as with
   Z_SYNC_FLUSH, and the compression state is reset so that decompression can
   restart from this point if previous compressed data has been damaged or if
-  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade
   compression.
 
     If deflate returns with avail_out == 0, this function must be called again
   with the same value of the flush parameter and more output space (updated
   avail_out), until the flush is complete (deflate returns with non-zero
-  avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
   avail_out is greater than six to avoid repeated flush markers due to
   avail_out == 0 on return.
 
     If the parameter flush is set to Z_FINISH, pending input is processed,
-  pending output is flushed and deflate returns with Z_STREAM_END if there
-  was enough output space; if deflate returns with Z_OK, this function must be
+  pending output is flushed and deflate returns with Z_STREAM_END if there was
+  enough output space; if deflate returns with Z_OK, this function must be
   called again with Z_FINISH and more output space (updated avail_out) but no
-  more input data, until it returns with Z_STREAM_END or an error. After
-  deflate has returned Z_STREAM_END, the only possible operations on the
-  stream are deflateReset or deflateEnd.
+  more input data, until it returns with Z_STREAM_END or an error.  After
+  deflate has returned Z_STREAM_END, the only possible operations on the stream
+  are deflateReset or deflateEnd.
 
     Z_FINISH can be used immediately after deflateInit if all the compression
-  is to be done in a single step. In this case, avail_out must be at least
-  the value returned by deflateBound (see below). If deflate does not return
-  Z_STREAM_END, then it must be called again as described above.
+  is to be done in a single step.  In this case, avail_out must be at least the
+  value returned by deflateBound (see below).  Then deflate is guaranteed to
+  return Z_STREAM_END.  If not enough output space is provided, deflate will
+  not return Z_STREAM_END, and it must be called again as described above.
 
     deflate() sets strm->adler to the adler32 checksum of all input read
   so far (that is, total_in bytes).
 
     deflate() may update strm->data_type if it can make a good guess about
-  the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
-  binary. This field is only for information purposes and does not affect
-  the compression algorithm in any manner.
+  the input data type (Z_BINARY or Z_TEXT).  In doubt, the data is considered
+  binary.  This field is only for information purposes and does not affect the
+  compression algorithm in any manner.
 
     deflate() returns Z_OK if some progress has been made (more input
   processed or more output produced), Z_STREAM_END if all input has been
   consumed and all output has been produced (only when flush is set to
   Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
-  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
-  (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+  if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not
   fatal, and deflate() can be called again with more input and more output
   space to continue compressing.
 */
@@ -344,13 +353,13 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
 ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
 /*
      All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any
-   pending output.
+   This function discards any unprocessed input and does not flush any pending
+   output.
 
      deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
    stream state was inconsistent, Z_DATA_ERROR if the stream was freed
-   prematurely (some input or output was discarded). In the error case,
-   msg may be set but then points to a static string (which must not be
+   prematurely (some input or output was discarded).  In the error case, msg
+   may be set but then points to a static string (which must not be
    deallocated).
 */
 
@@ -358,10 +367,10 @@ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
 /*
 ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
 
-     Initializes the internal stream state for decompression. The fields
+     Initializes the internal stream state for decompression.  The fields
    next_in, avail_in, zalloc, zfree and opaque must be initialized before by
-   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
-   value depends on the compression method), inflateInit determines the
+   the caller.  If next_in is not Z_NULL and avail_in is large enough (the
+   exact value depends on the compression method), inflateInit determines the
    compression method from the zlib header and allocates all data structures
    accordingly; otherwise the allocation will be deferred to the first call of
    inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
@@ -369,95 +378,116 @@ ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
 
      inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
    memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
-   version assumed by the caller.  msg is set to null if there is no error
-   message. inflateInit does not perform any decompression apart from reading
-   the zlib header if present: this will be done by inflate().  (So next_in and
-   avail_in may be modified, but next_out and avail_out are unchanged.)
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit() does not process any header information -- that is deferred
+   until inflate() is called.
 */
 
 
 ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
 /*
     inflate decompresses as much data as possible, and stops when the input
-  buffer becomes empty or the output buffer becomes full. It may introduce
+  buffer becomes empty or the output buffer becomes full.  It may introduce
   some output latency (reading input without producing any output) except when
   forced to flush.
 
-  The detailed semantics are as follows. inflate performs one or both of the
+  The detailed semantics are as follows.  inflate performs one or both of the
   following actions:
 
   - Decompress more input starting at next_in and update next_in and avail_in
-    accordingly. If not all input can be processed (because there is not
-    enough room in the output buffer), next_in is updated and processing
-    will resume at this point for the next call of inflate().
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing will
+    resume at this point for the next call of inflate().
 
   - Provide more output starting at next_out and update next_out and avail_out
-    accordingly.  inflate() provides as much output as possible, until there
-    is no more input data or no more space in the output buffer (see below
-    about the flush parameter).
-
-  Before the call of inflate(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming
-  more output, and updating the next_* and avail_* values accordingly.
-  The application can consume the uncompressed output when it wants, for
-  example when the output buffer is full (avail_out == 0), or after each
-  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
-  must be called again after making room in the output buffer because there
-  might be more output pending.
-
-    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
-  Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
-  output as possible to the output buffer. Z_BLOCK requests that inflate() stop
-  if and when it gets to the next deflate block boundary. When decoding the
-  zlib or gzip format, this will cause inflate() to return immediately after
-  the header and before the first block. When doing a raw inflate, inflate()
-  will go ahead and process the first block, and will return when it gets to
-  the end of that block, or when it runs out of data.
+    accordingly.  inflate() provides as much output as possible, until there is
+    no more input data or no more space in the output buffer (see below about
+    the flush parameter).
+
+    Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating the next_* and avail_* values accordingly.  The
+  application can consume the uncompressed output when it wants, for example
+  when the output buffer is full (avail_out == 0), or after each call of
+  inflate().  If inflate returns Z_OK and with zero avail_out, it must be
+  called again after making room in the output buffer because there might be
+  more output pending.
+
+    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much
+  output as possible to the output buffer.  Z_BLOCK requests that inflate()
+  stop if and when it gets to the next deflate block boundary.  When decoding
+  the zlib or gzip format, this will cause inflate() to return immediately
+  after the header and before the first block.  When doing a raw inflate,
+  inflate() will go ahead and process the first block, and will return when it
+  gets to the end of that block, or when it runs out of data.
 
     The Z_BLOCK option assists in appending to or combining deflate streams.
   Also to assist in this, on return inflate() will set strm->data_type to the
-  number of unused bits in the last byte taken from strm->next_in, plus 64
-  if inflate() is currently decoding the last block in the deflate stream,
-  plus 128 if inflate() returned immediately after decoding an end-of-block
-  code or decoding the complete header up to just before the first byte of the
-  deflate stream. The end-of-block will not be indicated until all of the
-  uncompressed data from that block has been written to strm->next_out.  The
-  number of unused bits may in general be greater than seven, except when
-  bit 7 of data_type is set, in which case the number of unused bits will be
-  less than eight.
+  number of unused bits in the last byte taken from strm->next_in, plus 64 if
+  inflate() is currently decoding the last block in the deflate stream, plus
+  128 if inflate() returned immediately after decoding an end-of-block code or
+  decoding the complete header up to just before the first byte of the deflate
+  stream.  The end-of-block will not be indicated until all of the uncompressed
+  data from that block has been written to strm->next_out.  The number of
+  unused bits may in general be greater than seven, except when bit 7 of
+  data_type is set, in which case the number of unused bits will be less than
+  eight.  data_type is set as noted here every time inflate() returns for all
+  flush options, and so can be used to determine the amount of currently
+  consumed input in bits.
+
+    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+  end of each deflate block header is reached, before any actual data in that
+  block is decoded.  This allows the caller to determine the length of the
+  deflate block header for later use in random access within a deflate block.
+  256 is added to the value of strm->data_type when inflate() returns
+  immediately after reaching the end of the deflate block header.
 
     inflate() should normally be called until it returns Z_STREAM_END or an
-  error. However if all decompression is to be performed in a single step
-  (a single call of inflate), the parameter flush should be set to
-  Z_FINISH. In this case all pending input is processed and all pending
-  output is flushed; avail_out must be large enough to hold all the
-  uncompressed data. (The size of the uncompressed data may have been saved
-  by the compressor for this purpose.) The next operation on this stream must
-  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
-  is never required, but can be used to inform inflate that a faster approach
-  may be used for the single inflate() call.
+  error.  However if all decompression is to be performed in a single step (a
+  single call of inflate), the parameter flush should be set to Z_FINISH.  In
+  this case all pending input is processed and all pending output is flushed;
+  avail_out must be large enough to hold all of the uncompressed data for the
+  operation to complete.  (The size of the uncompressed data may have been
+  saved by the compressor for this purpose.) The use of Z_FINISH is not
+  required to perform an inflation in one step.  However it may be used to
+  inform inflate that a faster approach can be used for the single inflate()
+  call.  Z_FINISH also informs inflate to not maintain a sliding window if the
+  stream completes, which reduces inflate's memory footprint.  If the stream
+  does not complete, either because not all of the stream is provided or not
+  enough output space is provided, then a sliding window will be allocated and
+  inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+  been used.
 
      In this implementation, inflate() always flushes as much output as
   possible to the output buffer, and always uses the faster approach on the
-  first call. So the only effect of the flush parameter in this implementation
-  is on the return value of inflate(), as noted below, or when it returns early
-  because Z_BLOCK is used.
+  first call.  So the effects of the flush parameter in this implementation are
+  on the return value of inflate() as noted below, when inflate() returns early
+  when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+  memory for a sliding window when Z_FINISH is used.
 
      If a preset dictionary is needed after this call (see inflateSetDictionary
-  below), inflate sets strm->adler to the adler32 checksum of the dictionary
+  below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
   chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
-  strm->adler to the adler32 checksum of all output produced so far (that is,
+  strm->adler to the Adler-32 checksum of all output produced so far (that is,
   total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
-  below. At the end of the stream, inflate() checks that its computed adler32
+  below.  At the end of the stream, inflate() checks that its computed adler32
   checksum is equal to that saved by the compressor and returns Z_STREAM_END
   only if the checksum is correct.
 
-    inflate() will decompress and check either zlib-wrapped or gzip-wrapped
-  deflate data.  The header type is detected automatically.  Any information
-  contained in the gzip header is not retained, so applications that need that
-  information should instead use raw inflate, see inflateInit2() below, or
-  inflateBack() and perform their own processing of the gzip header and
-  trailer.
+    inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+  deflate data.  The header type is detected automatically, if requested when
+  initializing with inflateInit2().  Any information contained in the gzip
+  header is not retained, so applications that need that information should
+  instead use raw inflate, see inflateInit2() below, or inflateBack() and
+  perform their own processing of the gzip header and trailer.  When processing
+  gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+  producted so far.  The CRC-32 is checked against the gzip trailer.
 
     inflate() returns Z_OK if some progress has been made (more input processed
   or more output produced), Z_STREAM_END if the end of the compressed data has
@@ -465,27 +495,28 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
   preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
   corrupted (input stream not conforming to the zlib format or incorrect check
   value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
-  if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+  next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory,
   Z_BUF_ERROR if no progress is possible or if there was not enough room in the
-  output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+  output buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and
   inflate() can be called again with more input and more output space to
-  continue decompressing. If Z_DATA_ERROR is returned, the application may then
-  call inflateSync() to look for a good compression block if a partial recovery
-  of the data is desired.
+  continue decompressing.  If Z_DATA_ERROR is returned, the application may
+  then call inflateSync() to look for a good compression block if a partial
+  recovery of the data is desired.
 */
 
 
 ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
 /*
      All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any
-   pending output.
+   This function discards any unprocessed input and does not flush any pending
+   output.
 
      inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
-   was inconsistent. In the error case, msg may be set but then points to a
+   was inconsistent.  In the error case, msg may be set but then points to a
    static string (which must not be deallocated).
 */
 
+
                         /* Advanced functions */
 
 /*
@@ -500,55 +531,57 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
                                      int  memLevel,
                                      int  strategy));
 
-     This is another version of deflateInit with more compression options. The
-   fields next_in, zalloc, zfree and opaque must be initialized before by
-   the caller.
+     This is another version of deflateInit with more compression options.  The
+   fields next_in, zalloc, zfree and opaque must be initialized before by the
+   caller.
 
-     The method parameter is the compression method. It must be Z_DEFLATED in
+     The method parameter is the compression method.  It must be Z_DEFLATED in
    this version of the library.
 
      The windowBits parameter is the base two logarithm of the window size
-   (the size of the history buffer). It should be in the range 8..15 for this
-   version of the library. Larger values of this parameter result in better
-   compression at the expense of memory usage. The default value is 15 if
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library.  Larger values of this parameter result in better
+   compression at the expense of memory usage.  The default value is 15 if
    deflateInit is used instead.
 
-     windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
-   determines the window size. deflate() will then generate raw deflate data
+     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits
+   determines the window size.  deflate() will then generate raw deflate data
    with no zlib header or trailer, and will not compute an adler32 check value.
 
-     windowBits can also be greater than 15 for optional gzip encoding. Add
+     windowBits can also be greater than 15 for optional gzip encoding.  Add
    16 to windowBits to write a simple gzip header and trailer around the
-   compressed data instead of a zlib wrapper. The gzip header will have no
-   file name, no extra data, no comment, no modification time (set to zero),
-   no header crc, and the operating system will be set to 255 (unknown).  If a
+   compressed data instead of a zlib wrapper.  The gzip header will have no
+   file name, no extra data, no comment, no modification time (set to zero), no
+   header crc, and the operating system will be set to 255 (unknown).  If a
    gzip stream is being written, strm->adler is a crc32 instead of an adler32.
 
      The memLevel parameter specifies how much memory should be allocated
-   for the internal compression state. memLevel=1 uses minimum memory but
-   is slow and reduces compression ratio; memLevel=9 uses maximum memory
-   for optimal speed. The default value is 8. See zconf.h for total memory
-   usage as a function of windowBits and memLevel.
+   for the internal compression state.  memLevel=1 uses minimum memory but is
+   slow and reduces compression ratio; memLevel=9 uses maximum memory for
+   optimal speed.  The default value is 8.  See zconf.h for total memory usage
+   as a function of windowBits and memLevel.
 
-     The strategy parameter is used to tune the compression algorithm. Use the
+     The strategy parameter is used to tune the compression algorithm.  Use the
    value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
    filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
    string match), or Z_RLE to limit match distances to one (run-length
-   encoding). Filtered data consists mostly of small values with a somewhat
-   random distribution. In this case, the compression algorithm is tuned to
-   compress them better. The effect of Z_FILTERED is to force more Huffman
+   encoding).  Filtered data consists mostly of small values with a somewhat
+   random distribution.  In this case, the compression algorithm is tuned to
+   compress them better.  The effect of Z_FILTERED is to force more Huffman
    coding and less string matching; it is somewhat intermediate between
-   Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
-   Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
-   parameter only affects the compression ratio but not the correctness of the
-   compressed output even if it is not set appropriately.  Z_FIXED prevents the
-   use of dynamic Huffman codes, allowing for a simpler decoder for special
-   applications.
-
-      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
-   method). msg is set to null if there is no error message.  deflateInit2 does
-   not perform any compression: this will be done by deflate().
+   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as
+   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The
+   strategy parameter only affects the compression ratio but not the
+   correctness of the compressed output even if it is not set appropriately.
+   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+   decoder for special applications.
+
+     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is
+   set to null if there is no error message.  deflateInit2 does not perform any
+   compression: this will be done by deflate().
 */
 
 ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
@@ -556,38 +589,43 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
                                              uInt  dictLength));
 /*
      Initializes the compression dictionary from the given byte sequence
-   without producing any compressed output. This function must be called
-   immediately after deflateInit, deflateInit2 or deflateReset, before any
-   call of deflate. The compressor and decompressor must use exactly the same
-   dictionary (see inflateSetDictionary).
+   without producing any compressed output.  When using the zlib format, this
+   function must be called immediately after deflateInit, deflateInit2 or
+   deflateReset, and before any call of deflate.  When doing raw deflate, this
+   function must be called either before any call of deflate, or immediately
+   after the completion of a deflate block, i.e. after all input has been
+   consumed and all output has been delivered when using any of the flush
+   options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH.  The
+   compressor and decompressor must use exactly the same dictionary (see
+   inflateSetDictionary).
 
      The dictionary should consist of strings (byte sequences) that are likely
    to be encountered later in the data to be compressed, with the most commonly
-   used strings preferably put towards the end of the dictionary. Using a
+   used strings preferably put towards the end of the dictionary.  Using a
    dictionary is most useful when the data to be compressed is short and can be
    predicted with good accuracy; the data can then be compressed better than
    with the default empty dictionary.
 
      Depending on the size of the compression data structures selected by
    deflateInit or deflateInit2, a part of the dictionary may in effect be
-   discarded, for example if the dictionary is larger than the window size in
-   deflate or deflate2. Thus the strings most likely to be useful should be
-   put at the end of the dictionary, not at the front. In addition, the
-   current implementation of deflate will use at most the window size minus
-   262 bytes of the provided dictionary.
+   discarded, for example if the dictionary is larger than the window size
+   provided in deflateInit or deflateInit2.  Thus the strings most likely to be
+   useful should be put at the end of the dictionary, not at the front.  In
+   addition, the current implementation of deflate will use at most the window
+   size minus 262 bytes of the provided dictionary.
 
      Upon return of this function, strm->adler is set to the adler32 value
    of the dictionary; the decompressor may later use this value to determine
-   which dictionary has been used by the compressor. (The adler32 value
+   which dictionary has been used by the compressor.  (The adler32 value
    applies to the whole dictionary even if only a subset of the dictionary is
    actually used by the compressor.) If a raw deflate was requested, then the
    adler32 value is not computed and strm->adler is not set.
 
      deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
-   parameter is invalid (such as NULL dictionary) or the stream state is
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
    inconsistent (for example if deflate has already been called for this stream
-   or if the compression method is bsort). deflateSetDictionary does not
-   perform any compression: this will be done by deflate().
+   or if not at a block boundary for raw deflate).  deflateSetDictionary does
+   not perform any compression: this will be done by deflate().
 */
 
 ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
@@ -597,26 +635,26 @@ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
 
      This function can be useful when several compression strategies will be
    tried, for example when there are several ways of pre-processing the input
-   data with a filter. The streams that will be discarded should then be freed
+   data with a filter.  The streams that will be discarded should then be freed
    by calling deflateEnd.  Note that deflateCopy duplicates the internal
-   compression state which can be quite large, so this strategy is slow and
-   can consume lots of memory.
+   compression state which can be quite large, so this strategy is slow and can
+   consume lots of memory.
 
      deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
    enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
-   (such as zalloc being NULL). msg is left unchanged in both source and
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
    destination.
 */
 
 ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
 /*
      This function is equivalent to deflateEnd followed by deflateInit,
-   but does not free and reallocate all the internal compression state.
-   The stream will keep the same compression level and any other attributes
-   that may have been set by deflateInit2.
+   but does not free and reallocate all the internal compression state.  The
+   stream will keep the same compression level and any other attributes that
+   may have been set by deflateInit2.
 
-      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being NULL).
+     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
 */
 
 ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
@@ -626,18 +664,18 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
      Dynamically update the compression level and compression strategy.  The
    interpretation of level and strategy is as in deflateInit2.  This can be
    used to switch between compression and straight copy of the input data, or
-   to switch to a different kind of input data requiring a different
-   strategy. If the compression level is changed, the input available so far
-   is compressed with the old level (and may be flushed); the new level will
-   take effect only at the next call of deflate().
+   to switch to a different kind of input data requiring a different strategy.
+   If the compression level is changed, the input available so far is
+   compressed with the old level (and may be flushed); the new level will take
+   effect only at the next call of deflate().
 
      Before the call of deflateParams, the stream state must be set as for
-   a call of deflate(), since the currently available input may have to
-   be compressed and flushed. In particular, strm->avail_out must be non-zero.
+   a call of deflate(), since the currently available input may have to be
+   compressed and flushed.  In particular, strm->avail_out must be non-zero.
 
      deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
-   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
-   if strm->avail_out was zero.
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if
+   strm->avail_out was zero.
 */
 
 ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
@@ -661,31 +699,53 @@ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
                                        uLong sourceLen));
 /*
      deflateBound() returns an upper bound on the compressed size after
-   deflation of sourceLen bytes.  It must be called after deflateInit()
-   or deflateInit2().  This would be used to allocate an output buffer
-   for deflation in a single pass, and so would be called before deflate().
+   deflation of sourceLen bytes.  It must be called after deflateInit() or
+   deflateInit2(), and after deflateSetHeader(), if used.  This would be used
+   to allocate an output buffer for deflation in a single pass, and so would be
+   called before deflate().  If that first deflate() call is provided the
+   sourceLen input bytes, an output buffer allocated to the size returned by
+   deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+   to return Z_STREAM_END.  Note that it is possible for the compressed size to
+   be larger than the value returned by deflateBound() if flush options other
+   than Z_FINISH or Z_NO_FLUSH are used.
 */
 
+ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
+                                       unsigned *pending,
+                                       int *bits));
+/*
+     deflatePending() returns the number of bytes and bits of output that have
+   been generated, but not yet provided in the available output.  The bytes not
+   provided would be due to the available output space having being consumed.
+   The number of bits of output not provided are between 0 and 7, where they
+   await more bits to join them in order to fill out a full byte.  If pending
+   or bits are Z_NULL, then those values are not set.
+
+     deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+ */
+
 ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
                                      int bits,
                                      int value));
 /*
      deflatePrime() inserts bits in the deflate output stream.  The intent
-  is that this function is used to start off the deflate output with the
-  bits leftover from a previous deflate stream when appending to it.  As such,
-  this function can only be used for raw deflate, and must be used before the
-  first deflate() call after a deflateInit2() or deflateReset().  bits must be
-  less than or equal to 16, and that many of the least significant bits of
-  value will be inserted in the output.
-
-      deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent.
+   is that this function is used to start off the deflate output with the bits
+   leftover from a previous deflate stream when appending to it.  As such, this
+   function can only be used for raw deflate, and must be used before the first
+   deflate() call after a deflateInit2() or deflateReset().  bits must be less
+   than or equal to 16, and that many of the least significant bits of value
+   will be inserted in the output.
+
+     deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+   room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+   source stream state was inconsistent.
 */
 
 ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
                                          gz_headerp head));
 /*
-      deflateSetHeader() provides gzip header information for when a gzip
+     deflateSetHeader() provides gzip header information for when a gzip
    stream is requested by deflateInit2().  deflateSetHeader() may be called
    after deflateInit2() or deflateReset() and before the first call of
    deflate().  The text, time, os, extra field, name, and comment information
@@ -698,11 +758,11 @@ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
    1.3.x) do not support header crc's, and will report that it is a "multi-part
    gzip file" and give up.
 
-      If deflateSetHeader is not used, the default gzip header has text false,
+     If deflateSetHeader is not used, the default gzip header has text false,
    the time set to zero, and os set to 255, with no extra, name, or comment
    fields.  The gzip header is returned to the default state by deflateReset().
 
-      deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
    stream state was inconsistent.
 */
 
@@ -710,43 +770,50 @@ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
 ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
                                      int  windowBits));
 
-     This is another version of inflateInit with an extra parameter. The
+     This is another version of inflateInit with an extra parameter.  The
    fields next_in, avail_in, zalloc, zfree and opaque must be initialized
    before by the caller.
 
      The windowBits parameter is the base two logarithm of the maximum window
    size (the size of the history buffer).  It should be in the range 8..15 for
-   this version of the library. The default value is 15 if inflateInit is used
-   instead. windowBits must be greater than or equal to the windowBits value
+   this version of the library.  The default value is 15 if inflateInit is used
+   instead.  windowBits must be greater than or equal to the windowBits value
    provided to deflateInit2() while compressing, or it must be equal to 15 if
-   deflateInit2() was not used. If a compressed stream with a larger window
+   deflateInit2() was not used.  If a compressed stream with a larger window
    size is given as input, inflate() will return with the error code
    Z_DATA_ERROR instead of trying to allocate a larger window.
 
-     windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
-   determines the window size. inflate() will then process raw deflate data,
+     windowBits can also be zero to request that inflate use the window size in
+   the zlib header of the compressed stream.
+
+     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits
+   determines the window size.  inflate() will then process raw deflate data,
    not looking for a zlib or gzip header, not generating a check value, and not
-   looking for any check values for comparison at the end of the stream. This
+   looking for any check values for comparison at the end of the stream.  This
    is for use with other formats that use the deflate compressed data format
-   such as zip.  Those formats provide their own check values. If a custom
+   such as zip.  Those formats provide their own check values.  If a custom
    format is developed using the raw deflate format for compressed data, it is
    recommended that a check value such as an adler32 or a crc32 be applied to
    the uncompressed data as is done in the zlib, gzip, and zip formats.  For
-   most applications, the zlib format should be used as is. Note that comments
+   most applications, the zlib format should be used as is.  Note that comments
    above on the use in deflateInit2() applies to the magnitude of windowBits.
 
-     windowBits can also be greater than 15 for optional gzip decoding. Add
+     windowBits can also be greater than 15 for optional gzip decoding.  Add
    32 to windowBits to enable zlib and gzip decoding with automatic header
    detection, or add 16 to decode only the gzip format (the zlib format will
-   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is
-   a crc32 instead of an adler32.
+   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a
+   crc32 instead of an adler32.
 
      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
-   is set to null if there is no error message.  inflateInit2 does not perform
-   any decompression apart from reading the zlib header if present: this will
-   be done by inflate(). (So next_in and avail_in may be modified, but next_out
-   and avail_out are unchanged.)
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit2 does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit2() does not process any header information -- that is
+   deferred until inflate() is called.
 */
 
 ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
@@ -754,36 +821,56 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
                                              uInt  dictLength));
 /*
      Initializes the decompression dictionary from the given uncompressed byte
-   sequence. This function must be called immediately after a call of inflate,
-   if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+   sequence.  This function must be called immediately after a call of inflate,
+   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor
    can be determined from the adler32 value returned by that call of inflate.
    The compressor and decompressor must use exactly the same dictionary (see
-   deflateSetDictionary).  For raw inflate, this function can be called
-   immediately after inflateInit2() or inflateReset() and before any call of
-   inflate() to set the dictionary.  The application must insure that the
-   dictionary that was used for compression is provided.
+   deflateSetDictionary).  For raw inflate, this function can be called at any
+   time to set the dictionary.  If the provided dictionary is smaller than the
+   window and there is already data in the window, then the provided dictionary
+   will amend what's there.  The application must insure that the dictionary
+   that was used for compression is provided.
 
      inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
-   parameter is invalid (such as NULL dictionary) or the stream state is
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
    inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
-   expected one (incorrect adler32 value). inflateSetDictionary does not
+   expected one (incorrect adler32 value).  inflateSetDictionary does not
    perform any decompression: this will be done by subsequent calls of
    inflate().
 */
 
-ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
+                                             Bytef *dictionary,
+                                             uInt  *dictLength));
 /*
-    Skips invalid compressed data until a full flush point (see above the
-  description of deflate with Z_FULL_FLUSH) can be found, or until all
-  available input is skipped. No output is provided.
+     Returns the sliding dictionary being maintained by inflate.  dictLength is
+   set to the number of bytes in the dictionary, and that many bytes are copied
+   to dictionary.  dictionary must have enough space, where 32768 bytes is
+   always enough.  If inflateGetDictionary() is called with dictionary equal to
+   Z_NULL, then only the dictionary length is returned, and nothing is copied.
+   Similary, if dictLength is Z_NULL, then it is not set.
+
+     inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+   stream state is inconsistent.
+*/
 
-    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
-  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
-  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
-  case, the application may save the current current value of total_in which
-  indicates where valid compressed data was found. In the error case, the
-  application may repeatedly call inflateSync, providing more input each time,
-  until success or end of the input data.
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+     Skips invalid compressed data until a possible full flush point (see above
+   for the description of deflate with Z_FULL_FLUSH) can be found, or until all
+   available input is skipped.  No output is provided.
+
+     inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+   All full flush points have this pattern, but not all occurrences of this
+   pattern are full flush points.
+
+     inflateSync returns Z_OK if a possible full flush point has been found,
+   Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+   has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+   In the success case, the application may save the current current value of
+   total_in which indicates where valid compressed data was found.  In the
+   error case, the application may repeatedly call inflateSync, providing more
+   input each time, until success or end of the input data.
 */
 
 ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
@@ -798,18 +885,30 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
 
      inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
    enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
-   (such as zalloc being NULL). msg is left unchanged in both source and
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
    destination.
 */
 
 ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
 /*
      This function is equivalent to inflateEnd followed by inflateInit,
-   but does not free and reallocate all the internal decompression state.
-   The stream will keep attributes that may have been set by inflateInit2.
+   but does not free and reallocate all the internal decompression state.  The
+   stream will keep attributes that may have been set by inflateInit2.
+
+     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
+                                      int windowBits));
+/*
+     This function is the same as inflateReset, but it also permits changing
+   the wrap and window size requests.  The windowBits parameter is interpreted
+   the same as it is for inflateInit2.
 
-      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being NULL).
+     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+   the windowBits parameter is invalid.
 */
 
 ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
@@ -817,54 +916,87 @@ ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
                                      int value));
 /*
      This function inserts bits in the inflate input stream.  The intent is
-  that this function is used to start inflating at a bit position in the
-  middle of a byte.  The provided bits will be used before any bytes are used
-  from next_in.  This function should only be used with raw inflate, and
-  should be used before the first inflate() call after inflateInit2() or
-  inflateReset().  bits must be less than or equal to 16, and that many of the
-  least significant bits of value will be inserted in the input.
-
-      inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   that this function is used to start inflating at a bit position in the
+   middle of a byte.  The provided bits will be used before any bytes are used
+   from next_in.  This function should only be used with raw inflate, and
+   should be used before the first inflate() call after inflateInit2() or
+   inflateReset().  bits must be less than or equal to 16, and that many of the
+   least significant bits of value will be inserted in the input.
+
+     If bits is negative, then the input stream bit buffer is emptied.  Then
+   inflatePrime() can be called again to put bits in the buffer.  This is used
+   to clear out bits leftover after feeding inflate a block description prior
+   to feeding inflate codes.
+
+     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
    stream state was inconsistent.
 */
 
+ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
+/*
+     This function returns two values, one in the lower 16 bits of the return
+   value, and the other in the remaining upper bits, obtained by shifting the
+   return value down 16 bits.  If the upper value is -1 and the lower value is
+   zero, then inflate() is currently decoding information outside of a block.
+   If the upper value is -1 and the lower value is non-zero, then inflate is in
+   the middle of a stored block, with the lower value equaling the number of
+   bytes from the input remaining to copy.  If the upper value is not -1, then
+   it is the number of bits back from the current bit position in the input of
+   the code (literal or length/distance pair) currently being processed.  In
+   that case the lower value is the number of bytes already emitted for that
+   code.
+
+     A code is being processed if inflate is waiting for more input to complete
+   decoding of the code, or if it has completed decoding but is waiting for
+   more output space to write the literal or match data.
+
+     inflateMark() is used to mark locations in the input data for random
+   access, which may be at bit positions, and to note those cases where the
+   output of a code may span boundaries of random access blocks.  The current
+   location in the input stream can be determined from avail_in and data_type
+   as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+     inflateMark returns the value noted above or -1 << 16 if the provided
+   source stream state was inconsistent.
+*/
+
 ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
                                          gz_headerp head));
 /*
-      inflateGetHeader() requests that gzip header information be stored in the
+     inflateGetHeader() requests that gzip header information be stored in the
    provided gz_header structure.  inflateGetHeader() may be called after
    inflateInit2() or inflateReset(), and before the first call of inflate().
    As inflate() processes the gzip stream, head->done is zero until the header
    is completed, at which time head->done is set to one.  If a zlib stream is
    being decoded, then head->done is set to -1 to indicate that there will be
-   no gzip header information forthcoming.  Note that Z_BLOCK can be used to
-   force inflate() to return immediately after header processing is complete
-   and before any actual data is decompressed.
+   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be
+   used to force inflate() to return immediately after header processing is
+   complete and before any actual data is decompressed.
 
-      The text, time, xflags, and os fields are filled in with the gzip header
+     The text, time, xflags, and os fields are filled in with the gzip header
    contents.  hcrc is set to true if there is a header CRC.  (The header CRC
-   was valid if done is set to one.)  If extra is not Z_NULL, then extra_max
+   was valid if done is set to one.) If extra is not Z_NULL, then extra_max
    contains the maximum number of bytes to write to extra.  Once done is true,
    extra_len contains the actual extra field length, and extra contains the
    extra field, or that field truncated if extra_max is less than extra_len.
    If name is not Z_NULL, then up to name_max characters are written there,
    terminated with a zero unless the length is greater than name_max.  If
    comment is not Z_NULL, then up to comm_max characters are written there,
-   terminated with a zero unless the length is greater than comm_max.  When
-   any of extra, name, or comment are not Z_NULL and the respective field is
-   not present in the header, then that field is set to Z_NULL to signal its
+   terminated with a zero unless the length is greater than comm_max.  When any
+   of extra, name, or comment are not Z_NULL and the respective field is not
+   present in the header, then that field is set to Z_NULL to signal its
    absence.  This allows the use of deflateSetHeader() with the returned
    structure to duplicate the header.  However if those fields are set to
    allocated memory, then the application will need to save those pointers
    elsewhere so that they can be eventually freed.
 
-      If inflateGetHeader is not used, then the header information is simply
+     If inflateGetHeader is not used, then the header information is simply
    discarded.  The header is always checked for validity, including the header
    CRC if present.  inflateReset() will reset the process to discard the header
    information.  The application would need to call inflateGetHeader() again to
    retrieve the header from the next gzip stream.
 
-      inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
    stream state was inconsistent.
 */
 
@@ -885,12 +1017,13 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
      See inflateBack() for the usage of these routines.
 
      inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
-   the parameters are invalid, Z_MEM_ERROR if the internal state could not
-   be allocated, or Z_VERSION_ERROR if the version of the library does not
-   match the version of the header file.
+   the parameters are invalid, Z_MEM_ERROR if the internal state could not be
+   allocated, or Z_VERSION_ERROR if the version of the library does not match
+   the version of the header file.
 */
 
-typedef unsigned (*in_func) OF((void FAR *, unsigned const char FAR * FAR *));
+typedef unsigned (*in_func) OF((void FAR *,
+                                z_const unsigned char FAR * FAR *));
 typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
 
 ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
@@ -898,24 +1031,25 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
                                     out_func out, void FAR *out_desc));
 /*
      inflateBack() does a raw inflate with a single call using a call-back
-   interface for input and output.  This is more efficient than inflate() for
-   file i/o applications in that it avoids copying between the output and the
-   sliding window by simply making the window itself the output buffer.  This
-   function trusts the application to not change the output buffer passed by
-   the output function, at least until inflateBack() returns.
+   interface for input and output.  This is potentially more efficient than
+   inflate() for file i/o applications, in that it avoids copying between the
+   output and the sliding window by simply making the window itself the output
+   buffer.  inflate() can be faster on modern CPUs when used with large
+   buffers.  inflateBack() trusts the application to not change the output
+   buffer passed by the output function, at least until inflateBack() returns.
 
      inflateBackInit() must be called first to allocate the internal state
    and to initialize the state with the user-provided window buffer.
    inflateBack() may then be used multiple times to inflate a complete, raw
-   deflate stream with each call.  inflateBackEnd() is then called to free
-   the allocated state.
+   deflate stream with each call.  inflateBackEnd() is then called to free the
+   allocated state.
 
      A raw deflate stream is one with no zlib or gzip header or trailer.
    This routine would normally be used in a utility that reads zip or gzip
    files and writes out uncompressed files.  The utility would decode the
-   header and process the trailer on its own, hence this routine expects
-   only the raw deflate stream to decompress.  This is different from the
-   normal behavior of inflate(), which expects either a zlib or gzip header and
+   header and process the trailer on its own, hence this routine expects only
+   the raw deflate stream to decompress.  This is different from the normal
+   behavior of inflate(), which expects either a zlib or gzip header and
    trailer around the deflate stream.
 
      inflateBack() uses two subroutines supplied by the caller that are then
@@ -941,7 +1075,7 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
    calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
    immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
    must also be initialized, and then if strm->avail_in is not zero, input will
-   initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].
 
      The in_desc and out_desc parameters of inflateBack() is passed as the
    first parameter of in() and out() respectively when they are called.  These
@@ -951,15 +1085,15 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
      On return, inflateBack() will set strm->next_in and strm->avail_in to
    pass back any unused input that was provided by the last in() call.  The
    return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
-   if in() or out() returned an error, Z_DATA_ERROR if there was a format
-   error in the deflate stream (in which case strm->msg is set to indicate the
-   nature of the error), or Z_STREAM_ERROR if the stream was not properly
-   initialized.  In the case of Z_BUF_ERROR, an input or output error can be
-   distinguished using strm->next_in which will be Z_NULL only if in() returned
-   an error.  If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
-   out() returning non-zero.  (in() will always be called before out(), so
-   strm->next_in is assured to be defined if out() returns non-zero.)  Note
-   that inflateBack() cannot return Z_OK.
+   if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+   in the deflate stream (in which case strm->msg is set to indicate the nature
+   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+   In the case of Z_BUF_ERROR, an input or output error can be distinguished
+   using strm->next_in which will be Z_NULL only if in() returned an error.  If
+   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+   non-zero.  (in() will always be called before out(), so strm->next_in is
+   assured to be defined if out() returns non-zero.) Note that inflateBack()
+   cannot return Z_OK.
 */
 
 ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
@@ -1011,27 +1145,27 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
      27-31: 0 (reserved)
  */
 
+#ifndef Z_SOLO
 
                         /* utility functions */
 
 /*
-     The following utility functions are implemented on top of the
-   basic stream-oriented functions. To simplify the interface, some
-   default options are assumed (compression level and memory usage,
-   standard memory allocation functions). The source code of these
-   utility functions can easily be modified if you need special options.
+     The following utility functions are implemented on top of the basic
+   stream-oriented functions.  To simplify the interface, some default options
+   are assumed (compression level and memory usage, standard memory allocation
+   functions).  The source code of these utility functions can be modified if
+   you need special options.
 */
 
 ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
                                  const Bytef *source, uLong sourceLen));
 /*
      Compresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer. Upon entry, destLen is the total
-   size of the destination buffer, which must be at least the value returned
-   by compressBound(sourceLen). Upon exit, destLen is the actual size of the
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
    compressed buffer.
-     This function can be used to compress a whole file at once if the
-   input file is mmap'ed.
+
      compress returns Z_OK if success, Z_MEM_ERROR if there was not
    enough memory, Z_BUF_ERROR if there was not enough room in the output
    buffer.
@@ -1041,11 +1175,11 @@ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
                                   const Bytef *source, uLong sourceLen,
                                   int level));
 /*
-     Compresses the source buffer into the destination buffer. The level
+     Compresses the source buffer into the destination buffer.  The level
    parameter has the same meaning as in deflateInit.  sourceLen is the byte
-   length of the source buffer. Upon entry, destLen is the total size of the
+   length of the source buffer.  Upon entry, destLen is the total size of the
    destination buffer, which must be at least the value returned by
-   compressBound(sourceLen). Upon exit, destLen is the actual size of the
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
    compressed buffer.
 
      compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
@@ -1056,160 +1190,255 @@ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
 ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
 /*
      compressBound() returns an upper bound on the compressed size after
-   compress() or compress2() on sourceLen bytes.  It would be used before
-   a compress() or compress2() call to allocate the destination buffer.
+   compress() or compress2() on sourceLen bytes.  It would be used before a
+   compress() or compress2() call to allocate the destination buffer.
 */
 
 ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
                                    const Bytef *source, uLong sourceLen));
 /*
      Decompresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer. Upon entry, destLen is the total
-   size of the destination buffer, which must be large enough to hold the
-   entire uncompressed data. (The size of the uncompressed data must have
-   been saved previously by the compressor and transmitted to the decompressor
-   by some mechanism outside the scope of this compression library.)
-   Upon exit, destLen is the actual size of the compressed buffer.
-     This function can be used to decompress a whole file at once if the
-   input file is mmap'ed.
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be large enough to hold the entire
+   uncompressed data.  (The size of the uncompressed data must have been saved
+   previously by the compressor and transmitted to the decompressor by some
+   mechanism outside the scope of this compression library.) Upon exit, destLen
+   is the actual size of the uncompressed buffer.
 
      uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
    enough memory, Z_BUF_ERROR if there was not enough room in the output
-   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.  In
+   the case where there is not enough room, uncompress() will fill the output
+   buffer with the uncompressed data up to that point.
 */
 
+                        /* gzip file access functions */
+
+/*
+     This library supports reading and writing files in gzip (.gz) format with
+   an interface similar to that of stdio, using the functions that start with
+   "gz".  The gzip format is different from the zlib format.  gzip is a gzip
+   wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
 
-typedef voidp gzFile;
+typedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */
 
-ZEXTERN gzFile ZEXPORT gzopen  OF((const char *path, const char *mode));
 /*
-     Opens a gzip (.gz) file for reading or writing. The mode parameter
-   is as in fopen ("rb" or "wb") but can also include a compression level
-   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
-   Huffman only compression as in "wb1h", or 'R' for run-length encoding
-   as in "wb1R". (See the description of deflateInit2 for more information
-   about the strategy parameter.)
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+
+     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as
+   in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
+   a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
+   compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
+   for fixed code compression as in "wb9F".  (See the description of
+   deflateInit2 for more information about the strategy parameter.)  'T' will
+   request transparent writing or appending with no compression and not using
+   the gzip format.
+
+     "a" can be used instead of "w" to request that the gzip stream that will
+   be written be appended to the file.  "+" will result in an error, since
+   reading and writing to the same gzip file is not supported.  The addition of
+   "x" when writing will create the file exclusively, which fails if the file
+   already exists.  On systems that support it, the addition of "e" when
+   reading or writing will set the flag to close the file on an execve() call.
+
+     These functions, as well as gzip, will read and decode a sequence of gzip
+   streams in a file.  The append function of gzopen() can be used to create
+   such a file.  (Also see gzflush() for another way to do this.)  When
+   appending, gzopen does not test whether the file begins with a gzip stream,
+   nor does it look for the end of the gzip streams to begin appending.  gzopen
+   will simply append a gzip stream to the existing file.
 
      gzopen can be used to read a file which is not in gzip format; in this
-   case gzread will directly read from the file without decompression.
+   case gzread will directly read from the file without decompression.  When
+   reading, this will be detected automatically by looking for the magic two-
+   byte gzip header.
+
+     gzopen returns NULL if the file could not be opened, if there was
+   insufficient memory to allocate the gzFile state, or if an invalid mode was
+   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+   errno can be checked to determine if the reason gzopen failed was that the
+   file could not be opened.
+*/
 
-     gzopen returns NULL if the file could not be opened or if there was
-   insufficient memory to allocate the (de)compression state; errno
-   can be checked to distinguish the two cases (if errno is zero, the
-   zlib error is Z_MEM_ERROR).  */
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+     gzdopen associates a gzFile with the file descriptor fd.  File descriptors
+   are obtained from calls like open, dup, creat, pipe or fileno (if the file
+   has been previously opened with fopen).  The mode parameter is as in gzopen.
+
+     The next call of gzclose on the returned gzFile will also close the file
+   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+   mode);.  The duplicated descriptor should be saved to avoid a leak, since
+   gzdopen does not close fd if it fails.  If you are using fileno() to get the
+   file descriptor from a FILE *, then you will have to use dup() to avoid
+   double-close()ing the file descriptor.  Both gzclose() and fclose() will
+   close the associated file descriptor, so they need to have different file
+   descriptors.
+
+     gzdopen returns NULL if there was insufficient memory to allocate the
+   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+   provided, or '+' was provided), or if fd is -1.  The file descriptor is not
+   used until the next gz* read, write, seek, or close operation, so gzdopen
+   will not detect if fd is invalid (unless fd is -1).
+*/
 
-ZEXTERN gzFile ZEXPORT gzdopen  OF((int fd, const char *mode));
+ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
 /*
-     gzdopen() associates a gzFile with the file descriptor fd.  File
-   descriptors are obtained from calls like open, dup, creat, pipe or
-   fileno (in the file has been previously opened with fopen).
-   The mode parameter is as in gzopen.
-     The next call of gzclose on the returned gzFile will also close the
-   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
-   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
-     gzdopen returns NULL if there was insufficient memory to allocate
-   the (de)compression state.
+     Set the internal buffer size used by this library's functions.  The
+   default buffer size is 8192 bytes.  This function must be called after
+   gzopen() or gzdopen(), and before any other calls that read or write the
+   file.  The buffer memory allocation is always deferred to the first read or
+   write.  Two buffers are allocated, either both of the specified size when
+   writing, or one of the specified size and the other twice that size when
+   reading.  A larger buffer size of, for example, 64K or 128K bytes will
+   noticeably increase the speed of decompression (reading).
+
+     The new buffer size also affects the maximum length for gzprintf().
+
+     gzbuffer() returns 0 on success, or -1 on failure, such as being called
+   too late.
 */
 
 ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
 /*
-     Dynamically update the compression level or strategy. See the description
+     Dynamically update the compression level or strategy.  See the description
    of deflateInit2 for the meaning of these parameters.
+
      gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
    opened for writing.
 */
 
-ZEXTERN int ZEXPORT    gzread  OF((gzFile file, voidp buf, unsigned len));
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
 /*
-     Reads the given number of uncompressed bytes from the compressed file.
-   If the input file was not in gzip format, gzread copies the given number
-   of bytes into the buffer.
-     gzread returns the number of uncompressed bytes actually read (0 for
-   end of file, -1 for error). */
+     Reads the given number of uncompressed bytes from the compressed file.  If
+   the input file is not in gzip format, gzread copies the given number of
+   bytes into the buffer directly from the file.
+
+     After reaching the end of a gzip stream in the input, gzread will continue
+   to read, looking for another gzip stream.  Any number of gzip streams may be
+   concatenated in the input file, and will all be decompressed by gzread().
+   If something other than a gzip stream is encountered after a gzip stream,
+   that remaining trailing garbage is ignored (and no error is returned).
+
+     gzread can be used to read a gzip file that is being concurrently written.
+   Upon reaching the end of the input, gzread will return with the available
+   data.  If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+   gzclearerr can be used to clear the end of file indicator in order to permit
+   gzread to be tried again.  Z_OK indicates that a gzip stream was completed
+   on the last gzread.  Z_BUF_ERROR indicates that the input file ended in the
+   middle of a gzip stream.  Note that gzread does not return -1 in the event
+   of an incomplete gzip stream.  This error is deferred until gzclose(), which
+   will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+   stream.  Alternatively, gzerror can be used before gzclose to detect this
+   case.
+
+     gzread returns the number of uncompressed bytes actually read, less than
+   len for end of file, or -1 for error.
+*/
 
-ZEXTERN int ZEXPORT    gzwrite OF((gzFile file,
-                                   voidpc buf, unsigned len));
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+                                voidpc buf, unsigned len));
 /*
      Writes the given number of uncompressed bytes into the compressed file.
-   gzwrite returns the number of uncompressed bytes actually written
-   (0 in case of error).
+   gzwrite returns the number of uncompressed bytes written or 0 in case of
+   error.
 */
 
-ZEXTERN int ZEXPORTVA   gzprintf OF((gzFile file, const char *format, ...))
-				    _Z_PRINTF_ATTRIBUTE(2, 3);
+ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
 /*
-     Converts, formats, and writes the args to the compressed file under
-   control of the format string, as in fprintf. gzprintf returns the number of
-   uncompressed bytes actually written (0 in case of error).  The number of
-   uncompressed bytes written is limited to 4095. The caller should assure that
-   this limit is not exceeded. If it is exceeded, then gzprintf() will return
-   return an error (0) with nothing written. In this case, there may also be a
-   buffer overflow with unpredictable consequences, which is possible only if
-   zlib was compiled with the insecure functions sprintf() or vsprintf()
-   because the secure snprintf() or vsnprintf() functions were not available.
+     Converts, formats, and writes the arguments to the compressed file under
+   control of the format string, as in fprintf.  gzprintf returns the number of
+   uncompressed bytes actually written, or 0 in case of error.  The number of
+   uncompressed bytes written is limited to 8191, or one less than the buffer
+   size given to gzbuffer().  The caller should assure that this limit is not
+   exceeded.  If it is exceeded, then gzprintf() will return an error (0) with
+   nothing written.  In this case, there may also be a buffer overflow with
+   unpredictable consequences, which is possible only if zlib was compiled with
+   the insecure functions sprintf() or vsprintf() because the secure snprintf()
+   or vsnprintf() functions were not available.  This can be determined using
+   zlibCompileFlags().
 */
 
 ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
 /*
-      Writes the given null-terminated string to the compressed file, excluding
+     Writes the given null-terminated string to the compressed file, excluding
    the terminating null character.
-      gzputs returns the number of characters written, or -1 in case of error.
+
+     gzputs returns the number of characters written, or -1 in case of error.
 */
 
 ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
 /*
-      Reads bytes from the compressed file until len-1 characters are read, or
-   a newline character is read and transferred to buf, or an end-of-file
-   condition is encountered.  The string is then terminated with a null
-   character.
-      gzgets returns buf, or Z_NULL in case of error.
+     Reads bytes from the compressed file until len-1 characters are read, or a
+   newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  If any characters are read or if len == 1, the
+   string is terminated with a null character.  If no characters are read due
+   to an end-of-file or len < 1, then the buffer is left untouched.
+
+     gzgets returns buf which is a null-terminated string, or it returns NULL
+   for end-of-file or in case of error.  If there was an error, the contents at
+   buf are indeterminate.
 */
 
-ZEXTERN int ZEXPORT    gzputc OF((gzFile file, int c));
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
 /*
-      Writes c, converted to an unsigned char, into the compressed file.
-   gzputc returns the value that was written, or -1 in case of error.
+     Writes c, converted to an unsigned char, into the compressed file.  gzputc
+   returns the value that was written, or -1 in case of error.
 */
 
-ZEXTERN int ZEXPORT    gzgetc OF((gzFile file));
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
 /*
-      Reads one byte from the compressed file. gzgetc returns this byte
-   or -1 in case of end of file or error.
+     Reads one byte from the compressed file.  gzgetc returns this byte or -1
+   in case of end of file or error.  This is implemented as a macro for speed.
+   As such, it does not do all of the checking the other functions do.  I.e.
+   it does not check to see if file is NULL, nor whether the structure file
+   points to has been clobbered or not.
 */
 
-ZEXTERN int ZEXPORT    gzungetc OF((int c, gzFile file));
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
 /*
-      Push one character back onto the stream to be read again later.
-   Only one character of push-back is allowed.  gzungetc() returns the
-   character pushed, or -1 on failure.  gzungetc() will fail if a
-   character has been pushed but not read yet, or if c is -1. The pushed
-   character will be discarded if the stream is repositioned with gzseek()
-   or gzrewind().
+     Push one character back onto the stream to be read as the first character
+   on the next read.  At least one character of push-back is allowed.
+   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will
+   fail if c is -1, and may fail if a character has been pushed but not read
+   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the
+   output buffer size of pushed characters is allowed.  (See gzbuffer above.)
+   The pushed character will be discarded if the stream is repositioned with
+   gzseek() or gzrewind().
 */
 
-ZEXTERN int ZEXPORT    gzflush OF((gzFile file, int flush));
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
 /*
-     Flushes all pending output into the compressed file. The parameter
-   flush is as in the deflate() function. The return value is the zlib
-   error number (see function gzerror below). gzflush returns Z_OK if
-   the flush parameter is Z_FINISH and all output could be flushed.
-     gzflush should be called only when strictly necessary because it can
-   degrade compression.
+     Flushes all pending output into the compressed file.  The parameter flush
+   is as in the deflate() function.  The return value is the zlib error number
+   (see function gzerror below).  gzflush is only permitted when writing.
+
+     If the flush parameter is Z_FINISH, the remaining data is written and the
+   gzip stream is completed in the output.  If gzwrite() is called again, a new
+   gzip stream will be started in the output.  gzread() is able to read such
+   concatented gzip streams.
+
+     gzflush should be called only when strictly necessary because it will
+   degrade compression if called too often.
 */
 
-ZEXTERN z_off_t ZEXPORT    gzseek OF((gzFile file,
-                                      z_off_t offset, int whence));
 /*
-      Sets the starting position for the next gzread or gzwrite on the
-   given compressed file. The offset represents a number of bytes in the
-   uncompressed data stream. The whence parameter is defined as in lseek(2);
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+                                   z_off_t offset, int whence));
+
+     Sets the starting position for the next gzread or gzwrite on the given
+   compressed file.  The offset represents a number of bytes in the
+   uncompressed data stream.  The whence parameter is defined as in lseek(2);
    the value SEEK_END is not supported.
+
      If the file is opened for reading, this function is emulated but can be
-   extremely slow. If the file is opened for writing, only forward seeks are
+   extremely slow.  If the file is opened for writing, only forward seeks are
    supported; gzseek then compresses a sequence of zeroes up to the new
    starting position.
 
-      gzseek returns the resulting offset location as measured in bytes from
+     gzseek returns the resulting offset location as measured in bytes from
    the beginning of the uncompressed stream, or -1 in case of error, in
    particular if the file is opened for writing and the new starting position
    would be before the current position.
@@ -1219,68 +1448,134 @@ ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
 /*
      Rewinds the given file. This function is supported only for reading.
 
-   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
 */
 
+/*
 ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+
+     Returns the starting position for the next gzread or gzwrite on the given
+   compressed file.  This position represents a number of bytes in the
+   uncompressed data stream, and is zero when starting, even if appending or
+   reading a gzip stream from the middle of a file using gzdopen().
+
+     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
 /*
-     Returns the starting position for the next gzread or gzwrite on the
-   given compressed file. This position represents a number of bytes in the
-   uncompressed data stream.
+ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
 
-   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+     Returns the current offset in the file being read or written.  This offset
+   includes the count of bytes that precede the gzip stream, for example when
+   appending or when using gzdopen() for reading.  When reading, the offset
+   does not include as yet unused buffered input.  This information can be used
+   for a progress indicator.  On error, gzoffset() returns -1.
 */
 
 ZEXTERN int ZEXPORT gzeof OF((gzFile file));
 /*
-     Returns 1 when EOF has previously been detected reading the given
-   input stream, otherwise zero.
+     Returns true (1) if the end-of-file indicator has been set while reading,
+   false (0) otherwise.  Note that the end-of-file indicator is set only if the
+   read tried to go past the end of the input, but came up short.  Therefore,
+   just like feof(), gzeof() may return false even if there is no more data to
+   read, in the event that the last read request was for the exact number of
+   bytes remaining in the input file.  This will happen if the input file size
+   is an exact multiple of the buffer size.
+
+     If gzeof() returns true, then the read functions will return no more data,
+   unless the end-of-file indicator is reset by gzclearerr() and the input file
+   has grown since the previous end of file was detected.
 */
 
 ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
 /*
-     Returns 1 if file is being read directly without decompression, otherwise
-   zero.
+     Returns true (1) if file is being copied directly while reading, or false
+   (0) if file is a gzip stream being decompressed.
+
+     If the input file is empty, gzdirect() will return true, since the input
+   does not contain a gzip stream.
+
+     If gzdirect() is used immediately after gzopen() or gzdopen() it will
+   cause buffers to be allocated to allow reading the file to determine if it
+   is a gzip file.  Therefore if gzbuffer() is used, it should be called before
+   gzdirect().
+
+     When writing, gzdirect() returns true (1) if transparent writing was
+   requested ("wT" for the gzopen() mode), or false (0) otherwise.  (Note:
+   gzdirect() is not needed when writing.  Transparent writing must be
+   explicitly requested, so the application already knows the answer.  When
+   linking statically, using gzdirect() will include all of the zlib code for
+   gzip file reading and decompression, which may not be desired.)
 */
 
 ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
 /*
-     Flushes all pending output if necessary, closes the compressed file
-   and deallocates all the (de)compression state. The return value is the zlib
-   error number (see function gzerror below).
+     Flushes all pending output if necessary, closes the compressed file and
+   deallocates the (de)compression state.  Note that once file is closed, you
+   cannot call gzerror with file, since its structures have been deallocated.
+   gzclose must not be called more than once on the same file, just as free
+   must not be called more than once on the same allocation.
+
+     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+   file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+   last read ended in the middle of a gzip stream, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
+ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
+/*
+     Same as gzclose(), but gzclose_r() is only for use when reading, and
+   gzclose_w() is only for use when writing or appending.  The advantage to
+   using these instead of gzclose() is that they avoid linking in zlib
+   compression or decompression code that is not used when only reading or only
+   writing respectively.  If gzclose() is used, then both compression and
+   decompression code will be included the application when linking to a static
+   zlib library.
 */
 
 ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
 /*
-     Returns the error message for the last error which occurred on the
-   given compressed file. errnum is set to zlib error number. If an
-   error occurred in the file system and not in the compression library,
-   errnum is set to Z_ERRNO and the application may consult errno
-   to get the exact error code.
+     Returns the error message for the last error which occurred on the given
+   compressed file.  errnum is set to zlib error number.  If an error occurred
+   in the file system and not in the compression library, errnum is set to
+   Z_ERRNO and the application may consult errno to get the exact error code.
+
+     The application must not modify the returned string.  Future calls to
+   this function may invalidate the previously returned string.  If file is
+   closed, then the string previously returned by gzerror will no longer be
+   available.
+
+     gzerror() should be used to distinguish errors from end-of-file for those
+   functions above that do not distinguish those cases in their return values.
 */
 
 ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
 /*
-     Clears the error and end-of-file flags for file. This is analogous to the
-   clearerr() function in stdio. This is useful for continuing to read a gzip
+     Clears the error and end-of-file flags for file.  This is analogous to the
+   clearerr() function in stdio.  This is useful for continuing to read a gzip
    file that is being written concurrently.
 */
 
+#endif /* !Z_SOLO */
+
                         /* checksum functions */
 
 /*
      These functions are not related to compression but are exported
-   anyway because they might be useful in applications using the
-   compression library.
+   anyway because they might be useful in applications using the compression
+   library.
 */
 
 ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
 /*
      Update a running Adler-32 checksum with the bytes buf[0..len-1] and
-   return the updated checksum. If buf is NULL, this function returns
-   the required initial value for the checksum.
-   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
-   much faster. Usage example:
+   return the updated checksum.  If buf is Z_NULL, this function returns the
+   required initial value for the checksum.
+
+     An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster.
+
+   Usage example:
 
      uLong adler = adler32(0L, Z_NULL, 0);
 
@@ -1290,21 +1585,25 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
      if (adler != original_adler) error();
 */
 
+/*
 ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
                                           z_off_t len2));
-/*
+
      Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
    and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
    each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
-   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.  Note
+   that the z_off_t type (like off_t) is a signed integer.  If len2 is
+   negative, the result has no meaning or utility.
 */
 
 ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
 /*
      Update a running CRC-32 with the bytes buf[0..len-1] and return the
-   updated CRC-32. If buf is NULL, this function returns the required initial
-   value for the for the crc. Pre- and post-conditioning (one's complement) is
+   updated CRC-32.  If buf is Z_NULL, this function returns the required
+   initial value for the crc.  Pre- and post-conditioning (one's complement) is
    performed within this function so it shouldn't be done by the application.
+
    Usage example:
 
      uLong crc = crc32(0L, Z_NULL, 0);
@@ -1315,9 +1614,9 @@ ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
      if (crc != original_crc) error();
 */
 
+/*
 ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
 
-/*
      Combine two CRC-32 check values into one.  For two sequences of bytes,
    seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
    calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
@@ -1346,26 +1645,121 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
                                          const char *version,
                                          int stream_size));
 #define deflateInit(strm, level) \
-        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
+        deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
 #define inflateInit(strm) \
-        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
+        inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
 #define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
         deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
-                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
+                      (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
 #define inflateInit2(strm, windowBits) \
-        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+                      (int)sizeof(z_stream))
 #define inflateBackInit(strm, windowBits, window) \
         inflateBackInit_((strm), (windowBits), (window), \
-        ZLIB_VERSION, sizeof(z_stream))
+                      ZLIB_VERSION, (int)sizeof(z_stream))
+
+#ifndef Z_SOLO
 
+/* gzgetc() macro and its supporting function and exposed data structure.  Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro.  The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously.  They can
+ * only be used by the gzgetc() macro.  You have been warned.
+ */
+struct gzFile_s {
+    unsigned have;
+    unsigned char *next;
+    z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
+#ifdef Z_PREFIX_SET
+#  undef z_gzgetc
+#  define z_gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#else
+#  define gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#endif
 
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#ifdef Z_LARGE64
+   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
+   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+#endif
+
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+#  ifdef Z_PREFIX_SET
+#    define z_gzopen z_gzopen64
+#    define z_gzseek z_gzseek64
+#    define z_gztell z_gztell64
+#    define z_gzoffset z_gzoffset64
+#    define z_adler32_combine z_adler32_combine64
+#    define z_crc32_combine z_crc32_combine64
+#  else
+#    define gzopen gzopen64
+#    define gzseek gzseek64
+#    define gztell gztell64
+#    define gzoffset gzoffset64
+#    define adler32_combine adler32_combine64
+#    define crc32_combine crc32_combine64
+#  endif
+#  ifndef Z_LARGE64
+     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
+     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
+     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
+     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#  endif
+#else
+   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
+   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
+   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
+   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+#endif
+
+#else /* Z_SOLO */
+
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+
+#endif /* !Z_SOLO */
+
+/* hack for buggy compilers */
 #if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
-    struct internal_state {int dummy;}; /* hack for buggy compilers */
+    struct internal_state {int dummy;};
 #endif
 
+/* undocumented functions */
 ZEXTERN const char   * ZEXPORT zError           OF((int));
-ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp z));
-ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));
+ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
+ZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));
+ZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));
+#if defined(_WIN32) && !defined(Z_SOLO)
+ZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,
+                                            const char *mode));
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifndef Z_SOLO
+ZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,
+                                                  const char *format,
+                                                  va_list va));
+#  endif
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/third_party/zlib/zutil.c b/third_party/zlib/zutil.c
index d55f594..23d2ebe 100644
--- a/third_party/zlib/zutil.c
+++ b/third_party/zlib/zutil.c
@@ -1,17 +1,20 @@
 /* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 /* @(#) $Id$ */
 
 #include "zutil.h"
+#ifndef Z_SOLO
+#  include "gzguts.h"
+#endif
 
 #ifndef NO_DUMMY_DECL
 struct internal_state      {int dummy;}; /* for buggy compilers */
 #endif
 
-const char * const z_errmsg[10] = {
+z_const char * const z_errmsg[10] = {
 "need dictionary",     /* Z_NEED_DICT       2  */
 "stream end",          /* Z_STREAM_END      1  */
 "",                    /* Z_OK              0  */
@@ -34,25 +37,25 @@ uLong ZEXPORT zlibCompileFlags()
     uLong flags;
 
     flags = 0;
-    switch (sizeof(uInt)) {
+    switch ((int)(sizeof(uInt))) {
     case 2:     break;
     case 4:     flags += 1;     break;
     case 8:     flags += 2;     break;
     default:    flags += 3;
     }
-    switch (sizeof(uLong)) {
+    switch ((int)(sizeof(uLong))) {
     case 2:     break;
     case 4:     flags += 1 << 2;        break;
     case 8:     flags += 2 << 2;        break;
     default:    flags += 3 << 2;
     }
-    switch (sizeof(voidpf)) {
+    switch ((int)(sizeof(voidpf))) {
     case 2:     break;
     case 4:     flags += 1 << 4;        break;
     case 8:     flags += 2 << 4;        break;
     default:    flags += 3 << 4;
     }
-    switch (sizeof(z_off_t)) {
+    switch ((int)(sizeof(z_off_t))) {
     case 2:     break;
     case 4:     flags += 1 << 6;        break;
     case 8:     flags += 2 << 6;        break;
@@ -85,27 +88,27 @@ uLong ZEXPORT zlibCompileFlags()
 #ifdef FASTEST
     flags += 1L << 21;
 #endif
-#ifdef STDC
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
 #  ifdef NO_vsnprintf
-        flags += 1L << 25;
+    flags += 1L << 25;
 #    ifdef HAS_vsprintf_void
-        flags += 1L << 26;
+    flags += 1L << 26;
 #    endif
 #  else
 #    ifdef HAS_vsnprintf_void
-        flags += 1L << 26;
+    flags += 1L << 26;
 #    endif
 #  endif
 #else
-        flags += 1L << 24;
+    flags += 1L << 24;
 #  ifdef NO_snprintf
-        flags += 1L << 25;
+    flags += 1L << 25;
 #    ifdef HAS_sprintf_void
-        flags += 1L << 26;
+    flags += 1L << 26;
 #    endif
 #  else
 #    ifdef HAS_snprintf_void
-        flags += 1L << 26;
+    flags += 1L << 26;
 #    endif
 #  endif
 #endif
@@ -117,9 +120,9 @@ uLong ZEXPORT zlibCompileFlags()
 #  ifndef verbose
 #    define verbose 0
 #  endif
-int z_verbose = verbose;
+int ZLIB_INTERNAL z_verbose = verbose;
 
-void z_error (m)
+void ZLIB_INTERNAL z_error (m)
     char *m;
 {
     fprintf(stderr, "%s\n", m);
@@ -146,7 +149,7 @@ const char * ZEXPORT zError(err)
 
 #ifndef HAVE_MEMCPY
 
-void zmemcpy(dest, source, len)
+void ZLIB_INTERNAL zmemcpy(dest, source, len)
     Bytef* dest;
     const Bytef* source;
     uInt  len;
@@ -157,7 +160,7 @@ void zmemcpy(dest, source, len)
     } while (--len != 0);
 }
 
-int zmemcmp(s1, s2, len)
+int ZLIB_INTERNAL zmemcmp(s1, s2, len)
     const Bytef* s1;
     const Bytef* s2;
     uInt  len;
@@ -170,7 +173,7 @@ int zmemcmp(s1, s2, len)
     return 0;
 }
 
-void zmemzero(dest, len)
+void ZLIB_INTERNAL zmemzero(dest, len)
     Bytef* dest;
     uInt  len;
 {
@@ -181,6 +184,7 @@ void zmemzero(dest, len)
 }
 #endif
 
+#ifndef Z_SOLO
 
 #ifdef SYS16BIT
 
@@ -213,7 +217,7 @@ local ptr_table table[MAX_PTR];
  * a protected system like OS/2. Use Microsoft C instead.
  */
 
-voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
 {
     voidpf buf = opaque; /* just to make some compilers happy */
     ulg bsize = (ulg)items*size;
@@ -237,7 +241,7 @@ voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
     return buf;
 }
 
-void  zcfree (voidpf opaque, voidpf ptr)
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
 {
     int n;
     if (*(ush*)&ptr != 0) { /* object < 64K */
@@ -272,13 +276,13 @@ void  zcfree (voidpf opaque, voidpf ptr)
 #  define _hfree   hfree
 #endif
 
-voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
 {
     if (opaque) opaque = 0; /* to make compiler happy */
     return _halloc((long)items, size);
 }
 
-void  zcfree (voidpf opaque, voidpf ptr)
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
 {
     if (opaque) opaque = 0; /* to make compiler happy */
     _hfree(ptr);
@@ -297,7 +301,7 @@ extern voidp  calloc OF((uInt items, uInt size));
 extern void   free   OF((voidpf ptr));
 #endif
 
-voidpf zcalloc (opaque, items, size)
+voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
     voidpf opaque;
     unsigned items;
     unsigned size;
@@ -307,7 +311,7 @@ voidpf zcalloc (opaque, items, size)
                               (voidpf)calloc(items, size);
 }
 
-void  zcfree (opaque, ptr)
+void ZLIB_INTERNAL zcfree (opaque, ptr)
     voidpf opaque;
     voidpf ptr;
 {
@@ -316,3 +320,5 @@ void  zcfree (opaque, ptr)
 }
 
 #endif /* MY_ZCALLOC */
+
+#endif /* !Z_SOLO */
diff --git a/third_party/zlib/zutil.h b/third_party/zlib/zutil.h
index edd8e0a..24ab06b 100644
--- a/third_party/zlib/zutil.h
+++ b/third_party/zlib/zutil.h
@@ -1,5 +1,5 @@
 /* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * Copyright (C) 1995-2013 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -13,30 +13,24 @@
 #ifndef ZUTIL_H
 #define ZUTIL_H
 
-#define ZLIB_INTERNAL
+#ifdef HAVE_HIDDEN
+#  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+#  define ZLIB_INTERNAL
+#endif
+
 #include "zlib.h"
 
-#ifdef STDC
-#  ifndef _WIN32_WCE
+#if defined(STDC) && !defined(Z_SOLO)
+#  if !(defined(_WIN32_WCE) && defined(_MSC_VER))
 #    include <stddef.h>
 #  endif
 #  include <string.h>
 #  include <stdlib.h>
 #endif
-#ifdef NO_ERRNO_H
-#   ifdef _WIN32_WCE
-      /* The Microsoft C Run-Time Library for Windows CE doesn't have
-       * errno.  We define it as a global variable to simplify porting.
-       * Its value is always 0 and should not be used.  We rename it to
-       * avoid conflict with other libraries that use the same workaround.
-       */
-#     define errno z_errno
-#   endif
-    extern int errno;
-#else
-#  ifndef _WIN32_WCE
-#    include <errno.h>
-#  endif
+
+#ifdef Z_SOLO
+   typedef long ptrdiff_t;  /* guess -- will be caught if guess is wrong */
 #endif
 
 #ifndef local
@@ -50,7 +44,7 @@ typedef unsigned short ush;
 typedef ush FAR ushf;
 typedef unsigned long  ulg;
 
-extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 /* (size given to avoid silly warnings with Visual C++) */
 
 #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
@@ -88,16 +82,18 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 
 #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
 #  define OS_CODE  0x00
-#  if defined(__TURBOC__) || defined(__BORLANDC__)
-#    if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
-       /* Allow compilation with ANSI keywords only enabled */
-       void _Cdecl farfree( void *block );
-       void *_Cdecl farmalloc( unsigned long nbytes );
-#    else
-#      include <alloc.h>
+#  ifndef Z_SOLO
+#    if defined(__TURBOC__) || defined(__BORLANDC__)
+#      if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+         /* Allow compilation with ANSI keywords only enabled */
+         void _Cdecl farfree( void *block );
+         void *_Cdecl farmalloc( unsigned long nbytes );
+#      else
+#        include <alloc.h>
+#      endif
+#    else /* MSC or DJGPP */
+#      include <malloc.h>
 #    endif
-#  else /* MSC or DJGPP */
-#    include <malloc.h>
 #  endif
 #endif
 
@@ -117,18 +113,20 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 
 #ifdef OS2
 #  define OS_CODE  0x06
-#  ifdef M_I86
-     #include <malloc.h>
+#  if defined(M_I86) && !defined(Z_SOLO)
+#    include <malloc.h>
 #  endif
 #endif
 
 #if defined(MACOS) || defined(TARGET_OS_MAC)
 #  define OS_CODE  0x07
-#  if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
-#    include <unix.h> /* for fdopen */
-#  else
-#    ifndef fdopen
-#      define fdopen(fd,mode) NULL /* No fdopen() */
+#  ifndef Z_SOLO
+#    if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+#      include <unix.h> /* for fdopen */
+#    else
+#      ifndef fdopen
+#        define fdopen(fd,mode) NULL /* No fdopen() */
+#      endif
 #    endif
 #  endif
 #endif
@@ -151,7 +149,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 #  define fdopen(fd,mode) NULL /* No fdopen() */
 #endif
 
-#if (defined(_MSC_VER) && (_MSC_VER > 600))
+#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
 #  if defined(_WIN32_WCE)
 #    define fdopen(fd,mode) NULL /* No fdopen() */
 #    ifndef _PTRDIFF_T_DEFINED
@@ -163,6 +161,19 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 #  endif
 #endif
 
+#if defined(__BORLANDC__) && !defined(MSDOS)
+  #pragma warn -8004
+  #pragma warn -8008
+  #pragma warn -8066
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_WIN32) && \
+    (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
+    ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+    ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#endif
+
         /* common defaults */
 
 #ifndef OS_CODE
@@ -175,40 +186,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 
          /* functions */
 
-#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
-#  ifndef HAVE_VSNPRINTF
-#    define HAVE_VSNPRINTF
-#  endif
-#endif
-#if defined(__CYGWIN__)
-#  ifndef HAVE_VSNPRINTF
-#    define HAVE_VSNPRINTF
-#  endif
-#endif
-#ifndef HAVE_VSNPRINTF
-#  ifdef MSDOS
-     /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
-        but for now we just assume it doesn't. */
-#    define NO_vsnprintf
-#  endif
-#  ifdef __TURBOC__
-#    define NO_vsnprintf
-#  endif
-#  ifdef WIN32
-     /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
-#    if !defined(vsnprintf) && !defined(NO_vsnprintf)
-#      define vsnprintf _vsnprintf
-#    endif
-#  endif
-#  ifdef __SASC
-#    define NO_vsnprintf
-#  endif
-#endif
-#ifdef VMS
-#  define NO_vsnprintf
-#endif
-
-#if defined(pyr)
+#if defined(pyr) || defined(Z_SOLO)
 #  define NO_MEMCPY
 #endif
 #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
@@ -232,16 +210,16 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 #    define zmemzero(dest, len) memset(dest, 0, len)
 #  endif
 #else
-   extern void zmemcpy  OF((Bytef* dest, const Bytef* source, uInt len));
-   extern int  zmemcmp  OF((const Bytef* s1, const Bytef* s2, uInt len));
-   extern void zmemzero OF((Bytef* dest, uInt len));
+   void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+   int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+   void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
 #endif
 
 /* Diagnostic functions */
 #ifdef DEBUG
 #  include <stdio.h>
-   extern int z_verbose;
-   extern void z_error    OF((char *m));
+   extern int ZLIB_INTERNAL z_verbose;
+   extern void ZLIB_INTERNAL z_error OF((char *m));
 #  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
 #  define Trace(x) {if (z_verbose>=0) fprintf x ;}
 #  define Tracev(x) {if (z_verbose>0) fprintf x ;}
@@ -257,13 +235,19 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 #  define Tracecv(c,x)
 #endif
 
-
-voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
-void   zcfree  OF((voidpf opaque, voidpf ptr));
+#ifndef Z_SOLO
+   voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
+                                    unsigned size));
+   void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));
+#endif
 
 #define ZALLOC(strm, items, size) \
            (*((strm)->zalloc))((strm)->opaque, (items), (size))
 #define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
 #define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
 
+/* Reverse the bytes in a 32-bit value */
+#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+                    (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
 #endif /* ZUTIL_H */
-- 
2.1.4



More information about the samba-technical mailing list