URI: 
       tinitial sources import - mixmaster - mixmaster 3.0 patched for libressl
  HTML git clone git://parazyd.org/mixmaster.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
       ---
   DIR commit 50de79fe7f9e194b5a6bdd3a63fb3bdb455588a8
  HTML Author: parazyd <parazyd@dyne.org>
       Date:   Thu, 15 Sep 2016 01:44:49 +0200
       
       initial sources import
       
       Diffstat:
         A BUILD.Win32                         |      30 ++++++++++++++++++++++++++++++
         A COPYRIGHT                           |     134 +++++++++++++++++++++++++++++++
         A HISTORY                             |     502 +++++++++++++++++++++++++++++++
         A Install                             |    1403 +++++++++++++++++++++++++++++++
         A README                              |     191 +++++++++++++++++++++++++++++++
         A Src/Makefile.deps                   |      46 +++++++++++++++++++++++++++++++
         A Src/Makefile.in                     |      83 +++++++++++++++++++++++++++++++
         A Src/buffers.c                       |     816 +++++++++++++++++++++++++++++++
         A Src/chain.c                         |     384 +++++++++++++++++++++++++++++++
         A Src/chain1.c                        |     301 +++++++++++++++++++++++++++++++
         A Src/chain2.c                        |     685 +++++++++++++++++++++++++++++++
         A Src/compress.c                      |     210 +++++++++++++++++++++++++++++++
         A Src/config.h                        |     403 +++++++++++++++++++++++++++++++
         A Src/crypto.c                        |     492 +++++++++++++++++++++++++++++++
         A Src/crypto.h                        |      48 +++++++++++++++++++++++++++++++
         A Src/dllmain.c                       |      35 +++++++++++++++++++++++++++++++
         A Src/dummy.c                         |      16 ++++++++++++++++
         A Src/keymgt.c                        |     434 +++++++++++++++++++++++++++++++
         A Src/mail.c                          |     898 +++++++++++++++++++++++++++++++
         A Src/maildir.c                       |     323 +++++++++++++++++++++++++++++++
         A Src/main.c                          |     820 ++++++++++++++++++++++++++++++
         A Src/menu.c                          |    1003 +++++++++++++++++++++++++++++++
         A Src/menu.h                          |      48 +++++++++++++++++++++++++++++++
         A Src/menunym.c                       |     472 +++++++++++++++++++++++++++++++
         A Src/menusend.c                      |     556 ++++++++++++++++++++++++++++++
         A Src/menustats.c                     |     445 +++++++++++++++++++++++++++++++
         A Src/menuutil.c                      |     154 +++++++++++++++++++++++++++++++
         A Src/mime.c                          |     814 +++++++++++++++++++++++++++++++
         A Src/mix.c                           |    1262 +++++++++++++++++++++++++++++++
         A Src/mix.h                           |     917 +++++++++++++++++++++++++++++++
         A Src/mix3.h                          |     443 +++++++++++++++++++++++++++++++
         A Src/mixlib.def                      |     121 +++++++++++++++++++++++++++++++
         A Src/mpgp.c                          |     264 +++++++++++++++++++++++++++++++
         A Src/nym.c                           |     669 ++++++++++++++++++++++++++++++
         A Src/parsedate.y                     |     879 +++++++++++++++++++++++++++++++
         A Src/pgp.c                           |     494 +++++++++++++++++++++++++++++++
         A Src/pgp.h                           |     189 +++++++++++++++++++++++++++++++
         A Src/pgpcreat.c                      |     848 ++++++++++++++++++++++++++++++
         A Src/pgpdata.c                       |    1539 +++++++++++++++++++++++++++++++
         A Src/pgpdb.c                         |     583 +++++++++++++++++++++++++++++++
         A Src/pgpget.c                        |     870 +++++++++++++++++++++++++++++++
         A Src/pool.c                          |     981 +++++++++++++++++++++++++++++++
         A Src/random.c                        |     210 +++++++++++++++++++++++++++++++
         A Src/rem.c                           |     709 +++++++++++++++++++++++++++++++
         A Src/rem1.c                          |     599 +++++++++++++++++++++++++++++++
         A Src/rem2.c                          |     486 +++++++++++++++++++++++++++++++
         A Src/remailer.c                      |      36 +++++++++++++++++++++++++++++++
         A Src/rfc822.c                        |     585 +++++++++++++++++++++++++++++++
         A Src/rndseed.c                       |     157 +++++++++++++++++++++++++++++++
         A Src/service.c                       |     331 +++++++++++++++++++++++++++++++
         A Src/stats.c                         |     442 +++++++++++++++++++++++++++++++
         A Src/tests/test-parse_yearmonthday.c |      59 +++++++++++++++++++++++++++++++
         A Src/util.c                          |     704 +++++++++++++++++++++++++++++++
         A Src/version.h                       |       1 +
         A THANKS                              |     102 +++++++++++++++++++++++++++++++
         A TODO                                |      77 +++++++++++++++++++++++++++++++
         A conf/abuse.txt.in                   |      99 +++++++++++++++++++++++++++++++
         A conf/adminkey.txt                   |       1 +
         A conf/blocked.txt.in                 |      20 ++++++++++++++++++++
         A conf/dest.alw                       |      41 +++++++++++++++++++++++++++++++
         A conf/dest.blk                       |       2 ++
         A conf/end.hlp                        |      36 +++++++++++++++++++++++++++++++
         A conf/header.blk                     |      22 ++++++++++++++++++++++
         A conf/intro.hlp                      |      15 +++++++++++++++
         A conf/mix.cfg                        |      14 ++++++++++++++
         A conf/mix.cfg.ex                     |     192 +++++++++++++++++++++++++++++++
         A conf/mix.hlp                        |      45 +++++++++++++++++++++++++++++++
         A conf/mlist.txt                      |      48 +++++++++++++++++++++++++++++++
         A conf/news.hlp                       |      59 +++++++++++++++++++++++++++++++
         A conf/pgp.hlp                        |     143 +++++++++++++++++++++++++++++++
         A conf/pgponly.hlp                    |     144 +++++++++++++++++++++++++++++++
         A conf/pubring.asc                    |     544 +++++++++++++++++++++++++++++++
         A conf/pubring.mix                    |     384 +++++++++++++++++++++++++++++++
         A conf/rab.blk                        |       0 
         A conf/reply.txt.in                   |      32 +++++++++++++++++++++++++++++++
         A conf/rlist.txt                      |      61 +++++++++++++++++++++++++++++++
         A conf/type1.hlp                      |     100 +++++++++++++++++++++++++++++++
         A conf/usage.txt.in                   |      24 ++++++++++++++++++++++++
         A idea.txt                            |      34 +++++++++++++++++++++++++++++++
         A mixmaster.1                         |    1136 +++++++++++++++++++++++++++++++
         A mpgp.1                              |     121 +++++++++++++++++++++++++++++++
         A win32/installer/mixinstall.nsi      |      70 +++++++++++++++++++++++++++++++
         A win32/mix.sln                       |      79 +++++++++++++++++++++++++++++++
         A win32/mix.vcproj                    |     193 +++++++++++++++++++++++++++++++
         A win32/mixlib.vcproj                 |     459 +++++++++++++++++++++++++++++++
         A win32/pcre.vcproj                   |     117 +++++++++++++++++++++++++++++++
         A win32/pcre_chartables.vcproj        |     100 +++++++++++++++++++++++++++++++
         A win32/pdcurses.vcproj               |     607 +++++++++++++++++++++++++++++++
         A win32/zlib.vcproj                   |     217 +++++++++++++++++++++++++++++++
       
       89 files changed, 31462 insertions(+), 0 deletions(-)
       ---
   DIR diff --git a/BUILD.Win32 b/BUILD.Win32
       t@@ -0,0 +1,30 @@
       +Mixmaster on Windows is known to build with Microsoft Visual Studio .NET
       +2003 Professional.
       +
       +You will need openssl, zlib, pcre, and pdcurses.
       +
       +First, build openssl as described in the openssl documentation.  Place
       +the entire build directory in Src/openssl.
       +
       +zlib, pcre, and pdcurses sources are assumed to be in Src/zlib-1.1.4,
       +Src/pcre-2.08, and Src/pdcurses respectively.
       +
       +Open the mixmaster project win32/mix.sln, and build the mix solution.
       +You should find the results in win32/release.
       +
       +
       +References:
       + - http://www.openssl.org/
       + - http://pdcurses.sourceforge.net/
       +
       +-- 
       +Peter Palfrader, Sat,  1 May 2004 20:31:48 +0200
       +
       +
       +[Note to users of Mixmaster 3.0rc1 and earlier: mix.cfg.txt and pop3.cfg 
       +are now named mix.ini and pop3.ini, respectively, on WIN32. You will 
       +need to manually rename your custom config files, if appropriate.]
       +
       +--
       +Len Sassaman,    Thu, 13 Sep 2007 14:56:37 +0200
       +
   DIR diff --git a/COPYRIGHT b/COPYRIGHT
       t@@ -0,0 +1,134 @@
       +Copyright (c) 1999-2000 Anonymizer Inc.
       +Copyright (c) 2000-2002 Ulf Moeller
       +Copyright (c) 2001-2002 Janis Jagars
       +Copyright (c) 2001-2007 Peter Palfrader
       +Copyright (c) 2001-2008 Len Sassaman
       +Copyright (c) 2004-2008 Colin Tuckley
       +Copyright (c) 2007-2008 Steve Crook
       +
       +
       +MIXMASTER LICENSE AGREEMENT
       +
       +1. Grant of License.
       +
       + Anonymizer Inc. grants you the following non-exclusive license for
       + the Mixmaster program and its associated documentation (the "Program"),
       + subject to all of the following terms and conditions:
       +
       + a) You may use the Program, and copy and distribute verbatim copies
       + of the Program as you receive it, in any medium.
       +
       + Local regulations may exist which limit your rights to distribute or
       + use cryptographic software. In certain jurisdictions, parts of this
       + software may be protected by patents. It is your responsibility to
       + obtain the appropriate licenses.
       +
       + b) You may modify the Program or incorporate the Program or any
       + portion of it into other computer programs. You may copy and
       + distribute such modifications or work, provided that you:
       +
       +       (i) cause the modified Program to carry a prominent notice
       +       stating that it has been modified, and cause the modified files
       +       to carry notices stating that you changed the files and the
       +       date of any change;
       +
       +       (ii) reproduce and include this Agreement, the copyright
       +       notices and disclaimer of warranty on any copy; and
       +
       +       (iii) provide Anonymizer Inc. with a copy of the Source Code of
       +       such modifications or work via electronic mail to the address
       +       mixmaster@anonymizer.com, and grant Anonymizer Inc. a perpetual,
       +       royalty-free license to use and distribute the modifications or
       +       work in its products.
       +
       +       "Source Code" means the preferred form of a work for making
       +       modifications to it, including all modules it contains, plus
       +       any associated interface definition files, scripts used to
       +       control compilation and installation of an executable.
       +
       + c) Should Anonymizer Inc. be acquired by another entity, you:
       +
       +       (i) will grant to the acquiring entity the items in section
       +       1.b.(iii) in leiu of Anonymizer, Inc.;
       +
       + d) Should Anonymizer Inc. cease to exist, and no aquiring entity be
       +    available to accept Source Code modifications, you:
       +
       +       (i) will grant Lance Cottrell the items in section 1.b.(iii) in leiu
       +       of Anonymizer, Inc.
       +
       +       (ii) should Mr. Cottrell be deceased, section 1.b.(iii) of this
       +       license will be rendered null and void.
       +
       + e) In the case that the electronic mail address mixmaster@anonymizer.com
       +    ceases to accept electronic mail,
       +
       +       (i) submission of changes to the Mixmaster project at SourceForge
       +       will be accceptable;
       +
       +       (ii) if Mixmaster development is no longer hosted by SourceForge,
       +       submission of changes to any open source repository similar to
       +       SourceForge, or
       +
       +       (iii) submission to the Internet news group alt.privacy.anon-server
       +       will be acceptable.
       +
       + f) Submission of changes is required as a "best effort". If it is not
       +    possible for you to access any of the notification locations, a notation
       +    in the modified code stating that the modifications should be submitted by
       +    any capable parties who subsequently make use of the modified code will
       +    be acceptable in lieu of code submission.
       +
       +2. Reservation of Rights.
       +
       + No rights are granted to the Program except as expressly set forth
       + herein. You may not copy, modify, sublicense, or distribute the
       + Program except as expressly provided under this Agreement. Any
       + attempt otherwise to copy, modify, sublicense or distribute the
       + Program is void, and will automatically terminate your rights under
       + this Agreement.
       +
       +3. DISCLAIMER OF WARRANTY.
       +
       + BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
       + FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. THE
       + PROGRAM IS PROVIDED ON AN ``AS IS'' BASIS, WITHOUT WARRANTY OF ANY
       + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
       + WARRANTIES THAT THE PROGRAM IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR
       + A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE
       + QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
       + PROGRAM PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT ANONYMIZER INC. OR
       + ANY DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
       + NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF
       + WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF THE
       + PROGRAM IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
       +
       +4. LIMITATION OF LIABILITY.
       +
       + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
       + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL ANONYMIZER INC.
       + OR ANY DEVELOPER OR ANY OTHER CONTRIBUTOR OR ANY SUPPLIER OF ANY OF
       + SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY INDIRECT,
       + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER
       + INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK
       + STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
       + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
       + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
       + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
       + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
       + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
       + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
       + THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
       +
       +5. General.
       +
       + This license represents the complete agreement concerning subject
       + matter hereof. If any provision of this Agreement is held to be
       + unenforceable, such provision shall be reformed only to the extent
       + necessary to make it enforceable. This Agreement shall be governed by
       + California law provisions (except to the extent applicable law, if
       + any, provides otherwise), excluding its conflict-of-law provisions.
       + The application of the United Nations Convention on Contracts for the
       + International Sale of Goods is expressly excluded. Any law or
       + regulation which provides that the language of a contract shall be
       + construed against the drafter shall not apply to this License.
   DIR diff --git a/HISTORY b/HISTORY
       t@@ -0,0 +1,502 @@
       + 1998/1999           2.9   written from scratch.
       +
       +1999-04-14      2.9beta0   public preview release.
       +
       +1999-05-17      2.9beta1   Bug fixes (remix, OpenPGP encryption, FreeBSD
       +                           name conflict); Win32 DLL.
       +
       +1999-05-18      2.9beta2   Install bug fixes. -N and -n options renamed.
       +
       +1999-05-19      2.9beta3   OpenSSL-related bug fix. Type 1 remailer fixes
       +                           (pointed out by <kev@drule.org>).
       +
       +1999-05-20      2.9beta4   Read and generate OpenPGP encrypted secret keys.
       +
       +1999-05-20      2.9beta5   The client sent messages if PGP encryption failed.
       +
       +1999-05-28      2.9beta6   Message-ID generation bug fixes. Contributed by:
       +                           Johannes Kroeger <hanne@squirrel.owl.de>.
       +                           Remix-To bug fix.
       +
       +1999-06-09      2.9beta7   More (minor) remailer and Install script fixes.
       +
       +1999-06-10      2.9beta8   Regular expression bug fix. Thanks to Johannes
       +                           and Kevin for help with debugging!
       +
       +1999-07-20      2.9beta9   Bug fixes (remailer, nym creation).
       +
       +1999-08-03      2.9beta10  Fix for buffer overrun error.
       +                           "Chain:" pseudo-header may contain the number of
       +                           copies like this: `Chain: *,*,*,*; copies=3'
       +
       +1999-09-09      2.9beta11  Support MIME attachments and OpenPGP/MIME in the
       +                              client.
       +                           Do not select cpunk remailers if PGP key is missing.
       +                           Fix error in nym creation.
       +                           Header lines can be edited when composing new
       +                              messages in the mail reader.
       +                           Accept empty pass phrase to allow storing the
       +                              nym database on an encrypted file system.
       +                           More verbose error messages.
       +                           Various minor bug fixes.
       +                           * Thanks to Gerd Beuster for many good suggestions!
       +
       +1999-09-22      2.9beta12  OpenSSL 0.9.3 or newer is now required.
       +                           For the Mixmaster DLL, allow the application to
       +                              seed the random number generator.
       +
       +1999-09-29      2.9beta13  Fix OpenPGP 3DES decryption.
       +                           Store DSA secret keys in PGP5 compatible format.
       +                           Support new "ekx" capability.
       +                           Use the more secure new style OpenPGP conventional
       +                              encryption to protect the nym database and nym
       +                              keys.
       +
       +1999-10-01      2.9beta14  Bug fix.
       +
       +1999-10-01      2.9beta15  Bug fix: create mixrand.bin in Mix directory.
       +                           Support "Encrypt-IDEA" directive.
       +
       +1999-10-11      2.9beta16  Fix memory leaks.
       +
       +1999-11-03      2.9beta17  Bug fix.
       +                           Sending messages is logged as DEBUGINFO.
       +
       +1999-11-09      2.9beta18  Bug fix for rlist with trailing spaces.
       +                           Print remailer reliability (by Gerd Beuster).
       +
       +1999-12-19      2.9beta19  (internal)
       +
       +1999-12-19      2.9beta20  Output remailer RSA keys separately from the
       +                             DSA/ElGamal keys to avoid problems with old
       +                             versions of PGP.
       +                           Messages in mail folders can be deleted. Nym
       +                             messages and other encrypted mail will be
       +                             written back as plain text (by Gerd Beuster).
       +                           SMTP bug fix.
       +                           Support multiple OpenPGP decryption subkeys.
       +                           Fix remailer bug with Newsgroups header in encrypted
       +                             T1 messages.
       +                           Fix MIME-decoding bug (pointed out by Gerd Beuster).
       +                           Nym creation bug fix (by Gerd Beuster).
       +
       +2000-03-09      2.9beta21  Support for PGP partial length packets (by
       +                             Christian Mock).
       +
       +2000-03-16      2.9beta22  Bug fixes (by Antonomasia) and minor changes.
       +
       +2000-06-29      2.9beta23  Bug fix for nym creation with several newsgroups
       +                             reply blocks (by Gerd Beuster).
       +                           --nym option bug fix (by Adam Back).
       +
       +2001-09-11      2.9beta24  Changed pool.c to allow Mixmaster keys to pass
       +                             even when binary blocking is enabled. Note that
       +                             the solution is not a nice one: It does not
       +                             recognize Mix keys, it simply allows 10 lines of
       +                             binary garbage instead of 3. This should be enough
       +                             for Mix keys to come through (by Peter Palfrader).
       +                           Fixed a bug in pgpdata.c affecting v3 OpenPGP keys.
       +                           (by Michael Young).
       +
       +2001-09-14      2.9beta25  Now builds with pcre3 (by Peter Palfrader).
       +                           Added support for destination.allow (by Peter
       +                             Palfrader).
       +                           If the sender email address or IP address matches
       +                             anything in source.blk, ignore the message (by
       +                             cmeclax).
       +                           Added support for the Mutt -T option (by Bill
       +                             O'Hanlon).
       +                           Patches merged (by Len Sassaman).
       +
       +2001-09-17      2.9beta30  Version renamed to avoid conflicts with other
       +                             unofficial releases.
       +
       +2001-09-19      2.9beta31  Fixed a bug in mime.c that sometimes resulted in
       +                             malformed text attachments (by Michael Young).
       +                           Better error handling (by Scott Renfro).
       +                           Added support for multiple dest.blk files. This
       +                             is needed for the Remailer Abuse Blocklist (by
       +                             Markus Stöger).
       +                           Added support for remailer-adminkey replies to
       +                             provide a better way for remops to distribute
       +                             their keys. (by Markus Stöger).
       +                           Fixed errors with pcre2.08 (by Rodney Thayer).
       +                           Added long command option --type-list for the -T
       +                             option, and updated help (by Len Sassaman).
       +                           Removed redundant "encoded" variable in mime.c.
       +                           Fixed Installer bugs.
       +
       +2001-11-06      2.9beta32  Client functionality updates.
       +                           POP sockets now properly close.
       +                           Memory may be freed without allocating.
       +                           Correct time is written to mbox.
       +                           Key flags correctly set in key.txt. (all by
       +                             Disastry).
       +                           OpenSSL and OpenBSD Install script issues
       +                             addressed.
       +
       +2001-12-16      2.9b33     Support for Mixmaster as a service on Windows
       +                             platforms added (by Disastry).
       +                           Problem transparently remixing to Type I remailers
       +                             debugged and corrected (by Andy Dustman,
       +                             Disastry, Senshi-Admin).
       +                           Fixed an error in chain.c that was causing
       +                             segfaults with chains greater than 20 remailers.
       +                           Non-multipart MIME message errors fixed.
       +                           Fixed an error in rfc822.c (by Scott Renfro).
       +                           Fixed pgpget.c errors. (by Ulf Möller).
       +                           No longer permits automatic blocking of entire
       +                             domains or newsgroups.
       +                           Help files re-written (by Lucky Green).
       +                           Fixed inconsistencies between software name and
       +                             package name.
       +
       +2002-07-01      2.9b34     Encrypt-to directive is now supported.
       +                           Partial packets now properly expire if not
       +                             reassembled (by cmeclax).
       +                           Fixed an address blocking error introduced in
       +                             the last version (Peter Palfrader).
       +                           Various command line bug fixes.
       +
       +2002-07-10      2.9b35     Updated zlib due to security reasons.
       +                           Does not generate keys in client mode.
       +                           Uses binary format for id.log.
       +                           Assorted mpgp fixes (by Disastry).
       +                           Added support for storing the key passphrase
       +                             in the mix.cfg file. (by Disastry).
       +                           Now reports the contents of dest.alw for
       +                             middleman remailers (by Kat).
       +                           Reworked the OpenSSL version check in the
       +                             Install script.
       +
       +2002-08-09      2.9b36     Removed duplicate define of NYMDB from menu.h.
       +                           Fix a strncat() to undefined string variable in
       +                             mix.c (Closes: #584381).
       +                           Have the Makefile list all prerequisites for each
       +                             build target (Closes: #584386).
       +                           Change »majordomo@*« to »majordomo@« in default
       +                             dest.blk. The dest block engine does not under-
       +                             stand shell globs. Either substring matches or
       +                             regexen.
       +                           Fixed -T switch: if type2.list is not available fall
       +                             back to pubring.mix.
       +                           USE_IDEA is no longer default in config.h. It always
       +                             gets defined by the Install script instead.
       +                           Only create OpenPGP RSA keys if we compiled with
       +                             IDEA.
       +                           Make all filenames configurable in mix.cfg.
       +                           Add global mix.cfg support (compile time option).
       +                           The -G option now forces creation of new keys even in
       +                             client mode (Closes: #585176).
       +                           Random Documentation updates.
       +                           Default to not installing a .forward file in Install
       +                             script.
       +                           Fix unused variable warning on OpenBSD.
       +                           Fix public remailer keys getting re-signed
       +                             every time keys are requested (Closes: #478383).
       +                           Make smtp sending similar to local /usr/lib/sendmail
       +                             sending (wrt header/body separation;
       +                             Closes: #482052).
       +                           Add X-Loop header on mailbox forwarded messages.
       +                           Several small fixes by Sami Farin et al.
       +                           Detach correctly in daemon mode.
       +                           Minor Install script fixes.
       +
       +2002-08-20      2.9b37     OpenPGP enhancement release (fixes by Disastry).
       +                           Fix a small bug in pgpdata.c that stopped Mixmaster
       +                             from reading cipher preferences.
       +                           Fixed Passphrase reading in mpgp (the test program)
       +                             on Windows platform.
       +                           Add Hash: header when clearsigning.
       +                           Properly handle RSA keys whose key size is not a
       +                             multiple of 64.
       +                           Remove leading zeros from MPI.
       +                           Use MDC packets whenever possible.
       +                           List CAST5 and AES128 in cipher preferences.
       +                           Now displays Mixmaster version in the PGP version
       +                             header for non remailer/nym messages.
       +
       +2002-09-11      2.9b38     Install script deals with lack of patented IDEA
       +                             algorithm in a sane way (closes: #479020).
       +                           Compiled-in passphrase is now deprecated.
       +                           When expiring packet ids from id.log also expire
       +                             packets that are dated more than half a year in
       +                             the future.  That way we get rid of invalid
       +                             packets introduced by the switch to a binary file.
       +                           The stats in remailer-stats replies always had a
       +                             peak at 00:00 GMT which was wrong. Fixed.
       +                             (closes: #597688).
       +                           Fixed a bug with reading armored keyrings consisting
       +                             of more than one armored block or having comments
       +                              in front of the one armored block.
       +                           In RSA PGP keys, we now set e=0x11.
       +                           Mixmaster now deletes error and temporary files
       +                             older than PACKETEXP time along with expired
       +                             partial packets.
       +                           Linux PPC fixes (and all other archs where char is
       +                             unsigned).
       +
       +2002-10-07      2.9b39     Added a new feature, --store-mail (-I), which will
       +                             deliver an encrypted mix packet to the message pool
       +                             without attempting being decrypted.
       +                           Made minor updates for WIN32 DLL.
       +                           When sending type II messages interactively you may
       +                             now choose a middleman remailer as the last hop
       +                             in your chain (closes: #481244).
       +                           If a footer.txt file exists its content will be
       +                             appended to outgoing messages leaving the remailer
       +                             network at this hop (closes: #490117).
       +                           List known remailers in remailer-conf reply (closes:
       +                             #480330).
       +                           The files created with "SENDMAIL outfile" have
       +                             different names now to scale beyond 10k files
       +                             (closes: #587593).
       +                           Fixed the "is a mailfolder" checking for -f.
       +                           Various fixes for Mixmaster when not using ncurses.
       +                           Added new option --config to allow loading of
       +                             configuration information from an alternate file.
       +                           POOL is now used correctly if set in mix.cfg.
       +                           ASCII armor checksum is now verified on PGP keys.
       +                           Corrected a bug where 1/4096 of pgp messages was
       +                             destroyed due an improper armor checksum
       +                             interpretation.
       +                           Added password-based authenticated SMTP for mix.
       +                             Currently, only AUTH LOGIN is supported.
       +                           Mixmaster now handles <CR><LF> in pubring.mix.
       +                           Removed incorrect NT service checks in mix.c.
       +                           Mixmaster now keeps no stats in client mode.
       +                           The pool is autmatically checked for waiting
       +                             messages in the client configuration.
       +                           Mixmaster now bears a DFSG-compliant license.
       +                           Fixed permissions on tarball release.
       +                           Documentation updates.
       +
       +2002-10-16      2.9b40     New option MAILIN that can be set to either a mbox
       +                             or Maildir folder. New mail will be read from it
       +                             and the folder cleared every time Mixmaster
       +                             processes its pool, or at MAILINTIME intervals
       +                             (closes: #597043).
       +                           The Mixmaster daemon now writes a pid file.
       +                           Mixmaster in daemon mode now catches SIGTERM and
       +                             SIGINT and finishes its current queue run and then
       +                             exits successfully.
       +                           Minor code formating cleanup and Install script
       +                             fixes.
       +
       +2002-12-15      2.9b41     The Mixmaster protocol version is now prepended
       +                             to the software version in the Mixmaster cap-
       +                             string.
       +                           Minor configuration default changes and Install
       +                             script fixes.
       +                           Install script now always uses "make" and not
       +                             "gmake".
       +                           IDEA detection is fixed on systems that provide
       +                             the header files but then turn out to not
       +                             have the required functions upon linking.
       +                           Install now properly identifies system-wide
       +                             installations of pcre and/or zlib if they
       +                             are installed in /usr/local/.
       +                           Mixmaster will now ensure that an address
       +                             submitted in a blocking request does not
       +                             match that of a known remailer before
       +                             adding it to the dest.blk file (patch
       +                             submitted by Trek. Vulnerability originally
       +                             discovered by noise and rabbi.)
       +                           Minor documentation fixes.
       +
       +2002-12-16      2.9b42     Minor documentation fixes.
       +                           Append another newline character to mbox folders
       +                             when storing a mail so that the mandatory empty
       +                             line is there.
       +
       +2002-12-16      2.9.0rc1   Release candidate. Packaging changes only.
       +
       +2002-12-25      2.9.0      Release version. Minor documentation changes
       +                             and version number change only.
       +
       +2003-11-08      2.9.1      Several changes for the Windows build.
       +                           Some Install script fixes.
       +                           Fixed a problem in blockrequest() where a buffer
       +                             could have been used after it was free()'d which
       +                             resulted in segfaults.
       +                           Check that feedback buffer is not null before
       +                             operating on it in chain_select().
       +                             Closes #631353, thanks Sami Farin.
       +                           Make sure DH/DSA param file is actually opened
       +                             before writing to it. Fixes a segfault in
       +                             case it is not.
       +                           Handle a pool we cannot read correctly: don't close
       +                             the NULL dir handle (segfaults on *BSD). We also
       +                             print a warning in that case now.
       +                           Minor stats fix (gmtime vs localtime).
       +                           Fix pool stats bug.
       +
       +2004-03-20      3.0b1      FEATURE ENHANCEMENTS:
       +
       +                           The secret pgp keyring is now stored ASCII armored
       +                             with one key per ascii armor.
       +                           NB: Due to the bug with reading armored keyrings and
       +                             secring being stored armored now, it is not
       +                             advisable to downgrade Mixmaster unless special
       +                             action is taken to preserve the secret pgp
       +                             keyring.
       +                           Mixmaster now prompts for secret key passphrase when
       +                             started in daemon mode.
       +                           Mixmaster checks expiration and revocation status of
       +                             pgp keys, userids, and subkeys.
       +                           Mixmaster will not encrypt or sign with a revoked
       +                             or expired key.
       +                           When encrypting, Mixmaster uses preferences from
       +                             the primary userid (or the latest userid, if zero
       +                             or more than one primary userid is present.)
       +                           Mixmaster keys now have creation and expiration date.
       +                             It is not secured by any crypto voodoo, it's only
       +                             informational for clients to decide which keys to
       +                             use should they have more than one per remailer.
       +                             - on the client side we do not show remailers (and
       +                               therefore not use them) if their key is expired.
       +                             - the remailer refuses to decrypt messages to keys
       +                               that expired one month ago or earlier.
       +                             - the remailer automatically creates new Mixmaster
       +                               keys if the current ones are about to expire or
       +                               already are expired.
       +                             - the latest key from secring.mix is written to
       +                               key.txt. It used to be the first one. Since
       +                               creation of new mix key appends the key, this
       +                               seemed sensible.
       +                           Mixmaster now generates dummy messages automatically
       +                             as mail enters and exits the pool.
       +                           Applied Maildir feature patch by drt@un.bewaff.net,
       +                             with some changes by PP:
       +                             MAILBOX can now be a Maildir (closes: #586223).
       +                           New Star-Exclude feature by Colin Tuckley: 
       +                             User-selected remailers can be excluded from 
       +                             being chosen as random hops.
       +                           Have stats on intermediate vs. final hop count
       +                             (closes: #649900).
       +                           Add max capability for Type I.
       +                           Config option EXTFLAGS allows appending additional
       +                             flags to the capabilities string.  (Hauke Lampe)
       +                           Config option PRECEDENCE allows setting the
       +                             Precedence: header on all outgoing mail.
       +                             (Hauke Lampe)
       +                           In order to serve help files in different languages
       +                             we need a way to reply to requests like
       +                             remailer-help-it.  In order to not have to modify
       +                             the code for each and every new ressource,
       +                             Mixmaster now sends the file
       +                             requests/remailer-<something> to
       +                             remailer-<something> requests.
       +                             remailer-{help,key, stats,conf,adminkey} still are
       +                             special cases though.
       +                           Drop messages without timestamps and messages with
       +                             future timestamps.  This abandons backwards
       +                             compatibility with Mixmaster 2.0.3 and earlier.
       +                           Mixmaster attempts to detect system clock
       +                             misconfigurations and refuses to run as a
       +                             remailer if there is a problem suspected.
       +                             Only applies to Mixmaster in remailer mode.
       +
       +                           BUG FIXES:
       +
       +                           Mixmaster in daemon mode reloads configuration on
       +                             SIGHUP.
       +                           In the curses interface chain selection it was not
       +                             possible to select a random last hop with a usenet
       +                             post message.  Fixed (closes: #719165).
       +                           If remix was enabled and we had a Type-I Anon-Post-To
       +                             request we accidently randhoped it via the
       +                             configured default remailing chain (default:
       +                             *,*,*,*).
       +                             Fixed (closes: #729494).
       +                           In client mode (REMAIL n) the pool is flushed every
       +                             time mixmaster is run unless CLIENTAUTOFLUSH is
       +                             set to n.  (closes: #676794: Rate implementation
       +                             doubled)
       +                           Found that weird bug that sometimes led to "Unknown
       +                             remailer version!" errors: In chain_randfinal() we
       +                             selected a random value between 0 and maxrem
       +                             instead of 0 and maxrem - 1.  Mixmaster now uses
       +                             broken-chain info from stats.
       +                           Warn if remailer stats are older than a day or
       +                             from the future.
       +                           Don't send messages to ourselves via the mailsystem
       +                             but instead place them in the pool as incoming
       +                             messages so that they will get processed with the
       +                             next pool run.
       +                           No longer try to send a message if there are no
       +                             recipients left.
       +                           Set default max-randhops from 20 to 4.
       +                           Remix-To chain is limited by max-randhops limit as
       +                             well.
       +                           Messages to more than one remailer are dropped.
       +                           Nym support is not compiled in by default anymore.
       +                           The OpenPGP module mpgp now includes a man
       +                             page (large contributions by Trek).
       +                           Ignore 'No reliable remailers' problems when
       +                             randhopping messages in middleman mode.
       +                             That is better than dropping them.
       +                           Experimental feature:  --redirect -l <chain>.
       +                             If you have a mixmaster message with a
       +                             chain starting with hop1 (you cannot know any
       +                             more because it already is encrypted) then
       +                             mix --redirect -l foo,bar < file
       +                             redirect the message so the chain is actually
       +                             foo,bar,hop1,... and places it in your pool.
       +                             If the total number of hops (which cannot be
       +                             known) exceeds 20 the message is damanged
       +                             and will fail at the 20th node.
       +
       +2004-05-06      3.0b2
       +                           Use /dev/arandom instead of /dev/srandom on 
       +                             OpenBSD (Nikolay Sturm).
       +                           Fall back to 3DES as Encrypt-Key cipher if we don't
       +                             have IDEA. - Laurent Fousse <laurent@komite.net>
       +                           Also sort mail into the various mboxes if autoreply
       +                             is not set.
       +                           Properly ignore whitespace in chain selection.
       +                           Removed unused functions in keymgt.c.
       +                           Added new options -V, --version, and --about.
       +                           Made manpage corrections.
       +                           Minor ncurses display tweaks.
       +                           General improvements for Win32 support (by 
       +                             goblin and Peter Palfrader).
       +                           Preliminary Windows Installer work.
       +                           On Win32, default to Application Data/Mixmaster for
       +                             mixmaster's basedirectory.  This can still be
       +                             overridden by MIXPATH or the registry entry
       +                             HKEY_CURRENT_USER\Software\Mixmaster\MixDir
       +                           Introduced new option "(e)dit configuration 
       +                             file" in the main menu.
       +                           Changed 'q)uit' to 'q)uit w/o sending' in 
       +                             menusend.c.
       +                           Added stats downloading support. Currently 
       +                             works under Win32 only (by goblin).
       +                           Fixed bug in buffers.c.
       +
       +2006-06-24      3.0rc1
       +                           Prefer pubring.asc over secring.pgp.
       +                           Support an unpublished dest.alw file.
       +                           Added MINLAT directive. Ensures randhopped 
       +                             messages are sent through remailers of 
       +                             latency of MINLAT time or greater
       +                             (suggested by Steve Crook).
       +                           Improved OpenSSL version checking in the
       +                             Install script.
       +                           Added full stats download support.
       +                           Fixed buffer overflow bug in keymgt.c.
       +
       +2008-03-03     3.0
       +                           Changed name of WIN32 default config file
       +                             from mix.cfg.txt to mix.ini.
       +                           Changed pop3.cfg to pop3.ini on WIN32.
       +                           Updated Install script.
       +                           Minor documentation changes.
       +
       +
       +
       +Mixmaster maintainer history:
       +
       +1998-2000: Ulf Möller -- versions 2.9beta0 through 2.9beta22.
       +2000: Johannes Kroeger -- version 2.9beta23.
       +2001-2008: Len Sassaman -- versions 2.9beta24 through present.
   DIR diff --git a/Install b/Install
       t@@ -0,0 +1,1403 @@
       +#!/bin/sh
       +# Mixmaster version 3.0  --  (C) 1999-2008 Anonymizer Inc. and others.
       +
       +# Mixmaster may be redistributed and modified under certain conditions.
       +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +# ANY KIND, either express or implied. See the file COPYRIGHT for
       +# details.
       +
       +# $Id: Install 979 2008-03-03 18:17:07Z rabbi $
       +
       +#whereis program default-path
       +whereis()
       +{
       +  #echo "Looking for $1..."
       +  found=""
       +  for i in $* `which $1 2>&1`
       +  do
       +    if [ -f "$i" -a -x "$i" ]
       +    then
       +      found=$i
       +    fi
       +  done
       +  if [ "$found" = "" ]
       +  then
       +    found=$2
       +#    echo "$1 not found. Using $found."
       +#  else
       +#    echo "$1 is at $found."
       +  fi
       +}
       +
       +if echo -n | grep n >/dev/null
       +then
       + echo1=""
       + echo2="\c"
       +else
       + echo1="-n"
       + echo2=""
       +fi
       +
       +# readln text default
       +readln()
       +{
       +  echo $echo1 "$1 [$2] $echo2"
       +  read ans
       +  if [ -z "$ans" ]
       +  then
       +    ans="$2"
       +  fi
       +}
       +
       +# findlib libxxx.a -- find and configure libraries
       +#    Input:
       +#       $1       library name
       +#       $CONFIG  library configure options
       +#       $INCDIR  possible include directories
       +#       $SRCDIR  possible library source directories
       +#       $LIBDIR  possible library binary directories
       +#
       +#    Output:
       +#       $found   library directory
       +#       $lib     library name
       +#       $INCDIR  include directory if required, empty otherwise
       +#       $LDFLAG  linker options
       +#       $LIB     path to library file
       +#       $MAKELIB Makefile entry to compile library
       +findlib()
       +{
       + lib=$1
       + libso=`echo $lib | sed 's/\.a$/.so/'`
       + echo "Looking for $lib..."
       +
       + found=
       + source=
       + type=
       + LIB=
       + LDFLAG=
       + MAKELIB=
       +
       + for i in /usr/local/lib /usr/lib /lib /usr/lib64
       + do
       +  if [ -r $i/$lib -o -r $i/$libso ]
       +  then
       +   found=$i
       +   type=system
       +  fi
       + done
       +
       + for i in $LIBDIR
       + do
       +  if [ -r $i/$lib -o -r $i/$libso ]
       +  then
       +   found=$i
       +   type=installed
       +  fi
       + done
       +
       + for i in $SRCDIR
       + do
       +  if [ -r $i/$lib -o -r $i/lib/$lib ]
       +  then
       +   found=$i
       +   type=binary
       +  fi
       + done
       +
       + if [ -r "$found/$libso" ]
       + then
       +  echo "Found at $found/$libso."
       + elif [ -r "$found/$lib" ]
       + then
       +  echo "Found at $found/$lib."
       + elif [ -r "$found/lib/$lib" ]
       + then
       +  echo "Found at $found/lib/$lib."
       + fi
       +
       + for i in $SRCDIR
       + do
       +  if [ -d $i -a ! "$type" = binary ]
       +  then
       +   source=$i
       +  fi
       + done
       +
       + if [ "$source" != "" ]
       + then
       +  echo "Found source directory $source."
       +  if [ "$found" = "" ]
       +  then
       +   ans=y
       +  else
       +   echo "Use the source if the pre-installed library causes compilation problems."
       +   readln "Use source?" n
       +  fi
       +  if [ "$ans" = "y" ]
       +  then
       +   found=$source
       +   type=source
       +  fi
       + fi
       +
       + if [ "$found" = "" ]
       + then
       +  echo "Not found."
       + fi
       +
       + if [ -r $found/lib/$lib ]
       + then
       +  LIB=$found/lib/$lib
       + else
       +  LIB=$found/$lib
       + fi
       + if [ "$type" = system ]
       + then
       +  LIB=
       +  LDFLAG="-l`echo $lib | sed 's/^lib//;s/\.a$//'` -L$found"
       +  if [ "$found" = "/usr/local/lib" ]
       +  then
       +    INCDIR="/usr/local/include $INCDIR"
       +  fi
       + fi
       +
       + incdir=$INCDIR
       + INCDIR=
       + for i in $incdir
       + do
       +  if [ -d $i ]
       +  then
       +   INCDIR=$i
       +  fi
       + done
       +
       + if [ "$type" = source -o "$type" = binary ]
       + then
       +  if [ ! -r $found/lib/$lib ]
       +  then
       +   MAKELIB="$found/$lib:
       +        cd $found; make $lib"
       +  fi
       +  if [ -d $found/include ]
       +  then
       +   INCDIR=$found/include
       +  else
       +   INCDIR=$found
       +  fi
       + fi
       +
       + if [ "$type" = source ]
       + then
       +  dir=`pwd`
       +  if [ "$dir" = "" ]
       +  then
       +   dir=$PWD
       +  fi
       +
       +  cd $found
       +  if [ -x configure ]
       +  then
       +   echo "Configuring..."
       +   ./configure $CONFIG
       +  fi
       +  if [ "$lib" = "libcrypto.a" ]
       +  then
       +   if [ -f config ]
       +   then
       +    sh config
       +   elif [ -x Configure ]
       +   then
       +    ./Configure 2>tmp.$$
       +    cat tmp.$$
       +    readln "Your system?" `cat tmp.$$ | tr ' ' '\n' | grep -i \`uname\` | tail -1`
       +    rm -f tmp.$$
       +    echo "Configuring..."
       +    ./Configure $ans
       +   fi
       +  fi
       +  cd $dir
       + fi
       +}
       +
       +# Global installation.
       +
       +
       +##########################################################################
       +umask 077
       +
       +#FIXME -- Mixmaster now should be installed as root, and Install should
       +#create a remailer user. /var/spool/mixmaster is a good home.
       +
       +if [ `whoami` = root ]
       +then
       + echo "Please create a new user, e.g, \`mix', and install Mixmaster under that
       +user id.  Installing Mixmaster as root is not recommended."
       + readln "Continue anyway?" n
       + if [ "$ans" = n ]
       + then
       +  exit 1
       + fi
       +fi
       +
       +MIXDIR="$PWD"
       +if [ "$MIXDIR" = "" ]
       +then
       + MIXDIR=`pwd`
       +fi
       +MIXCFG="$MIXDIR/conf"
       +MIXSRC="$MIXDIR/Src"
       +MIXDEST0=${MIXPATH:-$HOME/Mix}
       +
       +system=`uname`
       +if [ "$system" = "MS-DOS" ]
       +then
       + system=msdos
       +fi
       +
       +if [ "$HOSTNAME" = "" ]
       +then
       + HOSTNAME=`hostname`
       +fi
       +if [ "$HOSTNAME" = "" ]
       +then
       + HOSTNAME=msdos
       + system=msdos
       +fi
       +
       +if [ "$system" = msdos ]
       +then
       + MIXDEST0=${MIXPATH:-C:/Mix}
       +fi
       +
       +if [ -f "$MIXSRC/Makefile" ]
       +then
       + if grep "#Makefile generated.*$HOSTNAME" $MIXSRC/Makefile
       + then
       +  echo "Found a Makefile for this system."
       +  readln "Use this Makefile?" y
       +  if [ "$ans" = n ]
       +  then
       +   rm -f "$MIXSRC/Makefile"
       +  fi
       + else
       +  readln "Remove old Makefile?" y
       +  if [ "$ans" = y ]
       +  then
       +   rm -f "$MIXSRC/Makefile"
       +  fi
       + fi
       +fi
       +
       +if [ -f "$MIXSRC/Makefile" ]
       +then
       + MIXDEST=`grep "DSPOOL=" $MIXSRC/Makefile | sed 's/.*DSPOOL=..//;s/\".*//'`
       + if [ "$MIXDEST" = "" ]
       + then
       +  MIXDEST="$MIXDEST0"
       + fi
       +fi
       +
       +if [ "$MIXDEST" = "" ]
       +then
       + readln "Mixmaster directory?" "$MIXDEST0"
       + MIXDEST=$ans
       +else
       + echo "Mixmaster directory: $MIXDEST"
       +fi
       +
       +if [ ! -d "$MIXDEST" ]
       +then
       +  echo "Creating directory $MIXDEST"
       +  mkdir "$MIXDEST"
       +fi
       +
       +if [ ! -d "$MIXDEST" ]
       +then
       +  echo "Cannot not create $MIXDEST"
       +  exit 1
       +fi
       +
       +if [ -f "$MIXDEST/mix.cfg" ]
       +then
       +  if [ -f "$MIXDEST/secring.mix" ]
       +  then
       +    remailer=y
       +    if grep PASSPHRASE "$MIXDEST/mix.cfg" >/dev/null
       +    then
       +      PASSINCONFIG=1
       +    fi
       +  else
       +    readln "Do you want to set up a remailer?" n
       +    remailer=$ans
       +  fi
       +elif [ -f "$MIXDEST/mixmaster.conf" ]
       +then
       +  echo "Upgrading from Mixmaster 2.0.*"
       +  remailer=n
       +else
       +  readln "Do you want to set up a remailer?" y
       +  remailer=$ans
       +fi
       +
       +
       +ans=""
       +if [ "$remailer" = "y" ]
       +then
       +  ans="n"
       +  if [ "$PASSINCONFIG" != 1 ]
       +  then
       +    echo ""
       +    echo "You can either compile your secret passphrase into the binary
       +or you can set it in your config file. Note that the former does not
       +really increase security as the passphrase can still be discovered by
       +running something like \`strings mixmaster'."
       +    echo ""
       +    echo "Most users should answer \`n' to this question:"
       +    echo ""
       +    readln "Do you want to compile the passphrase into the binary?" n
       +  fi
       +
       +  rm -f "$MIXSRC/mix.o" # make sure our new passphrase takes effect
       +  if [ "$ans" = "y" ]
       +  then
       +    ans=""
       +    echo "Please enter a passphrase for your remailer (must be the same
       +whenever you re-compile Mixmaster)."
       +    read ans
       +
       +    if [ "$ans" != "" ]
       +    then
       +      PASS="PASS=$ans"
       +    else
       +      echo "WARNING: not setting a passphrase"
       +    fi
       +  else
       +    if [ "$PASSINCONFIG" != 1 ]
       +    then
       +      ans=""
       +      echo "Please enter a passphrase for your remailer (it will be 
       +stored in mix.cfg in clear)."
       +      read ans
       +
       +      if [ "$ans" = "" ]
       +      then
       +        echo "WARNING: setting empty passphrase"
       +      fi
       +      PASSPHRASE="PASSPHRASE        $ans"
       +      if [ -f $MIXDEST/mix.cfg ]
       +      then
       +        echo "$PASSPHRASE" >> $MIXDEST/mix.cfg
       +      fi
       +    fi
       +  fi
       +fi
       +
       +
       +cd "$MIXSRC"
       +if [ ! -f Makefile ]
       +then
       + LIBS=
       + INC=
       + DEF=
       + LDFLAGS=
       +
       + if [ ! -z "$PASS" ]
       + then
       +   DEF="$DEF -DCOMPILEDPASS='\"\$(PASS)\"'"
       + fi
       +
       + if [ "$system" = msdos ]
       + then
       +  readln "Use WIN32 GUI?" y
       +  if [ "$ans" = y ]
       +  then
       +   system=win32
       +   LDFLAGS=-lwsock32
       +  fi
       + fi
       + if [ "$system" = SunOS ]
       + then
       +  LDFLAGS="-lsocket -lnsl"
       + fi
       +
       + LIBDIR=
       + INCDIR=
       + SRCDIR=zlib*
       + findlib libz.a
       + if [ "$found" = "" ]
       + then
       +  readln "Continue anyway?" n
       +  if [ "$ans" = "n" ]
       +  then
       +   echo "Please install zlib 1.1.4 or 1.2.3 or greater now."
       +   exit 1
       +  fi
       + else
       +  ZLIB="$MAKELIB"
       +  DEF="$DEF -DUSE_ZLIB"
       +  LIBS="$LIBS $LIB"
       +  LDFLAGS="$LDFLAGS $LDFLAG"
       +  if [ "$INCDIR" != "" ]
       +  then
       +   INC="$INC -I$INCDIR"
       +  fi
       + fi
       +
       + LIBDIR=
       + INCDIR="/usr/include /usr/include/pcre /usr/local/pcre/include"
       + SRCDIR=pcre*
       + findlib libpcre.a
       + if [ "$found" != "" ]
       + then
       +  PCRE="$MAKELIB"
       +  DEF="$DEF -DUSE_PCRE"
       +  LIBS="$LIBS $LIB"
       +  LDFLAGS="$LDFLAGS $LDFLAG"
       +  if [ "$INCDIR" != "" ]
       +  then
       +   INC="$INC -I$INCDIR"
       +  fi
       + fi
       +
       + opensslinfo="Please get OpenSSL 0.9.6l or greater from http://www.openssl.org/"
       + opensslwarning6="WARNING: This version of OpenSSL contains known vulnerabilities. Please upgrade to OpenSSL 0.9.6l or greater!"
       + opensslwarning7="WARNING: This version of OpenSSL contains known vulnerabilities. Please upgrade to OpenSSL 0.9.7c or greater!"
       + opensslwarning0=$opensslwarning7
       + LIBDIR=/usr/local/ssl/lib
       + INCDIR="/usr/include /usr/include/ssl /usr/lib/ssl/include /usr/local/ssl/include"
       + SRCDIR="openssl*"
       +
       + opensslwarn()
       + {
       + if [ "$1" = "6" ]
       + then
       +  echo $opensslwarning6
       + elif [ "$1" = "7" ]
       + then
       +  echo $opensslwarning7
       + else 
       +  echo $opensslwarning0
       + fi
       +  readln "Continue anyway?" y
       +  if [ "$ans" = "n" ]
       +  then
       +   echo $opensslinfo
       +   exit 1
       +  fi
       + }
       +
       + if [ "$system" = win32 ]
       + then
       +  findlib libeay32.a
       + else
       +  findlib libcrypto.a
       + fi
       + if [ "$found" = "" ]
       + then
       +  echo $opensslinfo
       +  exit 1
       + fi
       +
       + OPENSSLLIB="$LIB"
       + LIBS="$LIBS $LIB"
       + LDFLAGS="$LDFLAGS $LDFLAG"
       + if [ "$MAKELIB" != "" ]
       + then
       +  OPENSSL="$found/$lib:
       +        cd $found/crypto; make"
       + fi
       + if [ -d "$INCDIR/openssl" ]
       + then
       +  INC="$INC -I$INCDIR"
       + else
       +  # detect old SSLeay versions
       +  if [ -f "$INCDIR/crypto.h" ]
       +  then
       +   version=800
       +   if grep OPENSSL "$INCDIR/crypto.h" > /dev/null
       +   then
       +    version=920
       +   fi
       +  fi
       + fi
       +
       + # Find the OpenSSL version header
       + if [ -f "$INCDIR/openssl/opensslv.h" ]
       + then
       +  version=`grep 'SSL.*_VERSION_NUMBER.*0x' $INCDIR/openssl/opensslv.h | sed 's/.*0x0*//;s/[         ].*//;s/L$//' | tr '[a-f]' '[A-F]'`
       + elif [ -f "$INCDIR/opensslv.h" ]
       + then
       +  version=`grep 'SSL.*_VERSION_NUMBER.*0x' $INCDIR/opensslv.h | sed 's/.*0x0*//;s/[         ].*//;s/L$//' | tr '[a-f]' '[A-F]'`
       + fi
       + if [ "$version" = "" ]
       + then
       +  echo "Warning: Can't find OpenSSL version number!"
       +  readln "Continue anyway?" y
       +  if [ "$ans" = "n" ]
       +  then
       +   echo $opensslinfo
       +   exit 1
       +  fi
       +#
       +# Here we match against known OpenSSL versions
       +#
       + elif [ "$version" = "90581F" ]
       + then
       +  decimalversion=9459743
       +  echo "Compiling with OpenSSL 0.9.5a."
       +  opensslwarn 6
       + elif [ "$version" = "90601F" ]
       + then
       +  decimalversion=9461791
       +  echo "Compiling with OpenSSL 0.9.6a."
       +  opensslwarn 6
       + elif [ "$version" = "90602F" ]
       + then
       +  decimalversion=9461807
       +  echo "Compiling with OpenSSL 0.9.6b."
       +  opensslwarn 6
       + elif [ "$version" = "90603F" ]
       + then
       +  decimalversion=9461823
       +  echo "Compiling with OpenSSL 0.9.6c."
       +  opensslwarn 6
       + elif [ "$version" = "90604F" ]
       + then
       +  decimalversion=9461839
       +  echo "Compiling with OpenSSL 0.9.6d."
       +  opensslwarn 6
       + elif [ "$version" = "90605F" ]
       + then
       +  decimalversion=9461855
       +  echo "Compiling with OpenSSL 0.9.6e."
       +  opensslwarn 6
       + elif [ "$version" = "90606F" ]
       + then
       +  decimalversion=9461871
       +  echo "Compiling with OpenSSL 0.9.6f."
       +  opensslwarn 6
       + elif [ "$version" = "90607F" ]
       + then
       +  decimalversion=9461887
       +  echo "Compiling with OpenSSL 0.9.6g."
       +  opensslwarn 6
       + elif [ "$version" = "90608F" ]
       + then
       +  decimalversion=9461903
       +  echo "Compiling with OpenSSL 0.9.6h."
       +  opensslwarn 6
       +elif [ "$version" = "90609F" ]
       + then
       +  decimalversion=9461919
       +  echo "Compiling with OpenSSL 0.9.6i."
       +  opensslwarn 6
       + elif [ "$version" = "9060A0" ]
       + then
       +  decimalversion=9461920
       +  echo "Compiling with OpenSSL 0.9.6j."
       +  opensslwarn 6
       + elif [ "$version" = "9060B0" ]
       + then
       +  decimalversion=9461936
       +  echo "Compiling with OpenSSL 0.9.6k."
       +  opensslwarn 6
       + elif [ "$version" = "9060C0" ]
       + then
       +  decimalversion=9461952
       +  echo "Compiling with OpenSSL 0.9.6l."
       + elif [ "$version" = "9060D0" ]
       + then
       +  decimalversion=9461968
       +  echo "Compiling with OpenSSL 0.9.6m."
       + elif [ "$version" = "90700F" ]
       + then
       +  decimalversion=9465871
       +  echo "Compiling with OpenSSL 0.9.7."
       +  opensslwarn 7
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90701F" ]
       + then
       +  decimalversion=9465887
       +  echo "Compiling with OpenSSL 0.9.7a."
       +  opensslwarn 7
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90702F" ]
       + then
       +  decimalversion=9465903
       +  echo "Compiling with OpenSSL 0.9.7b."
       +  opensslwarn 7
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90703F" ]
       + then
       +  decimalversion=9465919
       +  echo "Compiling with OpenSSL 0.9.7c."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90704F" ]
       + then
       +  decimalversion=9465935
       +  echo "Compiling with OpenSSL 0.9.7d."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90705F" ]
       + then
       +  decimalversion=9465951
       +  echo "Compiling with OpenSSL 0.9.7e."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90706F" ]
       + then
       +  decimalversion=9465967
       +  echo "Compiling with OpenSSL 0.9.7f."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90707F" ]
       + then
       +  decimalversion=9465983
       +  echo "Compiling with OpenSSL 0.9.7g."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90708F" ]
       + then
       +  decimalversion=9465999
       +  echo "Compiling with OpenSSL 0.9.7h."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90709F" ]
       + then
       +  decimalversion=9466015
       +  echo "Compiling with OpenSSL 0.9.7i."
       +  DEF="$DEF -DUSE_AES"
       +
       + elif [ "$version" = "9070AF" ]
       + then
       +  decimalversion=9466031
       +  echo "Compiling with OpenSSL 0.9.7j."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "9070BF" ]
       + then
       +  decimalversion=9466047
       +  echo "Compiling with OpenSSL 0.9.7k."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "9070CF" ]
       + then
       +  decimalversion=9466063
       +  echo "Compiling with OpenSSL 0.9.7l."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "9070DF" ]
       + then
       +  decimalversion=9466079
       +  echo "Compiling with OpenSSL 0.9.7m."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "9070EF" ]
       + then
       +  decimalversion=9466095
       +  echo "Compiling with OpenSSL 0.9.7n."
       +  echo "This version was unreleased at the time of packaging."
       +  echo "It is not guaranteed to work. Please report any problems."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90800F" ]
       + then
       +  decimalversion=9469967
       +  echo "Compiling with OpenSSL 0.9.8."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90801F" ]
       + then
       +  decimalversion=9469983
       +  echo "Compiling with OpenSSL 0.9.8a."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90802F" ]
       + then
       +  decimalversion=9469999
       +  echo "Compiling with OpenSSL 0.9.8b."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90803F" ]
       + then
       +  decimalversion=9470015
       +  echo "Compiling with OpenSSL 0.9.8c."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90804F" ]
       + then
       +  decimalversion=9470031
       +  echo "Compiling with OpenSSL 0.9.8d."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90805F" ]
       + then
       +  decimalversion=9470047
       +  echo "Compiling with OpenSSL 0.9.8e."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90806F" ]
       + then
       +  decimalversion=9470063
       +  echo "Compiling with OpenSSL 0.9.8f."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90807F" ]
       + then
       +  decimalversion=9470079
       +  echo "Compiling with OpenSSL 0.9.8g."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90808F" ]
       + then
       +  decimalversion=9470095
       +  echo "Compiling with OpenSSL 0.9.8h."
       +  DEF="$DEF -DUSE_AES"
       + elif [ "$version" = "90809F" ]
       + then
       +  decimalversion=9470111
       +  echo "Compiling with OpenSSL 0.9.8h."
       +  echo "This version was unreleased at the time of packaging."
       +  echo "It is not guaranteed to work. Please report any problems."
       +  DEF="$DEF -DUSE_AES"
       + fi
       +#
       +# Now we try to guess about unknown versions: 
       +#
       + if [ "$decimalversion" = "" ]
       + then
       +  decimalversion=`echo 16i $version p | dc`
       + fi
       + if [ "$decimalversion" = "" ]
       + then
       +  echo "Warning: This version: ${version} of OpenSSL is not recognized."
       +  readln "Continue anyway?" y
       +  if [ "$ans" = "n" ]
       +  then
       +   echo $opensslinfo
       +   exit 1
       +  else
       +   echo "Does this version of OpenSSL contain AES support?"
       +   readln "If unsure of the answer, say \`n'" n
       +    if [ "$ans" = "y" ]
       +    then
       +    DEF="$DEF -DUSE_AES"
       +    fi
       +  fi
       + elif [ "$decimalversion" -lt "2336" ]  # 920
       + then
       +  echo "This version: ${version} of SSLeay is not supported."
       +  echo $opensslinfo
       +  exit 1
       + elif [ "$decimalversion" -lt "9449728" ]  # 903100
       + then
       +  echo "This version: ${version} of OpenSSL is not supported."
       +  echo $opensslinfo
       +  exit 1
       + elif [ "$decimalversion" -gt "9470111" ]  # 0.9.8h
       + then
       +  echo "Warning: This version: ${version} of OpenSSL is untested."
       +  readln "Continue anyway?" y
       +  if [ "$ans" = "n" ]
       +  then
       +   echo $opensslinfo
       +   exit 1
       +  else 
       +   echo "Does this version of OpenSSL contain AES support?"
       +   readln "If unsure of the answer, say \`n'" n
       +    if [ "$ans" = "y" ]
       +    then
       +    DEF="$DEF -DUSE_AES"
       +    fi
       +  fi
       + fi
       +
       + LIBDIR=
       + INCDIR=/usr/include/ncurses
       + SRCDIR=ncurses*
       + CONFIG=--enable-termcap
       + if [ "$TERMINFO" != "" ]
       + then
       +  CONFIG="--datadir=$TERMINFO"
       + fi
       + if [ -d /usr/share/terminfo ]
       + then
       +  CONFIG=
       + fi
       + if [ -d /usr/lib/terminfo ]
       + then
       +  CONFIG=--datadir=/usr/lib/terminfo
       + fi
       +
       +  if [ `uname` = OpenBSD ]
       +  then
       +   findlib libcurses.a
       +  else
       +   findlib libncurses.a
       +  fi
       + if [ "$found" = "" ]
       + then
       +  if [ "$system" != win32 ]
       +  then
       +   readln "Do you want to use Mixmaster's menu-based user interface?" y
       +   if [ "$ans" = "y" ]
       +   then
       +    echo "Please install ncurses now. It is available from http://www.clark.net/pub/dickey/ncurses/ncurses.tar.gz"
       +    exit 1
       +   fi
       +  fi
       + else
       +  DEF="$DEF -DUSE_NCURSES"
       +  if [ "$type" = system -o "$type" = installed ]
       +  then
       +   LIBS="$LIBS $LIB"
       +   LDFLAGS="$LDFLAGS $LDFLAG"
       +  else
       +   LIBS="$LIBS $found/lib/$lib"
       +   NCURSES="$found/lib/$lib:
       +        cd $found/ncurses; make ../lib/$lib"
       +  fi
       +  if [ "$INCDIR" != "" ]
       +  then
       +   INC="$INC -I$INCDIR"
       +  elif [ -f "/usr/include/ncurses.h" ]
       +  then
       +   DEF="$DEF -DHAVE_NCURSES_H"
       +  fi
       + fi
       +
       + ideawarn()
       + {
       +    echo "
       +  WARNING: Your version of OpenSSL has been configured without IDEA support.
       +  If you continue, Mixmaster will be installed with reduced functionality.
       +  This means (among other things) that Mixmaster will not create an RSA
       +  OpenPGP key (to avoid mail loss in the Type I system). You may want to
       +  re-install OpenSSL before proceeding.
       +
       +  This will not concern you if you only plan to run a type II remailer or
       +  simply want a type II client."
       +    readln "Continue anyway?" y
       +    if [ "$ans" = "n" ]
       +    then
       +     exit 1
       +    fi
       + }
       +
       + if [ "$system" = OpenBSD ]
       + then
       +  LIBDIR=
       +  INCDIR=
       +  SRCDIR=idea*
       +  findlib libidea.a
       +  if [ "$found" = "" ]
       +  then
       +   ideawarn
       +  else
       +   DEF="$DEF -DUSE_IDEA"
       +   IDEALIB="$MAKELIB"
       +   LIBS="$LIBS $LIB"
       +   LDFLAGS="$LDFLAGS $LDFLAG"
       +   if [ "$INCDIR" != "" ]
       +   then
       +    INC="$INC -I$INCDIR"
       +   fi
       +  fi
       + elif [ "$system" = msdos -o "$system" = win32 ]
       + then
       +  DEF="$DEF -DUSE_IDEA"
       + else
       +   echo "Checking for IDEA support..."
       +   cat <<END >tmptst.c
       +#include <openssl/idea.h>
       +int main() {
       +  void *dummy;
       +  dummy = idea_cfb64_encrypt;
       +  exit(0);
       +}
       +END
       +   if gcc $LDFLAGS $INC tmptst.c -o tmptst $OPENSSLLIB
       +   then
       +     DEF="$DEF -DUSE_IDEA"
       +   else
       +     ideawarn
       +   fi
       +   rm -f tmptst.c tmptst
       + fi
       +
       + echo "testing for setenv()..."
       + cat <<END >tmptst.c
       +int main() {
       +#include <stdlib.h>
       + setenv("TZ", "GMT", 0);
       + exit(0);
       +}
       +END
       + if gcc tmptst.c -o tmptst
       + then
       +   DEF="$DEF -DHAVE_SETENV"
       + fi
       + echo "done"
       + rm -f tmptst.c tmptst
       +
       +# if [ "$MIXDEST" = "$HOME/Mix" ]
       +# then
       +#  SPOOL=
       +# else
       +  SPOOL=-DSPOOL=\'\"$MIXDEST\"\'
       +# fi
       +
       + echo "Generating Makefile."
       + echo "#Makefile generated on $HOSTNAME `date`" >Makefile
       + sed -e "s#%MIXDIR#$SPOOL#" \
       +     -e "s#%LIBS#$LIBS#" \
       +     -e "s#%LDFLAGS#$LDFLAGS#" \
       +     -e "s#%INC#$INC#" \
       +     -e "s#%DEF#$DEF#" < Makefile.in >> Makefile
       +# echo "$ZLIB" >>Makefile
       +# echo "$PCRE" >>Makefile
       + echo "$IDEALIB" >>Makefile
       + echo "$NCURSES" >>Makefile
       + echo "$OPENSSL" >>Makefile
       +fi
       +
       +
       +
       +
       +
       +echo "Compiling. Please wait."
       +whereis make
       +make=$found
       +
       +if [ "$system" = win32 ]
       +then
       +# (cd zlib*; make libz.a)
       +# (cd pcre*; make libpcre.a)
       + if [ "$PASS" != "" ]
       + then
       +  $make "$PASS" dllmix
       + else
       +  $make dllmix
       + fi
       +else
       + if [ "$PASS" != "" ]
       + then
       +  $make "$PASS"
       + else
       +  $make
       + fi
       +fi
       +
       +if [ -x mixmaster ]
       +then
       + echo
       +else
       + echo "Error: The compilation failed. Please consult the documentation (section
       +\`Installation problems')."
       + readln "Remove the old Makefile?" y
       + if [ "$ans" = y ]
       + then
       +  rm -f Makefile
       + fi
       + exit 1
       +fi
       +
       +if [ -f "$MIXDEST/mixmaster.conf" -a ! -f "$MIXDEST/mix.cfg" ]
       +then
       + export MIXDEST
       + export MIXDIR
       + export MIXSRC
       + "${MIXDIR}/upgrade"
       + exit 0
       +fi
       +
       +if [ -f mixmaster.exe ]
       +then
       + cp mixmaster.exe "$MIXDEST"
       +else
       + cp mixmaster "$MIXDEST"
       +fi
       +
       +cd "$MIXCFG"
       +for i in mlist.txt pubring.mix rlist.txt pubring.asc
       +do
       + if [ ! -f "$MIXDEST/$i" ]
       + then
       +  cp "$i" "$MIXDEST"
       + fi
       +done
       +
       +if [ "$remailer" = "y" ]
       +then
       + cd "$MIXCFG"
       + for i in adminkey.txt dest.alw
       + do
       +  if [ ! -f "$MIXDEST/$i" ]
       +  then
       +   cp "$i" "$MIXDEST"
       +  fi
       + done
       +fi
       +
       +if [ "$remailer" = "n" ]
       +then
       + if [ ! -f "$MIXDEST/mix.cfg" ]
       + then
       +  whereis sendmail /usr/lib/sendmail /usr/sbin/sendmail
       +  echo "SENDMAIL        $found -t" >"$MIXDEST/mix.cfg"
       +  cat mix.cfg >>"$MIXDEST/mix.cfg"
       + fi
       + echo "Client installation complete."
       + exit
       +fi
       +
       +for i in *.blk
       +do
       + if [ ! -f "$MIXDEST/$i" ]
       + then
       +  cp "$i" "$MIXDEST"
       + fi
       +done
       +
       +cd "$MIXDEST"
       +
       +installed=n
       +if [ -f mix.cfg ]
       +then
       + if grep REMAILERADDR mix.cfg >/dev/null
       + then
       +  installed=y
       + fi
       +fi
       +
       +if [ "$installed" = "n" ]
       +then
       + Date=`date`
       + whereis sendmail /usr/lib/sendmail /usr/sbin/sendmail
       + sendmail=$found
       +
       + echo "Mixmaster can be installed in the low-maintenance \`middleman' mode.
       +In that mode, it will send mail to other remailers only, to avoid
       +complaints about anonymous messages."
       + readln "Install as middleman?" n
       + middle=$ans
       +
       + readln "The e-mail address of your remailer:" `whoami`@$HOSTNAME
       + RMA=$ans
       +
       + echo "Do you want Mixmaster to send auto-replies to messages it does not
       +understand (If the address <$RMA> is also used"
       + readln "for mail to be read by a human, type \`n')?" y
       + autoreply=$ans
       +
       + if [ "$middle" = n ]
       + then
       +  readln "An address to appear in the \`From:' line of anonymous messages:" `echo $RMA | sed 's/.*@/nobody@/'`
       +  RAA=$ans
       +
       +  readln "Address for complaints to be sent to:" `echo $RMA | sed 's/.*@/abuse@/'`
       +  CA=$ans
       + else
       +  RAA=$RMA
       +  CA=$RMA
       + fi
       +
       + echo "Choose a name for your remailer.  It will appear in remailer status messages."
       + readln "Long name:" "Anonymous Remailer"
       + RMN=$ans
       +
       + if [ "$middle" = n ]
       + then
       +  echo "Choose a name to be used in the \`From:' line of remailed messages."
       +  readln "Anon long name:" "Anonymous"
       +  RAN=$ans
       + fi
       +
       + readln "A short name to appear in lists:" `echo $HOSTNAME|sed 's/\..*//'`
       + SN=$ans
       +
       + readln "Accept Mixmaster (Type II) messages?" y
       + mix=$ans
       +
       + readln "Accept PGP (Type I) remailer messages?" n
       + pgp=$ans
       +
       + unencrypted=n
       + if [ "$pgp" = "y" ]
       + then
       +  readln "Accept unencrypted remailer messages?" n
       +  unencrypted=$ans
       + fi
       +
       + echo "Mixmaster will log error messages and warnings. Do you want to log"
       + readln "informational messages about normal operation as well?" y
       + if [ "$ans" = y ]
       + then
       +  verbose=2
       + else
       +  verbose=1
       + fi
       +
       + readln "Filter binary attachments?" n
       + binfilter=$ans
       +
       + if [ "$middle" = n ]
       + then
       +  if [ "$autoreply" = y ]
       +  then
       +   readln "Allow users to add themselves to the list of blocked addresses?" y
       +   autoblock=$ans
       +  fi
       +
       +  echo "Do you want to allow posting? Newsgroups can be restricted in dest.blk.
       +y)es, post locally; use m)ail-to-news gateway; n)o."
       +  readln "Allow posting to Usenet?" m
       +  post="$ans"
       +  if [ "$ans" = y ]
       +  then
       +   whereis inews /usr/lib/news/inews
       +   readln "News posting software:" "$found -h"
       +   news=$ans
       +   readln "Organization line for anonymous Usenet posts:" "Anonymous Posting Service"
       +   orga=$ans
       +   readln "Use anti-spam message IDs?" y
       +   mid=$ans
       +  elif [ "$ans" = m ]
       +  then
       +   readln "Mail-to-news gateway:" mail2news@nym.alias.net
       +   news=$ans
       +  fi
       + fi
       +
       +# Commented the poolsize question out, since poolsize is the least
       +# important of the three pool parameters.
       +#
       +# echo "How many messages do you want to keep in the reordering pool?
       +#A larger pool is more secure, but also causes higher latency.
       +#0 means to remail immediately."
       +# readln "Pool size:" 45
       +# poolsize=$ans
       +
       + mbox=
       + if [ -f ~/.forward ]
       + then
       +  mbox=`head -1 ~/.forward | sed 's/^"//;s/"$//'`
       +  if echo "$mbox" | grep 'mix' >/dev/null 2>/dev/null
       +  then
       +   mbox=
       +  elif echo "$mbox" | grep 'procmail' >/dev/null 2>/dev/null
       +  then
       +   if grep mix ~/.procmailrc >/dev/null 2>/dev/null
       +   then
       +    mbox=
       +   fi
       +  fi
       + fi
       +
       + if [ "$mbox" = "" ]
       + then
       +  mbox=${MAIL:-/usr/spool/mail/$NAME}
       +  touch "$mbox"
       +  if [ ! -w "$mbox" ]
       +  then
       +   echo "$mbox is not writeable."
       +   readln "Mailbox for non-remailer messages:" "${MIXDEST}/mbox"
       +   mbox=$ans
       +  fi
       + fi
       +
       + cat <<END >mix.cfg
       +# mix.cfg -- installed $Date
       +SENDMAIL        $sendmail -t
       +
       +# Where to store non-remailer messages:
       +MAILBOX                $mbox
       +#MAILABUSE        mbox.abuse
       +#MAILBLOCK        mbox.block
       +#MAILUSAGE        mbox.usage
       +#MAILANON        mbox.anon
       +#MAILERROR        mbox.error
       +#MAILBOUNCE        mbox.bounce
       +
       +REMAIL                y
       +MIDDLEMAN        $middle
       +
       +BINFILTER        $binfilter
       +AUTOBLOCK        $autoblock
       +
       +ERRLOG          error.log
       +VERBOSE                $verbose
       +
       +# Remailer name and addresses
       +REMAILERADDR        $RMA
       +ANONADDR        $RAA
       +COMPLAINTS        $CA
       +
       +SHORTNAME        $SN
       +REMAILERNAME        $RMN
       +ANONNAME        $RAN
       +
       +# Supported formats:
       +MIX             $mix
       +PGP             $pgp
       +UNENCRYPTED     $unencrypted
       +
       +# Maximum message size in kB (0 for no limit):
       +SIZELIMIT       0
       +
       +# Usenet news:
       +NEWS                $news
       +ORGANIZATION        $orga
       +MID                $mid
       +
       +# Remailing strategy:
       +SENDPOOLTIME    15m
       +POOLSIZE        45
       +RATE            65
       +INDUMMYP        10
       +OUTDUMMYP       90
       +CHAIN           *,*,*,*
       +IDEXP           7d
       +PACKETEXP       7d
       +
       +$PASSPHRASE
       +
       +END
       +
       +fi # not yet installed
       +
       +
       +REPLACE="s/%RMN/$RMN/g;s/%RMA/$RMA/g;s/%CA/$CA/g;s/%RAA/$RAA/g"
       +if [ "$installed" = "n" ]
       +then
       + cd "$MIXCFG"
       + if [ ! -f "$MIXDEST/help.txt" ]
       + then
       +  sed "$REPLACE" < intro.hlp >"$MIXDEST/help.txt"
       +  if [ "$mix" = y ]
       +  then
       +   sed "$REPLACE" < mix.hlp >>"$MIXDEST/help.txt"
       +  fi
       +  if [ "$unencrypted" = y ]
       +  then
       +   sed "$REPLACE" < type1.hlp >>"$MIXDEST/help.txt"
       +   if [ "$pgp" = y ]
       +   then
       +    sed "$REPLACE" < pgp.hlp >>"$MIXDEST/help.txt"
       +   fi
       +  elif [ "$pgp" = y ]
       +  then
       +   sed "$REPLACE" < pgponly.hlp >>"$MIXDEST/help.txt"
       +  fi
       +  if [ "$post" = y ]
       +  then
       +   if [ "$pgp" = y -o "$unencrypted" = y ]
       +   then
       +    sed "$REPLACE" < news.hlp >>"$MIXDEST/help.txt"
       +   fi
       +  fi
       +  sed "$REPLACE" < end.hlp >>"$MIXDEST/help.txt"
       + fi
       +
       + for i in *.txt.in
       + do
       +  j=`echo $i | sed 's/\.in$//'`
       +  if [ ! -f "$MIXDEST/$j" ]
       +  then
       +    sed "$REPLACE" < "$i" >"$MIXDEST/$j"
       +  fi
       + done
       + cd "$MIXDEST"
       +fi
       +
       +echo
       +if [ ! -f secring.mix ]
       +then
       + echo "Generating secret keys. This may take a while..."
       +else
       + echo "Updating secret keys..."
       +fi
       +./mixmaster -K
       +if [ -f key.txt ]
       +then
       + echo "Done."
       + echo
       +else
       + echo "Installation failed. Please consult the Mixmaster documentation."
       + exit 1
       +fi
       +
       +if [ "$system" = msdos -o "$system" = win32 ]
       +then
       + exit
       +fi
       +
       +umask 033
       +
       +# Set .forward?
       +# 
       +set=y
       +# FIXME -- Mixmastger should run in daemon mode, not from procmail
       +# Make the Install script do that.
       +
       +if grep procmail ~/.forward >/dev/null 2>/dev/null
       +then
       + if grep mix ~/.procmailrc >/dev/null 2>/dev/null
       + then
       +  echo "Mixmaster is installed in your .procmailrc file."
       +  set=n
       + fi
       +fi
       +
       +if [ "$set" = y -a -f ~/.forward ]
       +then
       + echo "Your current .forward is:"
       + cat ~/.forward
       + echo
       + if grep mix ~/.forward >/dev/null 2>/dev/null
       + then
       +  echo "Mixmaster already is installed in your .forward file."
       +  set=n
       + elif [ "$mbox" != "" ]
       + then
       +  if echo "$mbox" | grep '|' >/dev/null 2>/dev/null
       +  then
       +   echo "Mixmaster will pipe messages to $mbox"
       +  elif echo $mbox | grep '@' >/dev/null 2>/dev/null
       +  then
       +   echo "Mixmaster will forward messages to $mbox"
       +  else
       +   echo "Mixmaster will store messages to $mbox"
       +  fi
       + fi
       +fi
       +
       +if [ "$set" = y ]
       +then
       + echo "Set .forward to the following line:"
       + echo "\"|${MIXDEST}/mixmaster -RM\""
       + if [ -f ~/.forward ]
       + then
       +  readln "Overwrite now?" n
       + else
       +  readln "Do that now?" n
       + fi
       + if [ "$ans" = "y" ]
       + then
       +  echo "\"|${MIXDEST}/mixmaster -RM\"" >~/.forward
       + fi
       +fi
       +
       +#FIXME -- we need a second script that can re-generate help files
       +# when the conf changes.
       +
       +if [ "$RMA" != "" ]
       +then
       + echo "
       +Mixmaster will send the following files as auto-replies:
       +Mail to <$RMA> with Subject: remailer-help => help.txt"
       + echo "Mail to <$RMA> with Subject: remailer-adminkey => adminkey.txt
       +Remember to add your Remailer Admin public PGP key to the adminkey.txt file."
       + if [ "$autoblock" = y ]
       + then
       +  echo "Mail to <$RMA> with line DESTINATION-BLOCK => blocked.txt"
       + fi
       + if [ "$autoreply" = y ]
       + then
       +  echo "Other mail to <$RMA> => usage.txt"
       +  echo
       +  if [ "$CA" != "$RMA" ]
       +  then
       +   echo "If you arrange for mail to <$CA> and <$RAA>
       +to be forwarded to <$RMA>:
       +Mail to <$CA> => abuse.txt
       +Mail to <$RAA> => reply.txt"
       +  fi
       + fi
       +fi
       +
       +echo
       +echo "Mixmaster installation complete."
       +
   DIR diff --git a/README b/README
       t@@ -0,0 +1,191 @@
       +Mixmaster 3.0 -- anonymous remailer software -- (C) 1999 - 2000 Anonymizer Inc.
       +                                  (C) 2000-2008 The Mixmaster Development Team
       +-------------------------------------------------------------------------------
       +
       +This program consists of
       +
       +* a remailer client:
       +
       +  The remailer client supports sending anonymous mail using Cypherpunk and
       +  Mixmaster remailers. It supports OpenPGP encryption (compatible with PGP 2,
       +  PGP 5 and up, and GnuPG).
       +
       +  The client can be used with a menu-based user interface and with command line
       +  options.
       +
       +* a remailer:
       +
       +  The remailer supports the Cypherpunk and Mixmaster message formats.  It can
       +  be integrated with the mail delivery system of Unix-based computers or use
       +  the POP3 and SMTP protocols for mail transfer.  Mixmaster includes an
       +  automated abuse-handling system.
       +
       +Please report any problems via the bug and patch trackers at
       +http://sourceforge.net/projects/mixmaster/
       +
       +
       +Installation:
       +------------
       +
       +Libraries:
       +
       +  Mixmaster requires the libraries OpenSSL, zlib, and pcre. 
       +  
       +  If you want to use the menu-based user interface, you also need the ncurses
       +  library. If these libraries are not installed on your system, you will need
       +  to obtain the latest versions from the sources below and extract them in the
       +  the Src/ directory first.
       +
       +  OpenSSL is available from http://www.openssl.org/source/
       +
       +  Ncurses can be obtained from http://ftp.gnu.org/pub/gnu/ncurses/
       +
       +  The Perl Compatable Regular Expressions library can be obtained from
       +  ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/
       +
       +  The zlib compression libraries can be obtained from
       +  http://www.gzip.org/zlib/
       +
       +To install or upgrade Mixmaster, type `./Install'.
       +
       +Mixmaster clients rely on pingers to compile statistics and keyrings for
       +currently operating remailers.  A list of public pingers can be obtained from
       +http://www.noreply.org/allpingers/.
       +
       +Alternatively clients can operate their own pingers to generate statistics.
       +Pinger software can be obtained from http://www.palfrader.org/echolot/.  If you
       +choose this option, please publish the pinger results for the benefit of other
       +Mixmaster users and notify the metastats maintainer at admin@mixmin.net.
       +
       +The required files published by pingers are:-
       +  pubring.asc    Type 1 remailer keys
       +  pubring.mix    Type 2 remailer keys
       +  rlist.txt      List of reliable type 1 remailers
       +  mlist.txt      List of reliable type 2 remailers
       +  type2.list     List of known type 2 remailers (optional)
       +
       +Using the remailer client:
       +-------------------------
       +
       +To use the menu-based user interface, simply run `mixmaster'. To send an
       +anonymous or pseudonymous reply to a message from within your mail or news
       +reader, you can pipe it to `mixmaster'.
       +
       +The interactive mode supports sending mail and contains a simple mail reading
       +function. OpenPGP messages are encrypted and decrypted automatically. 
       +
       +In the non-interactive mode, Mixmaster reads a message from a file or from its
       +standard input. The command line options are described in the manual page
       +(mixmaster.1).
       +
       +
       +Mixmaster as a remailer:
       +-----------------------
       +
       +The Mixmaster remailer can be installed on any account that can receive mail.
       +Non-remailer messages will be delivered as usual. If you have root access, you
       +may want to create a new user (e.g., `remailer') and install Mixmaster under
       +that user id.
       +
       +The Install script provides a simple way to set up the remailer. More
       +information about configuring Mixmaster can be found in the manual page.
       +Typically, incoming mail is piped to "mixmaster -RM". In a UUCP setting, it may
       +be useful to use just "mixmaster -R", and run "mixmaster -S" once all messages
       +have arrived.
       +
       +Announcing a new remailer to the public is most commonly done by posting the
       +remailer keys and capabilities to alt.privacy.anon-server as well as the
       +"remops" mailing list. Information about the remops list can be found here:
       +http://lists.mixmin.net/mailman/listinfo/remops
       +
       +
       +Installation problems:
       +---------------------
       +
       +In case one of the libraries Mixmaster uses is installed incorrectly on your
       +system, place the library source code (available from the locations listed
       +above) in the Src directory, remove the old Makefile, run the Install script
       +again and answer `y' when asked whether to use the source code.
       +
       +The ncurses library can use termcap and terminfo databases. The Mixmaster
       +Install script tries to find out whether terminfo is available. If you get a
       +"Can't open display" error when starting the Mixmaster menu, run "./configure
       +--enable-termcap; make lib/libncurses.a" in the ncurses directory.
       +
       +
       +Security notes:
       +--------------
       +
       +The ciphers and the anonymizing mix-net protocol used in Mixmaster correspond
       +to the state of the art (see the Security Considerations section of the
       +Mixmaster Protocol specification for details). However, no security proofs
       +exist for any practical cryptosystem. It is unlikely that their security will
       +be broken, but there is no "perfect security". Software can also contain
       +implementation errors. The complete Mixmaster source code is available for
       +public review, so that everyone can verify what the program does, and it is
       +unlikely that security related errors or secret back doors in the software
       +would go unnoticed.
       +
       +No software is secure if run in an insecure environment. For that reason you
       +must make sure that there is no malicious software (such as viruses) running on
       +your computer. Deleted files and even passphrases can in many cases be read
       +from the hard disk if an adversary has access to the computer. The use of disk
       +encryption programs is recommended to avoid this risk.
       +
       +Anonymous messages are secure as long as at least one of the remailers you use
       +in a chain is honest. You can use up to 20 remailers in a chain, but
       +reliability and speed decrease with longer chains. Four is a reasonable number
       +of remailers to use. Many remailer operators sign their keys. You should verify
       +those signatures with OpenPGP to make sure that you have the actual remailer
       +keys.
       +
       +Anonymous keys usually cannot be introduced to the OpenPGP web of trust without
       +giving up anonymity. For that reason, this client will use any OpenPGP key
       +found on the key ring, whether it is certified or not. Your key ring must not
       +contain any invalid keys when used with this program.
       +
       +If you want to use a pseudonym, the client will ask you for a passphrase to
       +protect the nym database. Your passphrase should be long, and hard to guess.
       +Anyone who gets hold of your nym database and private keys and can determine
       +the passphrase will be able to compromise your pseudonymous identities. Note
       +that some operating systems may store your passphrase on your hard disk in
       +clear.
       +
       +While a good client passphrase can protect your keys if someone gets hold of
       +your files, the remailer passphrase offers only casual protection for the
       +remailer keys. If you install a remailer, the remailer passphrase must be
       +different from your private passphrases.
       +
       +Note that nym.alias.net style nym-servers are trivially breakable by an
       +adversary performing a long-term intersection attack. Discussion of 
       +these attacks can be found in section 4.2 of The Pynchon Gate, by 
       +Sassaman, Cohen, and Mathewson, 2005. Use of Type I remailers for any 
       +purpose is discouraged.
       +
       +
       +Copyright:
       +---------
       +
       +Mixmaster may be redistributed and modified under certain conditions.  This
       +software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
       +either express or implied. See the file COPYRIGHT for details.
       +
       +A license is required to use the IDEA(TM) algorithm for commercial purposes;
       +see the file idea.txt for details.
       +
       +Mixmaster uses the compression library zlib by Jean-loup Gailly and Mark Adler,
       +the free ncurses library and the regex library by Philip Hazel.  This product
       +includes cryptographic software written by Eric Young (eay@cryptsoft.com). This
       +product includes software developed by the OpenSSL Project for use in the
       +OpenSSL Toolkit (http://www.OpenSSL.org/).  For some platforms: This product
       +includes software developed by the University of California, Berkeley and its
       +contributors.
       +
       +Additionally, this software uses code provided by the members of the 
       +Mixmaster development team. The members respectively hold the copyright 
       +to the code in question, having elected to make it available under the 
       +Mixmaster license.
       +
       +All trademarks are the property of their respective owners.
       +
       +$Id: README 974 2008-03-03 17:40:11Z rabbi $
   DIR diff --git a/Src/Makefile.deps b/Src/Makefile.deps
       t@@ -0,0 +1,46 @@
       +# Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +# Mixmaster may be redistributed and modified under certain conditions.
       +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +# ANY KIND, either express or implied. See the file COPYRIGHT for
       +# details.
       +
       +# $Id: $
       +
       +buffers.o: mix3.h config.h version.h mix.h
       +chain.o: mix3.h config.h version.h mix.h
       +chain1.o: mix3.h config.h version.h mix.h pgp.h
       +chain2.o: mix3.h config.h version.h mix.h
       +chain3.o: mix3.h config.h version.h mix.h
       +compress.o: mix3.h config.h version.h mix.h
       +crypto.o: mix3.h config.h version.h mix.h crypto.h
       +dllmain.o: mix3.h config.h version.h mix.h
       +dummy.o: mix3.h config.h version.h mix.h
       +keymgt.o: mix3.h config.h version.h mix.h
       +mail.o: mix3.h config.h version.h mix.h
       +maildir.o: mix3.h config.h version.h mix.h
       +main.o: mix3.h config.h version.h mix.h
       +menu.o: menu.h mix3.h config.h version.h mix.h
       +menunym.o: menu.h mix3.h config.h version.h mix.h
       +menusend.o: menu.h mix3.h config.h version.h mix.h
       +menuutil.o: menu.h mix3.h config.h version.h mix.h
       +mime.o: mix3.h config.h version.h mix.h
       +mix.o: mix3.h config.h version.h mix.h menu.h
       +nym.o: mix3.h config.h version.h mix.h pgp.h
       +pgp.o: mix3.h config.h version.h mix.h pgp.h
       +pgpcreat.o: mix3.h config.h version.h mix.h pgp.h crypto.h
       +pgpdata.o: mix3.h config.h version.h mix.h pgp.h crypto.h
       +pgpdb.o: mix3.h config.h version.h mix.h pgp.h
       +pgpget.o: mix3.h config.h version.h mix.h pgp.h crypto.h
       +mpgp.o: mix3.h config.h version.h mix.h pgp.h
       +pool.o: mix3.h config.h version.h mix.h
       +random.o: mix3.h config.h version.h mix.h crypto.h
       +rem.o: mix3.h config.h version.h mix.h
       +rem1.o: mix3.h config.h version.h mix.h
       +rem2.o: mix3.h config.h version.h mix.h
       +rem3.o: mix3.h config.h version.h mix.h
       +remailer.o: mix.h
       +rfc822.o: mix3.h config.h version.h mix.h
       +rndseed.o: mix3.h config.h version.h mix.h
       +stats.o: mix3.h config.h version.h mix.h
       +util.o: mix3.h config.h version.h mix.h
   DIR diff --git a/Src/Makefile.in b/Src/Makefile.in
       t@@ -0,0 +1,83 @@
       +# Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +# Mixmaster may be redistributed and modified under certain conditions.
       +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +# ANY KIND, either express or implied. See the file COPYRIGHT for
       +# details.
       +
       +# $Id: Makefile.in 647 2003-10-25 23:34:13Z weasel $
       +
       +# Edit according to the libraries you want to use:
       +INC = %INC
       +DEF = %DEF -DUSE_SOCK %MIXDIR
       +LIBS = %LIBS
       +LDFLAGS = %LDFLAGS
       +
       +OPT = -g -Wall
       +# OPT = -g -pg -Wall -DDEBUG
       +# OPT = -O2 -Wall
       +
       +CFLAGS = $(INC) $(DEF) $(OPT)
       +CC = gcc
       +AR = ar rc
       +RANLIB = ranlib
       +#MAKE = make
       +
       +OBJ = mix.o rem.o rem1.o rem2.o chain.o chain1.o chain2.o nym.o pgp.o pgpdb.o pgpdata.o pgpget.o pgpcreat.o pool.o mail.o rfc822.o mime.o keymgt.o compress.o stats.o crypto.o random.o util.o buffers.o maildir.o parsedate.tab.o
       +
       +MIXOBJ = rndseed.o menu.o menusend.o menunym.o menuutil.o menustats.o
       +NOMENUOBJ = rndseed.o dummy.o
       +WINOBJ = winmain.o winutil.o
       +
       +all:        mixmaster
       +
       +mixmaster: $(OBJ) $(MIXOBJ) main.o $(LIBS)
       +        $(CC) $(OBJ) $(MIXOBJ) main.o $(LIBS) $(LDFLAGS) -o mixmaster
       +
       +libmix.a: $(OBJ) $(MIXOBJ) dllmain.o
       +        $(AR) libmix.a $(OBJ) $(MIXOBJ) dllmain.o
       +
       +libmix32.a: libmix.a mixlib.def
       +        dllwrap --dllname mixlib.dll --def mixlib.def --output-lib libmix32.a libmix.a zlib-1.1.4/libz.a pcre-2.08/libpcre.a openssl/libeay32.a -lwsock32
       +
       +dllmix: main.o libmix32.a
       +        $(CC) main.o libmix32.a -o dllmix
       +
       +winmix.exe:        $(WINOBJ) libmix32.a
       +        $(CC) $(WINOBJ) libmix32.a -lgdi32 -luser32 $(LDFLAGS) -o mixmaster.exe
       +
       +winmix: winmenu.res #winmix.exe
       +        rsrc winmenu.res mixmaster.exe
       +
       +winmenu.o:        winmenu.rc winmenu.h
       +        windres winmenu.rc winmenu.o
       +
       +remailer:        $(OBJ) $(NOMENUOBJ) remailer.o $(LIBS)
       +        $(CC) $(OBJ) $(NOMENUOBJ) remailer.o $(LIBS) $(LDFLAGS) -o remailer
       +
       +mpgp:        $(OBJ) $(NOMENUOBJ) mpgp.o $(LIBS)
       +        $(CC) $(OBJ) $(NOMENUOBJ) mpgp.o $(LIBS) $(LDFLAGS) -o mpgp
       +
       +test:        $(OBJ) test.o $(NOMENUOBJ) $(LIBS)
       +        $(CC) $(OBJ) test.o $(NOMENUOBJ) $(LIBS) $(LDFLAGS) -o test
       +
       +clean:
       +        -rm -f *.o *.a *.res *~ mixmaster mix *.exe remailer test mpgp core gmon.out
       +
       +allclean: clean
       +        -rm -f Makefile
       +
       +distclean:        allclean
       +
       +ci: clean
       +        cd ~/src/mix3; ci -l * Mix/* Mix/Src/*; echo
       +
       +parsedate.tab.c: parsedate.y
       +        @echo Expect 6 shift/reduce conflicts
       +        bison parsedate.y
       +
       +parsedate: parsedate.tab.c
       +        gcc -DTEST parsedate.tab.c -o parsedate
       +
       +
       +include Makefile.deps
   DIR diff --git a/Src/buffers.c b/Src/buffers.c
       t@@ -0,0 +1,816 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Dynamically allocated buffers
       +   $Id: buffers.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +#include <ctype.h>
       +#include <stdarg.h>
       +#ifdef WIN32
       +#include <io.h>
       +#endif /* WIN32 */
       +#include <assert.h>
       +#ifdef POSIX
       +#include <unistd.h>
       +#endif /* POSIX */
       +
       +static void fail(void)
       +{
       +  errlog(ERRORMSG, "Out of memory!\n");
       +  abort();
       +}
       +
       +#define space 128                /* allocate some additional space */
       +
       +static void alloc(BUFFER *b)
       +{
       +  b->data = malloc(space);
       +  if (b->data == NULL)
       +    fail();
       +  b->data[0] = 0;
       +  b->size = space;
       +}
       +
       +#undef buf_new /* DEBUG */
       +BUFFER *buf_new(void)
       +{
       +  BUFFER *b;
       +
       +  b = malloc(sizeof(BUFFER));
       +  if (b == NULL)
       +    fail();
       +  alloc(b);
       +  b->length = 0;
       +  b->ptr = 0;
       +  b->sensitive = 0;
       +
       +  return (b);
       +}
       +
       +#ifdef DEBUG
       +static void sanity_check(BUFFER *b)
       +{
       +  assert(b != NULL);
       +  assert(b->size > 0);
       +  assert(b->data != NULL);
       +  assert(b->length >= 0 && b->length < b->size);
       +  assert(b->ptr >= 0 && b->ptr <= b->length);
       +}
       +#else /* not DEBUG */
       +#define sanity_check(arg)
       +#endif /* else not DEBUG */
       +
       +int buf_reset(BUFFER *buffer)
       +{
       +  sanity_check(buffer);
       +
       +  buffer->length = 0;
       +  buffer->ptr = 0;
       +  if (buffer->sensitive)
       +    memset(buffer->data, 0, buffer->size);
       +  free(buffer->data);
       +  alloc(buffer);
       +  return (0);
       +}
       +
       +int buf_free(BUFFER *buffer)
       +{
       +  int err = 0;
       +
       +  if (buffer->sensitive)
       +    memset(buffer->data, 0, buffer->size);
       +  free(buffer->data);
       +  free(buffer);
       +  return (err);
       +}
       +
       +int buf_clear(BUFFER *buffer)
       +{
       +  sanity_check(buffer);
       +  buffer->data[0] = '\0';
       +  buffer->length = 0;
       +  buffer->ptr = 0;
       +  return (0);
       +}
       +
       +int buf_append(BUFFER *buffer, byte *msg, int len)
       +{
       +  assert(len >= 0);
       +  sanity_check(buffer);
       +
       +  if (buffer->length + len >= buffer->size) {
       +    register byte *new;
       +    register long newsize;
       +
       +    newsize = 2 * buffer->length;        /* double buffer size */
       +    if (newsize < buffer->length + len + space)
       +      newsize = buffer->length + len + space;
       +    new = malloc(newsize);
       +    if (new == NULL)
       +      fail();
       +    memcpy(new, buffer->data, buffer->length);
       +    if (buffer->sensitive)
       +      memset(buffer->data, 0, buffer->size);
       +    free(buffer->data);
       +    buffer->data = new;
       +    buffer->size = newsize;
       +  }
       +  if (msg != NULL)
       +    memcpy(buffer->data + buffer->length, msg, len);
       +  buffer->length += len;
       +
       +  buffer->data[buffer->length] = 0;
       +  return (0);
       +}
       +
       +int buf_appendrnd(BUFFER *to, int n)
       +{
       +  buf_append(to, NULL, n);
       +  rnd_bytes(to->data + to->length - n, n);
       +  return (0);
       +}
       +
       +int buf_appendzero(BUFFER *to, int n)
       +{
       +  buf_append(to, NULL, n);
       +  memset(to->data + to->length - n, 0, n);
       +  return (0);
       +}
       +
       +int buf_setrnd(BUFFER *b, int n)
       +{
       +  buf_prepare(b, n);
       +  rnd_bytes(b->data, n);
       +  return (0);
       +}
       +
       +int buf_cat(BUFFER *to, BUFFER *from)
       +{
       +  return (buf_append(to, from->data, from->length));
       +}
       +
       +int buf_set(BUFFER *to, BUFFER *from)
       +{
       +  buf_reset(to);
       +  return (buf_cat(to, from));
       +}
       +
       +int buf_appendc(BUFFER *to, byte b)
       +{
       +  return (buf_append(to, &b, 1));
       +}
       +
       +int buf_rest(BUFFER *to, BUFFER *from)
       +{
       +  assert(from != to);
       +  return (buf_append(to, from->data + from->ptr, from->length - from->ptr));
       +}
       +
       +int buf_appends(BUFFER *buffer, char *s)
       +{
       +  return (buf_append(buffer, s, strlen(s)));
       +}
       +
       +int buf_sets(BUFFER *buffer, char *s)
       +{
       +  buf_clear(buffer);
       +  return (buf_appends(buffer, s));
       +}
       +
       +int buf_setc(BUFFER *buffer, byte c)
       +{
       +  buf_clear(buffer);
       +  return (buf_appendc(buffer, c));
       +}
       +
       +int buf_nl(BUFFER *b)
       +{
       +  return (buf_append(b, "\n", 1));
       +}
       +
       +int buf_vappendf(BUFFER *b, char *fmt, va_list args)
       +{
       +  for (; *fmt != '\0'; fmt++)
       +    if (*fmt == '%') {
       +      int lzero = 0;
       +      int longvar = 0;
       +      int len = 0;
       +
       +      for (;;) {
       +        if (*++fmt == '\0')
       +          return (-1);
       +        if (*fmt == '%') {
       +          buf_appendc(b, '%');
       +          break;
       +        } else if (*fmt == 'b') {        /* extension of printf */
       +          buf_cat(b, va_arg(args, BUFFER *));
       +
       +          break;
       +        } else if (*fmt == 'c') {
       +          buf_appendc(b, va_arg(args, int));
       +
       +          break;
       +        } else if (*fmt == 's') {
       +          buf_appends(b, va_arg(args, char *));
       +
       +          break;
       +        } else if (*fmt == 'd' || *fmt == 'X') {
       +          int base, val, sign = 0;
       +          BUFFER *out;
       +
       +          out = buf_new();
       +          base = *fmt == 'd' ? 10 : 16;
       +          if (longvar)
       +            val = va_arg(args, long);
       +
       +          else
       +            val = va_arg(args, int);
       +
       +          if (val < 0)
       +            sign = 1, val = -val;
       +          do {
       +            if (val % base > 9)
       +              buf_appendc(out, val % base - 10 + 'A');
       +            else
       +              buf_appendc(out, val % base + '0');
       +            val /= base;
       +          } while (val > 0);
       +          if (sign)
       +            len--;
       +          while (len-- > out->length)
       +            buf_appendc(b, lzero ? '0' : ' ');
       +          if (sign)
       +            buf_appendc(b, '-');
       +          for (len = out->length - 1; len >= 0; len--)
       +            buf_appendc(b, out->data[len]);
       +          buf_free(out);
       +          break;
       +        } else if (*fmt == 'l')
       +          longvar = 1;
       +        else if (*fmt == '0' && len == 0)
       +          lzero = 1;
       +        else if (isdigit(*fmt))
       +          len = len * 10 + *fmt - '0';
       +        else
       +          assert(0);
       +      }
       +    } else
       +      buf_appendc(b, *fmt);
       +  return (0);
       +}
       +
       +int buf_setf(BUFFER *b, char *fmt, ...)
       +{
       +  va_list args;
       +  int ret;
       +
       +  va_start(args, fmt);
       +  buf_clear(b);
       +  ret = buf_vappendf(b, fmt, args);
       +  va_end(args);
       +  return (ret);
       +}
       +
       +int buf_appendf(BUFFER *b, char *fmt, ...)
       +{
       +  va_list args;
       +  int ret;
       +
       +  va_start(args, fmt);
       +  ret = buf_vappendf(b, fmt, args);
       +  va_end(args);
       +  return (ret);
       +}
       +
       +int buf_pad(BUFFER *buffer, int size)
       +{
       +  assert(size - buffer->length >= 0);
       +  buf_appendrnd(buffer, size - buffer->length);
       +  return (0);
       +}
       +
       +int buf_prepare(BUFFER *buffer, int size)
       +{
       +  buf_clear(buffer);
       +  buf_append(buffer, NULL, size);
       +  return (0);
       +}
       +
       +int buf_read(BUFFER *outmsg, FILE *infile)
       +{
       +  char buf[BUFSIZE];
       +  int n;
       +  int err = -1;
       +
       +  assert(infile != NULL);
       +  sanity_check(outmsg);
       +
       +  for (;;) {
       +    n = fread(buf, 1, BUFSIZE, infile);
       +    if (n > 0)
       +      err = 0;
       +    buf_append(outmsg, buf, n);
       +    if (n < BUFSIZE)
       +      break;
       +#ifdef BUFFER_MAX
       +    if (outmsg->length > BUFFER_MAX) {
       +      errlog(ERRORMSG, "Message file too large. Giving up.\n");
       +      return (1);
       +    }
       +#endif /* BUFFER_MAX */
       +  }
       +
       +#ifdef WIN32
       +  if (isatty(fileno(infile)) && isatty(fileno(stdout)))
       +    printf("\n");
       +#endif /* WIN32 */
       +
       +  return (err);
       +}
       +
       +int buf_write(BUFFER *buffer, FILE *out)
       +{
       +  assert(out != NULL);
       +  sanity_check(buffer);
       +
       +  return (fwrite(buffer->data, 1, buffer->length, out) == buffer->length
       +          ? 0 : -1);
       +}
       +
       +int buf_write_sync(BUFFER *buffer, FILE *out)
       +{
       +    int ret = 0;
       +
       +    if (buf_write(buffer, out) == -1) {
       +      fclose(out);
       +      return -1;
       +    }
       +
       +    if (fflush(out) != 0)
       +      ret = -1;
       +
       +#ifdef POSIX
       +    /* dir entry not synced */
       +    if (fsync(fileno(out)) != 0)
       +      ret = -1;
       +#endif /* POSIX */
       +
       +    if (fclose(out) != 0)
       +      ret = -1;
       +
       +    return ret;
       +}
       +
       +int buf_rewind(BUFFER *buffer)
       +{
       +  sanity_check(buffer);
       +
       +  buffer->ptr = 0;
       +  return (0);
       +}
       +
       +int buf_get(BUFFER *buffer, BUFFER *to, int n)
       +{
       +  sanity_check(buffer);
       +  sanity_check(to);
       +  assert(n > 0);
       +  assert(buffer != to);
       +
       +  buf_clear(to);
       +  if (buffer->length - buffer->ptr < n)
       +    return (-1);
       +  buf_append(to, buffer->data + buffer->ptr, n);
       +  buffer->ptr += n;
       +  return (0);
       +}
       +
       +int buf_getc(BUFFER *buffer)
       +{
       +  sanity_check(buffer);
       +  if (buffer->ptr == buffer->length)
       +    return (-1);
       +  else
       +    return (buffer->data[buffer->ptr++]);
       +}
       +
       +void buf_ungetc(BUFFER *buffer)
       +{
       +  sanity_check(buffer);
       +  if (buffer->ptr > 0)
       +    buffer->ptr--;
       +}
       +
       +int buf_getline(BUFFER *buffer, BUFFER *line)
       +{
       +  register int i;
       +  int ret = 0;
       +  int nl = 0;
       +
       +  sanity_check(buffer);
       +
       +  if (line != NULL)
       +    buf_clear(line);
       +  if (buffer->ptr == buffer->length)
       +    return (-1);
       +
       +  for (i = buffer->ptr; i < buffer->length; i++) {
       +    if (buffer->data[i] > '\r')
       +      continue;
       +    if (buffer->data[i] == '\0' || buffer->data[i] == '\n') {
       +      nl = 1;
       +      break;
       +    }
       +    if (buffer->data[i] == '\r' &&
       +        i + 1 <= buffer->length && buffer->data[i + 1] == '\n') {
       +      nl = 2;
       +      break;
       +    }
       +  }
       +
       +  if (line != NULL)
       +    buf_append(line, buffer->data + buffer->ptr, i - buffer->ptr);
       +  if (i == buffer->ptr)
       +    ret = 1;
       +  buffer->ptr = i + nl;
       +
       +  return (ret);
       +}
       +
       +int buf_chop(BUFFER *b)
       +{
       +  int i;
       +
       +  sanity_check(b);
       +
       +  for (i = 0; i < b->length; i++)
       +    if (b->data[i] == '\0' || b->data[i] == '\n' ||
       +        (b->data[i] == '\r' && i + 1 < b->length &&
       +         b->data[i + 1] == '\n'))
       +      b->length = i;
       +  b->data[b->length] = 0;
       +  return (0);
       +}
       +
       +int buf_isheader(BUFFER *buffer)
       +{
       +  BUFFER *line;
       +  long p;
       +  int i;
       +  int err;
       +  int ret;
       +
       +  line = buf_new();
       +  p = buffer->ptr;
       +  ret = 0;
       +  err = buf_getline(buffer, line);
       +  if (err != 0)
       +    goto end;
       +
       +  for (i = 0; i < line->length; i++) {
       +    if (line->data[i] == ' ' || line->data[i] == '\t')
       +      break;
       +    if (line->data[i] == ':') {
       +      ret = 1;
       +      break;
       +    }
       +  }
       +
       +end:
       +  buffer->ptr = p;
       +  buf_free(line);
       +  return(ret);
       +}
       +
       +int buf_getheader(BUFFER *buffer, BUFFER *field, BUFFER *content)
       +{
       +  BUFFER *line;
       +  long p;
       +  int i;
       +  int err;
       +
       +  line = buf_new();
       +  buf_reset(field);
       +  buf_reset(content);
       +
       +  err = buf_getline(buffer, line);
       +  if (err != 0)
       +    goto end;
       +
       +  err = -1;
       +  for (i = 0; i < line->length; i++) {
       +    if (line->data[i] == ' ' || line->data[i] == '\t')
       +      break;
       +    if (line->data[i] == ':') {
       +      err = 0;
       +      break;
       +    }
       +  }
       +  if (err == -1 && bufileft(line, "From ")) {
       +    buf_set(field, line);
       +    err = 0;
       +  }
       +  if (err == -1) {
       +    /* badly formatted message -- try to process anyway */
       +    buf_sets(field, "X-Invalid");
       +    buf_set(content, line);
       +    err = 0;
       +    goto end;
       +  }
       +  buf_append(field, line->data, i);
       +  if (i < line->length)
       +    i++;
       +  else
       +    err = 1;
       +  while (i < line->length &&
       +         (line->data[i] == ' ' || line->data[i] == '\t'))
       +    i++;
       +  buf_append(content, line->data + i, line->length - i);
       +
       +  for (;;) {
       +    p = buffer->ptr;
       +    if (buf_getline(buffer, line) != 0)
       +      break;
       +    if (line->data[0] != ' ' && line->data[0] != '\t')
       +      break;
       +#if 1
       +    buf_nl(content);
       +    buf_cat(content, line);
       +#else /* end of 1 */
       +    buf_appendc(content, ' ');
       +    buf_appends(content, line->data + 1);
       +#endif /* else if not 1 */
       +  }
       +  buffer->ptr = p;
       +end:
       +  buf_free(line);
       +  return (err);
       +}
       +
       +int buf_appendheader(BUFFER *buffer, BUFFER *field, BUFFER *content)
       +{
       +  return buf_appendf(buffer, "%b: %b\n", field, content);
       +}
       +
       +int buf_lookahead(BUFFER *buffer, BUFFER *line)
       +{
       +  long p;
       +  int e;
       +
       +  p = buffer->ptr;
       +  e = buf_getline(buffer, line);
       +  buffer->ptr = p;
       +  return (e);
       +}
       +
       +int buf_eq(BUFFER *b1, BUFFER *b2)
       +{
       +  sanity_check(b1);
       +  sanity_check(b2);
       +
       +  if (b1->length != b2->length)
       +    return (0);
       +  if (b1->length > 0 && memcmp(b1->data, b2->data, b1->length) != 0)
       +    return (0);
       +  return (1);
       +}
       +
       +int buf_ieq(BUFFER *b1, BUFFER *b2)
       +{
       +  int i;
       +  sanity_check(b1);
       +  sanity_check(b2);
       +
       +  if (b1->length != b2->length)
       +    return (0);
       +  for (i = 0; i < b1->length; i++)
       +    if (tolower(b1->data[i]) != tolower(b2->data[i]))
       +      return (0);
       +  return (1);
       +}
       +
       +void buf_move(BUFFER *dest, BUFFER *src)
       +     /* equivalent to buf_set(dest, src); buf_reset(src); */
       +{
       +  BUFFER temp;
       +  sanity_check(src);
       +  buf_reset(dest);
       +  temp.data = dest->data, temp.size = dest->size;
       +  dest->data = src->data, dest->size = src->size, dest->length = src->length;
       +  src->data = temp.data, src->size = temp.size, src->length = 0;
       +  dest->ptr = 0, src->ptr = 0;
       +}
       +
       +int buf_appendl(BUFFER *b, long l)
       +{
       +  buf_appendc(b, (l >> 24) & 255);
       +  buf_appendc(b, (l >> 16) & 255);
       +  buf_appendc(b, (l >> 8) & 255);
       +  buf_appendc(b, l & 255);
       +  return (0);
       +}
       +
       +int buf_appendl_lo(BUFFER *b, long l)
       +{
       +  buf_appendc(b, l & 255);
       +  buf_appendc(b, (l >> 8) & 255);
       +  buf_appendc(b, (l >> 16) & 255);
       +  buf_appendc(b, (l >> 24) & 255);
       +  return (0);
       +}
       +
       +long buf_getl(BUFFER *b)
       +{
       +  long l;
       +
       +  if (b->ptr + 4 > b->length)
       +    return (-1);
       +  l = buf_getc(b) << 24;
       +  l += buf_getc(b) << 16;
       +  l += buf_getc(b) << 8;
       +  l += buf_getc(b);
       +  return (l);
       +}
       +
       +long buf_getl_lo(BUFFER *b)
       +{
       +  long l;
       +
       +  if (b->ptr + 4 > b->length)
       +    return (-1);
       +  l = buf_getc(b);
       +  l += buf_getc(b) << 8;
       +  l += buf_getc(b) << 16;
       +  l += buf_getc(b) << 24;
       +
       +  return (l);
       +}
       +
       +int buf_appendi(BUFFER *b, int i)
       +{
       +  buf_appendc(b, (i >> 8) & 255);
       +  buf_appendc(b, i & 255);
       +  return (0);
       +}
       +
       +int buf_appendi_lo(BUFFER *b, int i)
       +{
       +  buf_appendc(b, i & 255);
       +  buf_appendc(b, (i >> 8) & 255);
       +  return (0);
       +}
       +
       +int buf_geti(BUFFER *b)
       +{
       +  int i;
       +
       +  if (b->ptr + 2 > b->length)
       +    return (-1);
       +  i = buf_getc(b) << 8;
       +  i += buf_getc(b);
       +  return (i);
       +}
       +
       +int buf_geti_lo(BUFFER *b)
       +{
       +  int i;
       +
       +  if (b->ptr + 2 > b->length)
       +    return (-1);
       +  i = buf_getc(b);
       +  i += buf_getc(b) << 8;
       +  return (i);
       +}
       +
       +int buf_getb(BUFFER *b, BUFFER *p)
       +{
       +  long l;
       +
       +  l = buf_getl(b);
       +  return (buf_get(b, p, l));
       +}
       +
       +int buf_appendb(BUFFER *b, BUFFER *p)
       +{
       +  long l;
       +
       +  l = p->length;
       +  buf_appendl(b, l);
       +  return (buf_cat(b, p));
       +}
       +
       +int bufleft(BUFFER *b, char *k) {
       +  return(strleft(b->data, k));
       +}
       +
       +int bufileft(BUFFER *b, char *k) {
       +  return(strileft(b->data, k));
       +}
       +
       +int buffind(BUFFER *b, char *k) {
       +  return(strfind(b->data, k));
       +}
       +
       +int bufifind(BUFFER *b, char *k) {
       +  return(strifind(b->data, k));
       +}
       +
       +int bufiright(BUFFER *b, char *k) {
       +  int l = strlen(k);
       +  if (l <= b->length)
       +    return (strieq(b->data + b->length - l, k));
       +  return(0);
       +}
       +
       +int bufeq(BUFFER *b, char *k) {
       +  return(streq(b->data, k));
       +}
       +
       +int bufieq(BUFFER *b, char *k) {
       +  return(strieq(b->data, k));
       +}
       +
       +/* void buf_cut_out(BUFFER *buffer, BUFFER *cut_out, BUFFER *rest,
       + *                  int from, int len);
       + *
       + * Cut a chunk out of the buffer.
       + *
       + * Starting with from, len bytes are cut out of buffer. The chunk
       + * of text that has been cut out is returned in cut_out, the
       + * remainings of buffer are returned in rest.
       + *
       + * This function was added by Gerd Beuster. (gb@uni-koblenz.de)
       + */
       +
       +void buf_cut_out(BUFFER *buffer, BUFFER *cut_out, BUFFER *rest,
       +                 int from, int len){
       +
       +  assert((len >= 0) && (from >= 0));
       +  assert(from+len <= buffer->length);
       +  assert(cut_out != rest);
       +
       +  buffer->ptr = 0;
       +  if(from > 0)
       +    buf_get(buffer, rest, from);
       +  buf_get(buffer, cut_out, len);
       +  buf_rest(rest, buffer);
       +}
       +
       +
       +#ifdef DEBUG
       +/* check for memory leaks */
       +#undef malloc
       +#undef free
       +void *malloc(size_t size);
       +void free(void *ptr);
       +#define max 100000
       +static int n=0;
       +static void *m[max];
       +static char *mm[max];
       +
       +void mix3_leaks(void) {
       +  int i, ok=1;
       +  for (i = 0; i < n; i++)
       +    if (m[i]) {
       +      fprintf(stderr, "Leak [%d] %s\n", i, mm[i]);
       +      ok = 0;
       +    }
       +  if (ok)
       +    fprintf(stderr, "No memory leaks.\n");
       +}
       +
       +void *mix3_malloc(size_t size) {
       +  void *ptr;
       +  if (n == 0)
       +    atexit(mix3_leaks);
       +  ptr = malloc(size);
       +  if (n >= max) abort();
       +  m[n++] = ptr;
       +  mm[n] = "?";
       +  return(ptr);
       +}
       +
       +void mix3_free(void *ptr) {
       +  int i;
       +  for (i = 0; i < n; i++)
       +    if (m[i] == ptr) {
       +      m[i] = 0;
       +      break;
       +    }
       +  free(ptr);
       +}
       +
       +BUFFER *mix3_bufnew(char *file, int line, char *func) {
       +  mm[n] = malloc(strlen(file) + strlen(func) + 15);
       +  sprintf(mm[n], "in %s %s:%d", func, file, line);
       +  return(buf_new());
       +}
       +#endif /* DEBUG */
   DIR diff --git a/Src/chain.c b/Src/chain.c
       t@@ -0,0 +1,384 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Prepare messages for remailer chain
       +   $Id: chain.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include <string.h>
       +#include <ctype.h>
       +#include <assert.h>
       +#include <stdlib.h>
       +
       +void clienterr(BUFFER *msgbuf, char *err)
       +{
       +  if (msgbuf) {
       +    buf_sets(msgbuf, "Error: ");
       +    buf_appends(msgbuf, err);
       +  } else
       +    errlog(ERRORMSG, "%s\n", err);
       +}
       +
       +void parse_badchains(int badchains[MAXREM][MAXREM], char *file, char *startindicator, REMAILER *remailer, int maxrem) {
       +  int i,j;
       +  FILE *list;
       +  char line[LINELEN];
       +
       +  if (!badchains)
       +    return;
       +
       +  for (i = 0; i < maxrem; i++ )
       +    for (j = 0; j < maxrem; j++ )
       +      badchains[i][j] = 0;
       +  list = mix_openfile(TYPE2REL, "r");
       +  if (list != NULL) {
       +    while (fgets(line, sizeof(line), list) != NULL &&
       +      !strleft(line, startindicator)) ;
       +    while (fgets(line, sizeof(line), list) != NULL &&
       +      strleft(line, "(")) {
       +      char *left, *right, *tmp;
       +      int lefti, righti;
       +
       +      left = line + 1;
       +      while (*left == ' ')
       +        left ++;
       +
       +      tmp = left + 1;
       +      while (*tmp != ' ' && *tmp != '\0' && *tmp != ')')
       +        tmp ++;
       +      if (*tmp == '\0' || *tmp == ')')
       +        /* parsing this line failed */
       +        continue;
       +      *tmp = '\0';
       +
       +      right = tmp+1;
       +      while (*right == ' ')
       +        right ++;
       +      tmp = right + 1;
       +      while (*tmp != ' ' && *tmp != '\0' && *tmp != ')')
       +        tmp ++;
       +      if (*tmp == '\0')
       +        /* parsing this line failed */
       +        continue;
       +      *tmp = '\0';
       +
       +      lefti = -1;
       +      righti = -1;
       +      for (i = 1; i < maxrem; i++) {
       +        if (strcmp(remailer[i].name, left) == 0)
       +          lefti = i;
       +        if (strcmp(remailer[i].name, right) == 0)
       +          righti = i;
       +      }
       +      if (strcmp(left, "*") == 0)
       +        lefti = 0;
       +      if (strcmp(right, "*") == 0)
       +        righti = 0;
       +
       +      if (lefti == -1 || righti == -1)
       +        /* we don't know about one or both remailers */
       +        continue;
       +      badchains[lefti][righti] = 1;
       +    }
       +    fclose(list);
       +    /* If some broken chain includes all remailers (*) mark it broken for
       +     * every single remailer - this simplifies handling in other places */
       +    for (i=1; i < maxrem; i++ ) {
       +      if (badchains[0][i])
       +        for (j=1; j < maxrem; j++ )
       +          badchains[j][i] = 1;
       +      if (badchains[i][0])
       +        for (j=1; j < maxrem; j++ )
       +          badchains[i][j] = 1;
       +    }
       +  }
       +}
       +
       +
       +int chain_select(int hop[], char *chainstr, int maxrem, REMAILER *remailer,
       +                 int type, BUFFER *feedback)
       +{
       +  int len = 0;
       +  int i, j, k;
       +  BUFFER *chain, *selected, *addr;
       +  chain = buf_new();
       +  selected = buf_new();
       +  addr = buf_new();
       +
       +  if (chainstr == NULL || chainstr[0] == '\0')
       +    buf_sets(chain, CHAIN);
       +  else
       +    buf_sets(chain, chainstr);
       +
       +  /* put the chain backwards: final hop is in hop[0] */
       +
       +  for (i = chain->length; i >= 0; i--)
       +    if (i == 0 || chain->data[i - 1] == ','
       +        || chain->data[i - 1] == ';' || chain->data[i - 1] == ':') {
       +      for (j = i; isspace(chain->data[j]);)        /* ignore whitespace */
       +        j++;
       +      if (chain->data[j] == '\0')
       +        break;
       +
       +      if (chain->data[j] == '*')
       +        k = 0;
       +#if 0
       +      else if (isdigit(chain->data[j]))
       +        k = atoi(chain->data + j);
       +#endif /* 0 */
       +      else {
       +        buf_sets(selected, chain->data + j);
       +        rfc822_addr(selected, addr);
       +        buf_clear(selected);
       +        buf_getline(addr, selected);
       +        if (!selected->length)
       +          buf_sets(selected, chain->data + j);
       +
       +        for (k = 0; k < maxrem; k++)
       +          if (((remailer[k].flags.mix && type == 0) ||
       +               (remailer[k].flags.cpunk && type == 1) ||
       +               (remailer[k].flags.newnym && type == 2)) &&
       +              (streq(remailer[k].name, selected->data) ||
       +               strieq(remailer[k].addr, selected->data) ||
       +               (selected->data[0] == '@' && strifind(remailer[k].addr,
       +                                            selected->data))))
       +            break;
       +      }
       +      if (k < 0 || k >= maxrem) {
       +        if (feedback != NULL) {
       +                buf_appendf(feedback, "No such remailer: %b", selected);
       +                buf_nl(feedback);
       +        }
       +#if 0
       +        k = 0;
       +#else /* end of 0 */
       +        len = -1;
       +        goto end;
       +#endif /* else not 0 */
       +      }
       +      hop[len++] = k;
       +      if (len >= 20) {          /* array passed in is has length 20 */
       +        if (feedback != NULL) {
       +                buf_appends(feedback, "Chain too long.\n");
       +        }
       +        break;
       +      }
       +      if (i > 0)
       +        chain->data[i - 1] = '\0';
       +    }
       +end:
       +  buf_free(chain);
       +  buf_free(selected);
       +  buf_free(addr);
       +  return len;
       +}
       +
       +int chain_randfinal(int type, REMAILER *remailer, int badchains[MAXREM][MAXREM], int maxrem, int rtype, int chain[], int chainlen, int ignore_constraints_if_necessary)
       +{
       +  int randavail;
       +  int i;
       +  int t;
       +  int select[MAXREM];
       +  int secondtolasthop = (chainlen <= 1 ? -1 : chain[1]);
       +  int constraints_ignored = 0;
       +
       +  t = rtype;
       +  if (rtype == 2)
       +    t = 1;
       +
       +start:
       +  randavail = 0;
       +  /* select a random final hop */
       +  for (i = 1; i < maxrem; i++) {
       +    select[i] = 
       +       ((remailer[i].flags.mix && rtype == 0) ||             /* remailer supports type */
       +         (remailer[i].flags.pgp && remailer[i].flags.ek && rtype == 1) ||
       +         (remailer[i].flags.newnym && rtype == 2)) &&
       +        (remailer[i].info[t].reliability >= 100 * RELFINAL || constraints_ignored ) && /* remailer has sufficient reliability */
       +        (remailer[i].info[t].latency <= MAXLAT || constraints_ignored ) &&             /* remailer has low enough latency */
       +        (remailer[i].info[t].latency >= MINLAT || constraints_ignored ) &&             /* remailer has high enough latency */
       +        (type == MSG_NULL || !remailer[i].flags.middle) &&   /* remailer is not middleman */
       +        !remailer[i].flags.star_ex &&                        /* remailer is not excluded from random selection */
       +        (remailer[i].flags.post || type != MSG_POST) &&      /* remailer supports post when this is a post */
       +        ((secondtolasthop == -1) || !badchains[secondtolasthop][i]);
       +                                     /* we only have hop or the previous one can send to this (may be random) */
       +    randavail += select[i];
       +  }
       +
       +  for (i = 1; i <= DISTANCE; i++)
       +    if (i < chainlen && select[chain[i]] && chain[i]) {
       +      select[chain[i]] = 0;
       +      randavail--;
       +    }
       +
       +  assert(randavail >= 0);
       +  if (randavail == 0) {
       +    if (ignore_constraints_if_necessary && !constraints_ignored) {
       +      errlog(WARNING, "No reliable remailers. Ignoring for randhop\n");
       +      constraints_ignored = 1;
       +      goto start;
       +    };
       +    i = -1;
       +  } else {
       +    do
       +      i = rnd_number(maxrem - 1) + 1;
       +    while (!select[i]);
       +  }
       +  return (i);
       +}
       +
       +int chain_rand(REMAILER *remailer, int badchains[MAXREM][MAXREM], int maxrem,
       +               int thischain[], int chainlen, int t, int ignore_constraints_if_necessary)
       +     /* set random chain. returns 0 if not random, 1 if random, -1 on error */
       +/* t... 0 for mixmaster Type II
       + *      1 for cypherpunk Type I
       + */
       +{
       +  int hop;
       +  int err = 0;
       +  int constraints_ignored = 0;
       +
       +  assert(t == 0 || t == 1);
       +
       +start:
       +  for (hop = 0; hop < chainlen; hop++)
       +    if (thischain[hop] == 0) {
       +      int select[MAXREM];
       +      int randavail = 0;
       +      int i;
       +
       +      err = 1;
       +      if (hop > 0)
       +        assert(thischain[hop-1]); /* we already should have chosen a remailer after this one */
       +      for (i = 1; i < maxrem; i++) {
       +        select[i] = ((remailer[i].flags.mix && t == 0) ||        /* remailer supports type */
       +                     (remailer[i].flags.pgp && remailer[i].flags.ek && t == 1)) &&
       +          (remailer[i].info[t].reliability >= 100 * MINREL || constraints_ignored ) &&  /* remailer has sufficient reliability */
       +          (remailer[i].info[t].latency <= MAXLAT || constraints_ignored ) &&            /* remailer has low enough latency */
       +          (remailer[i].info[t].latency >= MINLAT || constraints_ignored ) &&            /* remailer has high enough latency */
       +          !remailer[i].flags.star_ex &&                          /* remailer is not excluded from random selection */
       +          !badchains[i][0] && !badchains[i][thischain[hop-1]] && /* remailer can send to the next one */
       +          (hop == chainlen-1 || !badchains[thischain[hop+1]][i]);
       +                                   /* we are at the first hop or the previous one can send to this (may be random) */
       +        randavail += select[i];
       +      }
       +
       +      for (i = hop - DISTANCE; i <= hop + DISTANCE; i++)
       +        if (i >= 0 && i < chainlen && select[thischain[i]] && thischain[i]) {
       +          select[thischain[i]] = 0;
       +          randavail--;
       +        }
       +
       +
       +      assert(randavail >= 0);
       +      if (randavail < 1) {
       +        if (ignore_constraints_if_necessary && !constraints_ignored) {
       +          errlog(WARNING, "No reliable remailers. Ignoring for randhop\n");
       +          constraints_ignored = 1;
       +          goto start;
       +        };
       +        err = -1;
       +        goto end;
       +      }
       +      do
       +        thischain[hop] = rnd_number(maxrem - 1) + 1;
       +      while (!select[thischain[hop]]);
       +    }
       +end:
       +  return (err);
       +}
       +
       +int mix_encrypt(int type, BUFFER *message, char *chainstr, int numcopies,
       +                BUFFER *chainlist)
       +{
       +  return (mix2_encrypt(type, message, chainstr, numcopies, 0, chainlist));
       +}
       +
       +/* float chain_reliablity(char *chain, int chaintype,
       +                          char *reliability_string);
       + *
       + * Compute reliablity of a chain.
       + *
       + * We get the reliablity of the chain by multiplying the reliablity of
       + * every remailer in the chain. The return value is the reliablity of
       + * the chain, or a negative number if the reliablity can not be
       + * calculated. There are two reasons why may not be able to calculated
       + * the reliablity: A remailer in the chain is selected randomly, or we
       + * don't have statistics about one of the remailers in the chain.
       + * remailer_type indicates the remailer type:
       + * 0 = Mixmaster, 1 = Cypherpunk
       + *
       + * If reliability_string is non-NULL, the reliability is also returned
       + * as a string in this variable. The size of the string must be at
       + * least 9 characters!
       + *
       + * This function has been added by Gerd Beuster. (gb@uni-koblenz.de)
       + *--------------------------------------------------------------------*/
       +
       +float chain_reliability(char *chain, int chaintype,
       +                        char *reliability_string){
       +
       +  float acc_reliability = 1; /* Accumulated reliablity */
       +  char *name_start, *name_end; /* temporary pointers used
       +                                 in string scanning */
       +  char remailer_name[20]; /* The length of the array is taken from mix3.h. */
       +  int error = 0;
       +  int maxrem;
       +  int i;
       +  int previous = -1;
       +  REMAILER remailer[MAXREM];
       +  int badchains[MAXREM][MAXREM];
       +
       +  /* chaintype 0=mix 1=ek 2=newnym */
       +  assert((chaintype == 0) || (chaintype == 1));
       +  maxrem = (chaintype == 0 ? mix2_rlist(remailer, badchains) : t1_rlist(remailer, badchains));
       +
       +  /* Dissect chain */
       +  name_start = chain;
       +  name_end = chain;
       +  while(*name_end != '\0'){ /* While string not scanned completely */
       +    do /* Get next remailer */
       +      name_end+=sizeof(char);
       +    while( (*name_end != ',') && (*name_end != '\0'));
       +    strncpy(remailer_name, name_start,
       +            (name_end - name_start) / sizeof(char) + 1*sizeof(char));
       +    remailer_name[name_end-name_start]='\0';
       +    /* Lookup reliablity for remailer remailer_name */
       +    for(i=0;
       +        (i < maxrem) && (strcmp(remailer[i].name, remailer_name) != 0);
       +        i++);
       +    if(!strcmp(remailer[i].name, remailer_name)) { /* Found it! */
       +      acc_reliability *=
       +        ((float) remailer[i].info[chaintype].reliability) / 10000;
       +      if (previous != -1) {
       +        if (badchains[previous][i] || badchains[0][i])
       +          acc_reliability = 0;
       +      }
       +      previous = i;
       +    } else
       +      error = 1; /* Did not find this remailer. We can't calculate
       +                    the reliablity for the whole chain. */
       +    name_start = name_end+sizeof(char);
       +  }
       +
       +  if(error || (name_start==name_end))
       +    acc_reliability = -1;
       +
       +  /* Convert reliability into string, if appropriate */
       +  if(reliability_string){
       +    if(acc_reliability < 0)
       +      sprintf(reliability_string, "  n/a  ");
       +    else{
       +      sprintf(reliability_string, "%6.2f", acc_reliability*100);
       +      *(reliability_string+6*sizeof(char)) = '%';
       +    }
       +  }
       +
       +  return acc_reliability;
       +}
       +
   DIR diff --git a/Src/chain1.c b/Src/chain1.c
       t@@ -0,0 +1,301 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Encrypt message for Cypherpunk remailer chain
       +   $Id: chain1.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include "pgp.h"
       +#include <string.h>
       +#include <ctype.h>
       +
       +#define N(X) (isdigit(X) ? (X)-'0' : 0)
       +
       +int t1_rlist(REMAILER remailer[], int badchains[MAXREM][MAXREM])
       +{
       +  FILE *list, *excl;
       +  int i, listed = 0;
       +  int n = 0;
       +  char line[2 * LINELEN], l2[LINELEN], name[LINELEN], *flags;
       +  BUFFER *starex;
       +
       +  starex = buf_new();
       +  excl = mix_openfile(STAREX, "r");
       +  if (excl != NULL) {
       +    buf_read(starex, excl);
       +    fclose(excl);
       +  }
       +
       +  list = mix_openfile(TYPE1LIST, "r");
       +  if (list == NULL) {
       +    buf_free(starex);
       +    return (-1);
       +  }
       +
       +  while (fgets(line, sizeof(line), list) != NULL && n < MAXREM) {
       +    if (strleft(line, "$remailer") &&
       +        strchr(line, '<') && strchr(line, '>') &&
       +        strchr(line, '{') && strchr(line, '{') + 4 < strchr(line, '}')) {
       +      if (line[strlen(line) - 1] == '\n')
       +        line[strlen(line) - 1] = '\0';
       +      if (line[strlen(line) - 1] == '\r')
       +        line[strlen(line) - 1] = '\0';
       +      while (line[strlen(line) - 1] == ' ')
       +        line[strlen(line) - 1] = '\0';
       +      if (line[strlen(line) - 1] != ';'
       +          && fgets(l2, sizeof(l2), list) != NULL)
       +        strcatn(line, l2, LINELEN);
       +      flags = strchr(line, '>');
       +      strncpy(name, strchr(line, '{') + 2,
       +              strchr(line, '}') - strchr(line, '{') - 3);
       +      name[strchr(line, '}') - strchr(line, '{') - 3] = '\0';
       +      name[20] = '\0';
       +
       +      for (i = 1; i <= n; i++)
       +        if (streq(name, remailer[i].name))
       +          break;
       +      if (i > n) {
       +        /* not in mix list */
       +        n++;
       +        strcpy(remailer[i].name, name);
       +        strncpy(remailer[i].addr, strchr(line, '<') + 1,
       +                strchr(line, '>') - strchr(line, '<'));
       +        remailer[i].addr[strchr(line, '>') - strchr(line, '<') - 1]
       +          = '\0';
       +        remailer[i].flags.mix = 0;
       +        remailer[i].flags.post = strifind(flags, " post");
       +      }
       +      remailer[i].flags.cpunk = strfind(flags, " cpunk");
       +      remailer[i].flags.pgp = strfind(flags, " pgp");
       +      remailer[i].flags.pgponly = strfind(flags, " pgponly");
       +      remailer[i].flags.latent = strfind(flags, " latent");
       +      remailer[i].flags.middle = strfind(flags, " middle");
       +      remailer[i].flags.ek = strfind(flags, " ek");
       +      remailer[i].flags.esub = strfind(flags, " esub");
       +      remailer[i].flags.newnym = strfind(flags, " newnym");
       +      remailer[i].flags.nym = strfind(flags, " nym");
       +      remailer[i].info[1].reliability = 0;
       +      remailer[i].info[1].latency = 0;
       +      remailer[i].info[1].history[0] = '\0';
       +      remailer[i].flags.star_ex = bufifind(starex, name);
       +   }
       +    if (strleft(line,
       +                "-----------------------------------------------------------------------"))
       +      break;
       +  }
       +  n++;                                /* ?? */
       +  while (fgets(line, sizeof(line), list) != NULL) {
       +    if (strlen(line) >= 72 && strlen(line) <= 73)
       +      for (i = 1; i < n; i++)
       +        if (strleft(line, remailer[i].name) &&
       +            line[strlen(remailer[i].name)] == ' ') {
       +          strncpy(remailer[i].info[1].history, line + 42, 12);
       +          remailer[i].info[1].history[12] = '\0';
       +          remailer[i].info[1].reliability = 10000 * N(line[64])
       +            + 1000 * N(line[65]) + 100 * N(line[66])
       +            + 10 * N(line[68]) + N(line[69]);
       +          remailer[i].info[1].latency = 36000 * N(line[55])
       +            + 3600 * N(line[56]) + 600 * N(line[58])
       +            + 60 * N(line[59]) + 10 * N(line[61])
       +            + N(line[62]);
       +          listed++;
       +        }
       +  }
       +  fclose(list);
       +  parse_badchains(badchains, TYPE1LIST, "Broken type-I remailer chains", remailer, n);
       +  if (listed < 4)                /* we have no valid reliability info */
       +    for (i = 1; i < n; i++)
       +      remailer[i].info[1].reliability = 10000;
       +
       +#ifdef USE_PGP
       +  pgp_rlist(remailer, n);
       +#endif /* USE_PGP */
       +  buf_free(starex);
       +  return (n);
       +}
       +
       +int t1_ek(BUFFER *key, BUFFER *seed, int num)
       +{
       +  buf_reset(key);
       +  buf_appendc(key, (byte) num);
       +  buf_cat(key, seed);
       +  digest_md5(key, key);
       +  encode(key, 0);
       +#ifdef DEBUG
       +  fprintf(stderr, "passphrase=%s (%2X%2X%2X%2X %d)\n", key->data,
       +          seed->data[0], seed->data[1], seed->data[2], seed->data[3], num);
       +#endif /* DEBUG */
       +  return (0);
       +}
       +
       +int t1_encrypt(int type, BUFFER *message, char *chainstr, int latency,
       +               BUFFER *ek, BUFFER *feedback)
       +{
       +  BUFFER *b, *rem, *dest, *line, *field, *content;
       +  REMAILER remailer[MAXREM];
       +  int badchains[MAXREM][MAXREM];
       +  int maxrem, chainlen = 0;
       +  int chain[20];
       +  int hop;
       +  int hashmark = 0;
       +  int err = 0;
       +
       +  b = buf_new();
       +  rem = buf_new();
       +  dest = buf_new();
       +  line = buf_new();
       +  field = buf_new();
       +  content = buf_new();
       +
       +  maxrem = t1_rlist(remailer, badchains);
       +  if (maxrem < 1) {
       +    clienterr(feedback, "No remailer list!");
       +    err = -1;
       +    goto end;
       +  }
       +  chainlen = chain_select(chain, chainstr, maxrem, remailer, 1, line);
       +  if (chainlen < 1) {
       +    if (line->length)
       +      clienterr(feedback, line->data);
       +    else
       +      clienterr(feedback, "Invalid remailer chain!");
       +    err = -1;
       +    goto end;
       +  }
       +  if (chain[0] == 0)
       +    chain[0] = chain_randfinal(type, remailer, badchains, maxrem, 1, chain, chainlen, 0);
       +
       +  if (chain[0] == -1) {
       +    clienterr(feedback, "Invalid remailer chain!");
       +    err = -1;
       +    goto end;
       +  }
       +  if (chain_rand(remailer, badchains, maxrem, chain, chainlen, 1, 0) == -1) {
       +    clienterr(feedback, "No reliable remailers!");
       +    err = -1;
       +    goto end;
       +  }
       +  while (buf_getheader(message, field, content) == 0) {
       +    hdr_encode(content, 0);
       +    if (type == MSG_POST && bufieq(field, "newsgroups") &&
       +        remailer[chain[0]].flags.post) {
       +      buf_appendf(dest, "Anon-Post-To: %b\n", content);
       +    } else if (type == MSG_MAIL && bufieq(field, "to")) {
       +      buf_appendf(dest, "Anon-To: %b\n", content);
       +    } else {
       +      /* paste header */
       +      if (type == MSG_POST && bufieq(field, "newsgroups"))
       +        buf_appendf(dest, "Anon-To: %s\n", MAILtoNEWS);
       +      if (hashmark == 0) {
       +        buf_appends(b, "##\n");
       +        hashmark = 1;
       +      }
       +      buf_appendheader(b, field, content);
       +    }
       +  }
       +  buf_nl(b);
       +  buf_rest(b, message);
       +  buf_move(message, b);
       +
       +  if (type != MSG_NULL && dest->length == 0) {
       +    clienterr(feedback, "No destination address!");
       +    err = -1;
       +    goto end;
       +  }
       +  if (type == MSG_NULL) {
       +    buf_sets(dest, "Null:\n");
       +  }
       +  for (hop = 0; hop < chainlen; hop++) {
       +    if (hop == 0) {
       +      buf_sets(b, "::\n");
       +      buf_cat(b, dest);
       +    } else {
       +      buf_sets(b, "::\nAnon-To: ");
       +      buf_appends(b, remailer[chain[hop - 1]].addr);
       +      buf_nl(b);
       +    }
       +    if (remailer[chain[hop]].flags.latent && latency > 0)
       +      buf_appendf(b, "Latent-Time: +%d:00r\n", latency);
       +    if (ek && remailer[chain[hop]].flags.ek) {
       +      t1_ek(line, ek, hop);
       +      buf_appendf(b, "Encrypt-Key: %b\n", line);
       +    }
       +    buf_nl(b);
       +    buf_cat(b, message);
       +#ifdef USE_PGP
       +    if (remailer[chain[hop]].flags.pgp) {
       +      buf_clear(message);
       +      buf_clear(rem);
       +      buf_setf(rem, "<%s>", remailer[chain[hop]].addr);
       +      err = pgp_encrypt(PGP_ENCRYPT | PGP_REMAIL | PGP_TEXT, b, rem,
       +                        NULL, NULL, NULL, NULL);
       +      if (err < 0) {
       +        buf_setf(line, "No PGP key for remailer %s!\n",
       +                 remailer[chain[hop]].name);
       +        clienterr(feedback, line->data);
       +        goto end;
       +      }
       +      buf_appends(message, "::\nEncrypted: PGP\n\n");
       +      buf_cat(message, b);
       +    } else
       +#endif /* USE_PGP */
       +    {
       +      if (remailer[chain[hop]].flags.pgponly) {
       +        buf_setf(line, "PGP encryption needed for remailer %s!\n",
       +                 remailer[chain[hop]].name);
       +        clienterr(feedback, line->data);
       +        goto end;
       +      }
       +      buf_move(message, b);
       +    }
       +    if (ek && remailer[chain[hop]].flags.ek)
       +      buf_appends(message, "\n**\n");
       +  }
       +  buf_clear(b);
       +  if (chainlen == 0) {
       +    buf_appends(b, "::\n");
       +    buf_cat(b, dest);
       +  } else {
       +    buf_appendf(b, "%s: %s\n", ek ? "::\nAnon-To" : "To",
       +                remailer[chain[chainlen - 1]].addr);
       +  }
       +  buf_nl(b);
       +  buf_cat(b, message);
       +  buf_move(message, b);
       +end:
       +  buf_free(b);
       +  buf_free(rem);
       +  buf_free(dest);
       +  buf_free(line);
       +  buf_free(field);
       +  buf_free(content);
       +  return (err);
       +}
       +
       +#ifdef USE_PGP
       +int t1_getreply(BUFFER *msg, BUFFER *ek, int len)
       +{
       +  BUFFER *key, *decrypt;
       +  int err = -1;
       +  int hop = 0;
       +
       +  key = buf_new();
       +  decrypt = buf_new();
       +
       +  do {
       +    t1_ek(key, ek, hop);
       +    buf_set(decrypt, msg);
       +    if (pgp_decrypt(decrypt, key, NULL, NULL, NULL) == 0
       +        && decrypt->data != NULL)
       +      err = 0, buf_move(msg, decrypt);
       +  }
       +  while (hop++ < len);
       +  return (err);
       +}
       +
       +#endif /* USE_PGP */
   DIR diff --git a/Src/chain2.c b/Src/chain2.c
       t@@ -0,0 +1,685 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Encrypt message for Mixmaster chain
       +   $Id: chain2.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include <string.h>
       +#include <stdlib.h>
       +#include <time.h>
       +#include <ctype.h>
       +#include <assert.h>
       +
       +#define N(X) (isdigit(X) ? (X)-'0' : 0)
       +
       +int prepare_type2list(BUFFER *out)
       +{
       +  FILE *list;
       +  char line[LINELEN], name[LINELEN], addr[LINELEN], keyid[LINELEN],
       +  version[LINELEN], flags[LINELEN], createdstr[LINELEN], expiresstr[LINELEN];
       +  int assigned;
       +  time_t created, expires;
       +
       +  list = mix_openfile(PUBRING, "r");
       +  if (list == NULL)
       +    return (-1);
       +  while (fgets(line, sizeof(line), list) != NULL) {
       +    if (strleft(line, begin_key)) {
       +      while (fgets(line, sizeof(line), list) != NULL &&
       +             !strleft(line, end_key)) ;
       +    } else if (strlen(line) > 36 && line[0] != '#') {
       +      assigned = sscanf(line, "%127s %127s %127s %127s %127s %127s %127s",
       +                 name, addr, keyid, version, flags, createdstr, expiresstr);
       +      if (assigned < 4)
       +        continue;
       +      if (assigned >= 6) {
       +        created = parse_yearmonthday(createdstr);
       +        if (created == 0 || created == -1) {
       +          errlog(WARNING, "Cannot parse creation date of key %s.\n", keyid);
       +          continue;
       +        };
       +        if (created > time(NULL)) {
       +          errlog(WARNING, "Key %s created in the future.\n", keyid);
       +          continue;
       +        };
       +      }
       +      if (assigned >= 7) {
       +        expires = parse_yearmonthday(expiresstr);
       +        if (expires == 0 || expires == -1) {
       +          errlog(WARNING, "Cannot parse expiration date of key %s.\n", keyid);
       +          continue;
       +        };
       +        if (expires < time(NULL)) {
       +          errlog(WARNING, "Key %s has expired.\n", keyid);
       +          continue;
       +        };
       +      }
       +      buf_appends(out, line);
       +    }
       +  }
       +  fclose(list);
       +  return (0);
       +}
       +
       +int mix2_rlist(REMAILER remailer[], int badchains[MAXREM][MAXREM])
       +{
       +  FILE *list, *excl;
       +  int n, i, listed = 0;
       +
       +  char line[LINELEN], name[LINELEN], addr[LINELEN], keyid[LINELEN],
       +  version[LINELEN], flags[LINELEN], createdstr[LINELEN], expiresstr[LINELEN];
       +  int assigned;
       +  time_t created, expires;
       +  BUFFER *starex;
       +
       +  starex = buf_new();
       +  excl = mix_openfile(STAREX, "r");
       +  if (excl != NULL) {
       +    buf_read(starex, excl);
       +    fclose(excl);
       +  }
       +
       +  list = mix_openfile(PUBRING, "r");
       +  if (list == NULL) {
       +    buf_free(starex);
       +    return (-1);
       +  }
       +  for (n = 1; fgets(line, sizeof(line), list) != NULL && n < MAXREM;)
       +    if (strleft(line, begin_key)) {
       +      while (fgets(line, sizeof(line), list) != NULL &&
       +             !strleft(line, end_key)) ;
       +    } else if (strlen(line) > 36 && line[0] != '#') {
       +      flags[0] = '\0';
       +      assigned = sscanf(line, "%127s %127s %127s %127s %127s %127s %127s",
       +                 name, addr, keyid, version, flags, createdstr, expiresstr);
       +      if (assigned < 4)
       +        continue;
       +      if (assigned >= 6) {
       +        created = parse_yearmonthday(createdstr);
       +        if (created == 0 || created == -1) {
       +          errlog(WARNING, "Cannot parse creation date of key %s.\n", keyid);
       +          continue;
       +        };
       +        if (created > time(NULL)) {
       +          errlog(WARNING, "Key %s created in the future.\n", keyid);
       +          continue;
       +        };
       +      }
       +      if (assigned >= 7) {
       +        expires = parse_yearmonthday(expiresstr);
       +        if (expires == 0 || expires == -1) {
       +          errlog(WARNING, "Cannot parse expiration date of key %s.\n", keyid);
       +          continue;
       +        };
       +        if (expires < time(NULL)) {
       +          errlog(WARNING, "Key %s has expired.\n", keyid);
       +          continue;
       +        };
       +      }
       +      strncpy(remailer[n].name, name, sizeof(remailer[n].name));
       +      remailer[n].name[sizeof(remailer[n].name) - 1] = '\0';
       +      strncpy(remailer[n].addr, addr, sizeof(remailer[n].addr));
       +      remailer[n].addr[sizeof(remailer[n].addr) - 1] = '\0';
       +      remailer[n].flags.mix = 1;
       +      remailer[n].flags.cpunk = 0;
       +      remailer[n].flags.nym = 0;
       +      remailer[n].flags.newnym = 0;
       +      id_decode(keyid, remailer[n].keyid);
       +      remailer[n].version = N(version[0]);
       +      remailer[n].flags.compress = strfind(flags, "C");
       +      remailer[n].flags.post = strfind(flags, "N");
       +      remailer[n].flags.middle = strfind(flags, "M");
       +      remailer[n].info[0].reliability = 0;
       +      remailer[n].info[0].latency = 0;
       +      remailer[n].info[0].history[0] = '\0';
       +      remailer[n].flags.star_ex = bufifind(starex, name);
       +      n++;
       +    }
       +  fclose(list);
       +  list = mix_openfile(TYPE2REL, "r");
       +  if (list != NULL) {
       +    while (fgets(line, sizeof(line), list) != NULL &&
       +           !strleft(line, "--------------------------------------------")) {
       +      if (strleft(line, "Last update:")) {
       +        int generated;
       +        int now = time(NULL);
       +        char *tmp = line + strlen("Last update:") + 1;
       +        generated = parsedate(tmp);
       +        if (generated == -1) {
       +          /* For some weird reason, this isn't rfc822 */
       +          if (strleft(tmp, "Mon") ||
       +              strleft(tmp, "Tue") ||
       +              strleft(tmp, "Wed") ||
       +              strleft(tmp, "Thu") ||
       +              strleft(tmp, "Fri") ||
       +              strleft(tmp, "Sat") ||
       +              strleft(tmp, "Sun"))
       +            tmp += 3;
       +          generated = parsedate(tmp);
       +        }
       +        now = time(NULL);
       +        if (generated != -1 && generated < now - SECONDSPERDAY)
       +          errlog(WARNING, "Remailer Reliability Statistics are older than one day (check your clock?).\n");
       +        if (generated != -1 && generated > now)
       +          errlog(WARNING, "Remailer Reliability Statistics are from the future (check your clock?).\n");
       +      }
       +    };
       +    while (fgets(line, sizeof(line), list) != NULL &&
       +           !strleft(line, "</PRE>"))
       +      if (strlen(line) >= 44 && strlen(line) <= 46)
       +        for (i = 1; i < n; i++)
       +          if (strleft(line, remailer[i].name) &&
       +              line[strlen(remailer[i].name)] == ' ') {
       +            strncpy(remailer[i].info[0].history, line + 15, 12);
       +            remailer[i].info[0].history[12] = '\0';
       +            remailer[i].info[0].reliability = 10000 * N(line[37])
       +              + 1000 * N(line[38]) + 100 * N(line[39])
       +              + 10 * N(line[41]) + N(line[42]);
       +            remailer[i].info[0].latency = 36000 * N(line[28])
       +              + 3600 * N(line[29]) + 600 * N(line[31])
       +              + 60 * N(line[32]) + 10 * N(line[34])
       +              + N(line[35]);
       +            listed++;
       +          }
       +    fclose(list);
       +  }
       +
       +  parse_badchains(badchains, TYPE2REL, "Broken type-II remailer chains", remailer, n);
       +  if (listed < 4)                /* we have no valid reliability info */
       +    for (i = 1; i < n; i++)
       +      remailer[i].info[0].reliability = 10000;
       +  buf_free(starex);
       +  return (n);
       +}
       +
       +static int send_packet(int numcopies, BUFFER *packet, int chain[],
       +                       int chainlen, int packetnum, int numpackets,
       +                       BUFFER *mid, REMAILER remailer[], int badchains[MAXREM][MAXREM],
       +                       int maxrem, char *redirect_to, int ignore_constraints_if_necessary,
       +                       BUFFER *feedback)
       +/*
       + * Puts a mix packet in the pool.
       + *
       + * numcopies   ... how often to put this packet into the pool
       + *                 i.e. send it.  required that random remailers are in the chain.
       + * packet      ... the payload, 10240 bytes in size.
       + * chain       ... the chain to send this message along
       + * chainlen    ... length of the chain
       + * packetnum   ... in multi-packet messages (fragmented) the serial of this packet
       + * numpackets  ...  the total number of packets
       + * mid         ... the message ID (required for fragmented packets
       + * remailer    ... information about remailers, their reliabilities, capabilities, etc.
       + * badchains   ... broken chain information
       + * maxrem      ... the number of remailers in remailer[] and badchains[]
       + * redirect_to ... if this is not-null it needs to be an email address.
       + *                 in this case packet needs to be not only the body, but a
       + *                 complete mixmaster packet of 20480 bytes in size (20 headers + body).
       + *                 the chain given is prepended to the one already encrypted in
       + *                 the existing message.  If this exceeds the allowed 20 hops in total
       + *                 the message is corrupted, the last node will realize this.
       + *                 This is useful if you want to reroute an existing mixmaster message
       + *                 that has foo as the next hop via a chain so that the packet will
       + *                 actually flow hop1,hop2,hop3,foo,....
       + * ignore_constraints_if_necessary .. to be used when randhopping messages.
       + *                 if a chain can not be constructed otherwhise, maxlat, minlat,
       + *                 and minrel are ignored.
       + * feedback    ... a buffer to write feedback to
       + */
       +{
       +  BUFFER *pid, *out, *header, *other, *encrypted, *key, *body;
       +  BUFFER *iv, *ivarray, *temp;
       +  BUFFER *pubkey;
       +  char addr[LINELEN];
       +  int thischain[20];
       +  int hop;
       +  int c, i;
       +  int timestamp = 0;
       +  int israndom = 0;
       +  int err = 1;
       +
       +  body = buf_new();
       +  pid = buf_new();
       +  out = buf_new();
       +  header = buf_new();
       +  other = buf_new();
       +  key = buf_new();
       +  encrypted = buf_new();
       +  iv = buf_new();
       +  ivarray = buf_new();
       +  temp = buf_new();
       +
       +  if (redirect_to != NULL) {
       +    assert(packet->length == 20480);
       +    buf_append(header, packet->data, 10240);
       +    buf_append(temp, packet->data + 10240, 10240);
       +    buf_clear(packet);
       +    buf_cat(packet, temp);
       +  } else 
       +    assert(packet->length == 10240);
       +
       +  buf_setrnd(pid, 16);
       +
       +  for (c = 0; c < numcopies; c++) {
       +    buf_set(body, packet);
       +
       +    for (hop = 0; hop < chainlen; hop++)
       +      thischain[hop] = chain[hop];
       +
       +    israndom = chain_rand(remailer, badchains, maxrem, thischain, chainlen, 0, ignore_constraints_if_necessary);
       +    if (israndom == -1) {
       +      err = -1;
       +      clienterr(feedback, "No reliable remailers!");
       +    }
       +    if ((numcopies > 1 || numpackets > 1) && !israndom && (chainlen != 1)) {
       +      clienterr(feedback,
       +                "Multi-packet message without random remailers!");
       +      err = -1;
       +      goto end;
       +    }
       +    for (hop = 0; hop < chainlen; hop++) {
       +      switch (remailer[thischain[hop]].version) {
       +      case 2:
       +      case 3:                        /* not implemented yet; fall back to version 2 */
       +        /* create header chart to be encrypted with the session key */
       +        if (numcopies > 1 && hop == 0 && redirect_to == NULL)
       +          buf_set(encrypted, pid);        /* same ID only at final hop */
       +        else
       +          buf_setrnd(encrypted, 16);
       +        buf_setrnd(key, 24);        /* key for encrypting the body */
       +        buf_cat(encrypted, key);
       +        buf_setrnd(iv, 8);        /* IV for encrypting the body */
       +
       +        if (hop > 0 || redirect_to != NULL) {
       +          /* IVs for header chart encryption */
       +          buf_setrnd(ivarray, 18 * 8);
       +          buf_cat(ivarray, iv);        /* 19th IV equals the body IV */
       +
       +          buf_appendc(encrypted, 0);
       +          buf_cat(encrypted, ivarray);
       +          memset(addr, 0, 80);
       +          if (hop == 0) {
       +            assert(redirect_to != NULL);
       +            strncpy(addr, redirect_to, 80);
       +          } else {
       +            assert(hop > 0);
       +            strcpy(addr, remailer[thischain[hop - 1]].addr);
       +          };
       +          buf_append(encrypted, addr, 80);
       +        } else {
       +          if (numpackets == 1)
       +            buf_appendc(encrypted, 1);
       +          else {
       +            buf_appendc(encrypted, 2);
       +            buf_appendc(encrypted, (byte) packetnum);
       +            buf_appendc(encrypted, (byte) numpackets);
       +          }
       +          buf_cat(encrypted, mid);
       +          buf_cat(encrypted, iv);        /* body encryption IV */
       +        }
       +
       +        /* timestamp */
       +        buf_appends(encrypted, "0000");
       +        buf_appendc(encrypted, '\0');        /* timestamp magic */
       +        timestamp = time(NULL) / SECONDSPERDAY - rnd_number(4);
       +        buf_appendi_lo(encrypted, timestamp);
       +
       +        /* message digest for this header */
       +        digest_md5(encrypted, temp);
       +        buf_cat(encrypted, temp);
       +        buf_pad(encrypted, 328);
       +
       +        /* encrypt message body */
       +        buf_crypt(body, key, iv, ENCRYPT);
       +
       +        if (hop > 0 || redirect_to != NULL) {
       +          /* encrypt the other header charts */
       +          buf_clear(other);
       +          for (i = 0; i < 19; i++) {
       +            buf_clear(iv);
       +            buf_clear(temp);
       +            buf_append(iv, ivarray->data + 8 * i, 8);
       +            buf_append(temp, header->data + 512 * i, 512);
       +            buf_crypt(temp, key, iv, ENCRYPT);
       +            buf_cat(other, temp);
       +          }
       +        } else
       +          buf_setrnd(other, 19 * 512);        /* fill with random data */
       +
       +        /* create session key and IV to encrypt the header ... */
       +        buf_setrnd(key, 24);
       +        buf_setrnd(iv, 8);
       +        buf_crypt(encrypted, key, iv, ENCRYPT);
       +        pubkey = buf_new();
       +        err = db_getpubkey(remailer[thischain[hop]].keyid, pubkey);
       +        if (err == -1)
       +          goto end;
       +        err = pk_encrypt(key, pubkey);        /* ... and encrypt the
       +                                           session key */
       +        buf_free(pubkey);
       +        if (err == -1 || key->length != 128) {
       +          clienterr(feedback, "Encryption failed!");
       +          err = -1;
       +          goto end;
       +        }
       +        /* now build the new header */
       +        buf_clear(header);
       +        buf_append(header, remailer[thischain[hop]].keyid, 16);
       +        buf_appendc(header, 128);
       +        buf_cat(header, key);
       +        buf_cat(header, iv);
       +        buf_cat(header, encrypted);
       +        buf_pad(header, 512);
       +        buf_cat(header, other);
       +        break;
       +      default:
       +        err = -1;
       +        goto end;
       +      }
       +    }
       +
       +    /* build the message */
       +    buf_sets(out, remailer[thischain[chainlen - 1]].addr);
       +    buf_nl(out);
       +    buf_cat(out, header);
       +    buf_cat(out, body);
       +    assert(header->length == 10240 && body->length == 10240);
       +    mix_pool(out, INTERMEDIATE, -1);
       +
       +    if (feedback) {
       +      for (hop = chainlen - 1; hop >= 0; hop--) {
       +        buf_appends(feedback, remailer[thischain[hop]].name);
       +        if (hop > 0)
       +          buf_appendc(feedback, ',');
       +      }
       +      buf_nl(feedback);
       +    }
       +  }
       +end:
       +  buf_free(pid);
       +  buf_free(body);
       +  buf_free(out);
       +  buf_free(header);
       +  buf_free(temp);
       +  buf_free(other);
       +  buf_free(key);
       +  buf_free(encrypted);
       +  buf_free(iv);
       +  buf_free(ivarray);
       +  return (err);
       +}
       +
       +int redirect_message(BUFFER *sendmsg, char *chainstr, int numcopies, BUFFER *feedback)
       +{
       +  BUFFER *field;
       +  BUFFER *content;
       +  BUFFER *line;
       +  char recipient[80] = "";
       +  int num = 0;
       +  int err = 0;
       +  int c;
       +  int hop;
       +
       +  REMAILER remailer[MAXREM];
       +  int chain[20];
       +  int thischain[20];
       +  int chainlen;
       +  int badchains[MAXREM][MAXREM];
       +  int maxrem;
       +  int tempchain[20];
       +  int tempchainlen;
       +  int israndom;
       +
       +  field = buf_new();
       +  content = buf_new();
       +  line = buf_new();
       +
       +  if (numcopies == 0)
       +    numcopies = NUMCOPIES;
       +  if (numcopies > 10)
       +    numcopies = 10;
       +
       +  /* Find the recipient */
       +  while (buf_getheader(sendmsg, field, content) == 0)
       +    if (bufieq(field, "to")) {
       +      strncpy(recipient, content->data, sizeof(recipient));
       +      num++;
       +    };
       +  if (num != 1) {
       +    clienterr(feedback, "Did not find exactly one To: address!");
       +    err = -1;
       +    goto end;
       +  };
       +
       +  /* Dearmor the message */
       +  err = mix_dearmor(sendmsg, sendmsg);
       +  if (err == -1)
       +    goto end;
       +  assert (sendmsg->length == 20480);
       +
       +  /* Check the chain */
       +  maxrem = mix2_rlist(remailer, badchains);
       +  if (maxrem < 1) {
       +    clienterr(feedback, "No remailer list!");
       +    err = -1;
       +    goto end;
       +  }
       +  chainlen = chain_select(chain, chainstr, maxrem, remailer, 0, line);
       +  if (chainlen < 1) {
       +    if (line->length)
       +      clienterr(feedback, line->data);
       +    else
       +      clienterr(feedback, "Invalid remailer chain!");
       +    err = -1;
       +    goto end;
       +  } else if (chainlen >= 20) {
       +    clienterr(feedback, "A chainlength of 20 will certainly destroy the message!");
       +    err = -1;
       +    goto end;
       +  };
       +
       +
       +  for (c = 0; c < numcopies; c++) {
       +    /* if our recipient is a remailer we want to make sure we're not using a known broken chain.
       +     * therefore we need to pick the final remailer with care */
       +    for (hop = 0; hop < chainlen; hop++)
       +      thischain[hop] = chain[hop];
       +    if (thischain[0] == 0) {
       +      /* Find out, if recipient is a remailer */
       +      tempchainlen = chain_select(tempchain, recipient, maxrem, remailer, 0, line);
       +      if (tempchainlen < 1 && line->length == 0) {
       +        /* recipient is apparently not a remailer we know about */
       +        ;
       +      } else {
       +        /* Build a new chain, based on the one we already selected but
       +         * with the recipient as the final hop.
       +         * This is so that chain_rand properly selects nodes based on
       +         * broken chains and DISTANCE */
       +        assert(chainlen < 20);
       +        for (hop = 0; hop < chainlen; hop++)
       +          thischain[hop+1] = thischain[hop];
       +        thischain[0] = tempchain[0];
       +
       +        israndom = chain_rand(remailer, badchains, maxrem, thischain, chainlen + 1, 0, 0);
       +        if (israndom == -1) {
       +          err = -1;
       +          clienterr(feedback, "No reliable remailers!");
       +          goto end;
       +        }
       +
       +        /* Remove the added recipient hop */
       +        for (hop = 0; hop < chainlen; hop++)
       +          thischain[hop] = thischain[hop + 1];
       +      };
       +    };
       +
       +    /* queue the packet */
       +    if (send_packet(1, sendmsg, thischain, chainlen,
       +            -1, -1, NULL,
       +            remailer, badchains, maxrem, recipient, 0, feedback) == -1)
       +      err = -1;
       +  };
       +
       +end:
       +  buf_free(field);
       +  buf_free(content);
       +  buf_free(line);
       +  return (err);
       +}
       +
       +int mix2_encrypt(int type, BUFFER *message, char *chainstr, int numcopies,
       +                 int ignore_constraints_if_necessary,
       +                 BUFFER *feedback)
       +{
       +  /* returns 0 on success, -1 on error. feedback contains the selected
       +     remailer chain or an error message
       +
       +   ignore_constraints_if_necessary .. to be used when randhopping messages.
       +                                   if a chain can not be constructed otherwhise,
       +                                   maxlat, minlat, and minrel are ignored.
       +     */
       +
       +  REMAILER remailer[MAXREM];
       +  int badchains[MAXREM][MAXREM];
       +  int maxrem;
       +  BUFFER *line, *field, *content, *header, *msgdest, *msgheader, *body,
       +      *temp, *mid;
       +  byte numdest = 0, numhdr = 0;
       +  char hdrline[LINELEN];
       +  BUFFER *packet;
       +  int chain[20];
       +  int chainlen;
       +  int i;
       +  int err = 0;
       +
       +  mix_init(NULL);
       +  packet = buf_new();
       +  line = buf_new();
       +  field = buf_new();
       +  content = buf_new();
       +  msgheader = buf_new();
       +  msgdest = buf_new();
       +  body = buf_new();
       +  temp = buf_new();
       +  mid = buf_new();
       +  header = buf_new();
       +  if (feedback)
       +    buf_reset(feedback);
       +
       +  if (numcopies == 0)
       +    numcopies = NUMCOPIES;
       +  if (numcopies > 10)
       +    numcopies = 10;
       +
       +  maxrem = mix2_rlist(remailer, badchains);
       +  if (maxrem < 1) {
       +    clienterr(feedback, "No remailer list!");
       +    err = -1;
       +    goto end;
       +  }
       +  chainlen = chain_select(chain, chainstr, maxrem, remailer, 0, line);
       +  if (chainlen < 1) {
       +    if (line->length)
       +      clienterr(feedback, line->data);
       +    else
       +      clienterr(feedback, "Invalid remailer chain!");
       +    err = -1;
       +    goto end;
       +  }
       +  if (chain[0] == 0)
       +    chain[0] = chain_randfinal(type, remailer, badchains, maxrem, 0, chain, chainlen, ignore_constraints_if_necessary);
       +
       +  if (chain[0] == -1) {
       +    clienterr(feedback, "No reliable remailers!");
       +    err = -1;
       +    goto end;
       +  }
       +  switch (remailer[chain[0]].version) {
       +  case 2:
       +    if (type == MSG_NULL) {
       +      memset(hdrline, 0, 80);
       +      strcpy(hdrline, "null:");
       +      buf_append(msgdest, hdrline, 80);
       +      numdest++;
       +    } else
       +      while (buf_getheader(message, field, content) == 0) {
       +        if (bufieq(field, "to")) {
       +          memset(hdrline, 0, 80);
       +          strncpy(hdrline, content->data, 80);
       +          buf_append(msgdest, hdrline, 80);
       +          numdest++;
       +        } else if (type == MSG_POST && bufieq(field, "newsgroups")) {
       +          memset(hdrline, 0, 80);
       +          strcpy(hdrline, "post: ");
       +          strcatn(hdrline, content->data, 80);
       +          buf_append(msgdest, hdrline, 80);
       +          numdest++;
       +        } else {
       +          buf_clear(header);
       +          buf_appendheader(header, field, content);
       +          hdr_encode(header, 80);
       +          while (buf_getline(header, line) == 0) {
       +            /* paste in encoded header entry */
       +            memset(hdrline, 0, 80);
       +            strncpy(hdrline, line->data, 80);
       +            buf_append(msgheader, hdrline, 80);
       +            numhdr++;
       +          }
       +        }
       +      }
       +    buf_appendc(body, numdest);
       +    buf_cat(body, msgdest);
       +    buf_appendc(body, numhdr);
       +    buf_cat(body, msgheader);
       +
       +    if (type != MSG_NULL) {
       +      buf_rest(temp, message);
       +      if (temp->length > 10236 && remailer[chain[0]].flags.compress)
       +        buf_compress(temp);
       +      buf_cat(body, temp);
       +      buf_reset(temp);
       +    }
       +    buf_setrnd(mid, 16);        /* message ID */
       +    for (i = 0; i <= body->length / 10236; i++) {
       +      long length;
       +
       +      length = body->length - i * 10236;
       +      if (length > 10236)
       +        length = 10236;
       +      buf_clear(packet);
       +      buf_appendl_lo(packet, length);
       +      buf_append(packet, body->data + i * 10236, length);
       +      buf_pad(packet, 10240);
       +      if (send_packet(numcopies, packet, chain, chainlen,
       +                      i + 1, body->length / 10236 + 1,
       +                      mid, remailer, badchains, maxrem, NULL, ignore_constraints_if_necessary, feedback) == -1)
       +        err = -1;
       +    }
       +    break;
       +  case 3:
       +    NOT_IMPLEMENTED;
       +    break;
       +  default:
       +    fprintf(stderr, "%d\n", chain[0]);
       +    clienterr(feedback, "Unknown remailer version!");
       +    err = -1;
       +  }
       +
       +end:
       +  buf_free(packet);
       +  buf_free(line);
       +  buf_free(field);
       +  buf_free(content);
       +  buf_free(header);
       +  buf_free(msgheader);
       +  buf_free(msgdest);
       +  buf_free(body);
       +  buf_free(temp);
       +  buf_free(mid);
       +  return (err);
       +}
   DIR diff --git a/Src/compress.c b/Src/compress.c
       t@@ -0,0 +1,210 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Buffer compression (interface to zlib)
       +   $Id: compress.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include <stdio.h>
       +#include <assert.h>
       +
       +static byte gz_magic[2] =
       +{0x1f, 0x8b};                        /* gzip magic header */
       +
       +/* gzip flag byte */
       +#define ASCII_FLAG   0x01
       +#define HEAD_CRC     0x02
       +#define EXTRA_FIELD  0x04
       +#define ORIG_NAME    0x08
       +#define COMMENT      0x10
       +#define RESERVED     0xE0
       +#define Z_DEFLATED   8
       +
       +#ifdef USE_ZLIB
       +#include "zlib.h"
       +
       +int buf_unzip(BUFFER *in, int type)
       +{
       +  BUFFER *out;
       +  z_stream s;
       +  long outstart;
       +  int err;
       +  int ret = 0;
       +
       +  out = buf_new();
       +
       +  s.zalloc = (alloc_func) 0;
       +  s.zfree = (free_func) 0;
       +  s.opaque = (voidpf) 0;
       +
       +  s.next_in = in->data + in->ptr;
       +  s.avail_in = in->length + 1 - in->ptr;        /* terminating 0 byte as "dummy" */
       +  s.next_out = NULL;
       +
       +  if (type == 1)
       +    err = inflateInit(&s);    /* zlib */
       +  else
       +    err = inflateInit2(&s, -MAX_WBITS);
       +  if (err != Z_OK) {
       +    ret = -1;
       +    goto end;
       +  }
       +  outstart = 0;
       +  buf_append(out, NULL, in->length * 15 / 10);
       +
       +  for (;;) {
       +    s.next_out = out->data + s.total_out + outstart;
       +    s.avail_out = out->length - outstart - s.total_out;
       +    err = inflate(&s, Z_PARTIAL_FLUSH);
       +    out->length -= s.avail_out;
       +    if (err != Z_OK)
       +      break;
       +    buf_append(out, NULL, BUFSIZE);
       +  }
       +  if (err != Z_STREAM_END)
       +    errlog(WARNING, "Decompression error %d\n", err);
       +
       +  err = inflateEnd(&s);
       +  if (err != Z_OK)
       +    ret = -1;
       +end:
       +  if (ret != 0)
       +    switch (err) {
       +    case Z_STREAM_ERROR:
       +      errlog(ERRORMSG, "Decompression error Z_STREAM_ERROR.\n", err);
       +      break;
       +    case Z_MEM_ERROR:
       +      errlog(ERRORMSG, "Decompression error Z_MEM_ERROR.\n", err);
       +      break;
       +    case Z_BUF_ERROR:
       +      errlog(ERRORMSG, "Decompression error Z_BUF_ERROR.\n", err);
       +      break;
       +    case Z_VERSION_ERROR:
       +      errlog(ERRORMSG, "Decompression error Z_VERSION_ERROR.\n", err);
       +      break;
       +    default:
       +      errlog(ERRORMSG, "Decompression error %d.\n", err);
       +    }
       +  buf_move(in, out);
       +  buf_free(out);
       +  return (ret);
       +}
       +
       +int buf_zip(BUFFER *out, BUFFER *in, int bits)
       +{
       +  z_stream s;
       +  long outstart;
       +  int err = -1;
       +
       +  assert(in != out);
       +
       +  s.zalloc = (alloc_func) 0;
       +  s.zfree = (free_func) 0;
       +  s.opaque = (voidpf) 0;
       +  s.next_in = NULL;
       +
       +  if (bits == 0)
       +    bits = MAX_WBITS;
       +
       +  if (deflateInit2(&s, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -bits, 8, 0) != Z_OK)
       +    goto end;
       +
       +  outstart = out->length;
       +  /* 12 is overhead, 1.01 is maximum expansion, and 1 is there to force a round-up */
       +  buf_append(out, NULL, (int)13+in->length*1.01); /* fit it in one chunk */
       +
       +  s.next_in = in->data;
       +  s.avail_in = in->length;
       +
       +  for (;;) {
       +    s.next_out = out->data + s.total_out + outstart;
       +    s.avail_out = out->length - outstart - s.total_out;
       +    err = deflate(&s, Z_FINISH);
       +    out->length -= s.avail_out;
       +    if (err != Z_OK)
       +      break;
       +    errlog(ERRORMSG, "Compressed data did not fit in one chunk.\n");
       +    buf_append(out, NULL, BUFSIZE);
       +  }
       +  if (deflateEnd(&s) != Z_OK || err != Z_STREAM_END)
       +    err = -1;
       +  else
       +    err = 0;
       +end:
       +  if (err != 0)
       +    errlog(ERRORMSG, "Compression error.\n");
       +  return (err);
       +}
       +
       +#else /* end of USE_ZLIB */
       +int buf_zip(BUFFER *out, BUFFER *in, int bits)
       +{
       +  return (-1);
       +}
       +
       +int buf_unzip(BUFFER *b, int type)
       +{
       +  errlog(ERRORMSG, "Can't uncompress: no zlib\n");
       +  return (-1);
       +}
       +#endif /* else not USE_ZLIB */
       +
       +int compressed(BUFFER *b)
       +{
       +  return (b->length >= 10 && b->data[0] == gz_magic[0] &&
       +          b->data[1] == gz_magic[1]);
       +}
       +
       +int buf_uncompress(BUFFER *in)
       +{
       +  int type;
       +  int err = -1;
       +  unsigned int len;
       +
       +  if (!compressed(in))
       +    return (0);
       +  type = in->data[3];
       +  if (in->data[2] != Z_DEFLATED || (type & RESERVED) == 0) {
       +    in->ptr = 10;
       +    if ((type & EXTRA_FIELD) != 0) {
       +      len = buf_geti(in);
       +      in->ptr += len;
       +    }
       +    if ((type & ORIG_NAME) != 0)
       +      while (buf_getc(in) > 0) ;
       +    if ((type & COMMENT) != 0)
       +      while (buf_getc(in) > 0) ;
       +    if ((type & HEAD_CRC) != 0)
       +      buf_geti(in);
       +    err = buf_unzip(in, 0);
       +  }
       +  return (err);
       +}
       +
       +int buf_compress(BUFFER *in)
       +{
       +  BUFFER *out;
       +  int err;
       +
       +  if (compressed(in))
       +    return (0);
       +
       +  out = buf_new();
       +  buf_appendc(out, gz_magic[0]);
       +  buf_appendc(out, gz_magic[1]);
       +  buf_appendc(out, Z_DEFLATED);
       +  buf_appendc(out, 0);                /* flags */
       +  buf_appendl(out, 0);                /* time */
       +  buf_appendc(out, 0);                /* xflags */
       +  buf_appendc(out, 3);                /* Unix */
       +  err = buf_zip(out, in, 0);
       +  if (err == 0)
       +    buf_move(in, out);
       +  buf_free(out);
       +  return (err);
       +}
   DIR diff --git a/Src/config.h b/Src/config.h
       t@@ -0,0 +1,403 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2008 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Configuration
       +   $Id: config.h 973 2008-03-03 16:55:38Z rabbi $ */
       +
       +
       +#ifndef _CONFIG_H
       +#define _CONFIG_H
       +#include "version.h"
       +#ifndef WIN32
       +#include "sys/param.h"
       +#endif /* WIN32 */
       +
       +/* Disclaimer to be inserted in all anonymous messages: */
       +#define DISCLAIMER \
       + "Comments: This message did not originate from the Sender address above.\n" \
       + "\tIt was remailed automatically by anonymizing remailer software.\n" \
       + "\tPlease report problems or inappropriate use to the\n" \
       + "\tremailer administrator at <%s>.\n"        /* (%s is the complaints address) */
       +
       +/* Additional disclaimer to be inserted in the body of messages with
       + * user-supplied From lines, e.g.
       + * "NOTE: The above From: line has not been authenticated!\n\n" */
       +#define FROMDISCLAIMER ""
       +
       +/* Additional disclaimer to be inserted at the bottom of the body of all
       + * messages */
       +#define MSGFOOTER ""
       +
       +/* Comment to be inserted when a binary attachment is filtered out: */
       +#define BINDISCLAIMER \
       + "[...]"
       +
       +/* Character set for MIME-encoded mail header lines */
       +#define MIMECHARSET "iso-8859-1"
       +#if 1
       +#define DEFLTENTITY ""
       +#else
       +#define DEFLTENTITY "text/plain; charset=" MIMECHARSET
       +#endif
       +
       +#ifdef WIN32
       +/* Use the PCRE regular expression library for destination blocking? */
       +#define USE_PCRE
       +/* Use zlib for compression? */
       +#define USE_ZLIB
       +/* Use ncurses? */
       +#define USE_NCURSES
       +/* Use the WIN GUI? */
       +#define USE_WINGUI
       +/* Use sockets to deliver mail */
       +#define USE_SOCK
       +/* Compile in Win32 service support */
       +#define WIN32SERVICE
       +#endif /* WIN32 */
       +
       +/** System dependencies **********************************************/
       +/* Macros: UNIX  for Unix-style systems
       +           POSIX for systems with POSIX header files (including DJGPP)
       +           MSDOS for 32 bit DOS
       +           WIN32 for Windows 95/NT */
       +
       +#if defined(_WIN32) && !defined(WIN32)
       +#define WIN32
       +#endif
       +
       +#if defined(__RSXNT__) && !defined(WIN32)
       +#define WIN32
       +#endif
       +
       +#if !defined(UNIX) && !defined(WIN32) && !defined(MSDOS)
       +#define UNIX
       +#endif
       +
       +#if defined(UNIX) && !defined(POSIX)
       +#define POSIX
       +#endif
       +
       +#ifdef UNIX
       +#define DEV_URANDOM "/dev/urandom"
       +#ifdef __OpenBSD__
       +#define DEV_RANDOM "/dev/arandom"
       +#else
       +#define DEV_RANDOM "/dev/random"
       +#endif
       +#endif
       +
       +#ifdef POSIX
       +# define HAVE_TERMIOS
       +#endif /* POSIX */
       +
       +#ifdef MSDOS
       +#define SHORTNAMES
       +#ifndef WIN32
       +#define HAVE_GETKEY
       +#undef USE_SOCK
       +#endif
       +#endif
       +
       +#if defined(USE_WINGUI) && !defined(WIN32)
       +#error "The GUI requires Win32!"
       +#endif
       +
       +#if defined(WIN32) && !defined(_USRDLL)
       +#define DLLIMPORT __declspec(dllimport)
       +#else
       +#define DLLIMPORT
       +#endif
       +
       +/* This block includes the config.h created by autoconf/configure.
       + * Eventually this old config.h stuff should be merged with the autoconf
       + * stuff perhaps. */
       +#ifdef HAVE_CONFIG_H
       +# include "../config.h"
       +#else /* End of HAVE_CONFIG_H */
       +
       +/* Setup for stuff that happens when autoconf isn't run.  This should be 
       + * removed once we finally nuke that damn Install script. */
       +
       +/** Libraries and library functions **********************************/
       +
       +/* Use the OpenSSL crypto library (required) */
       +#define USE_OPENSSL
       +/* Use IDEA algorithm? (See file idea.txt) */
       +/* #define USE_IDEA */
       +/* Use AES algorithm? - should be handled by Install script setting compiler option -DUSE_AES */
       +/* #define USE_AES */
       +/* Support the OpenPGP message format? */
       +#define USE_PGP
       +
       +#ifdef UNIX
       +# define HAVE_UNAME
       +# define HAVE_GECOS
       +#endif
       +
       +#if defined(POSIX) || defined(USE_SOCK)
       +# define HAVE_GETHOSTNAME
       +#endif
       +
       +#ifdef POSIX
       +/* not a POSIX function, but avaiable on virtually all Unix systems */
       +# define HAVE_GETTIMEOFDAY
       +#endif
       +
       +#ifdef linux
       +# define HAVE_GETDOMAINNAME
       +#endif
       +
       +#ifdef WIN32
       +# ifdef _MSC_VER
       +#pragma warning(disable: 4018) /* signed/unsigned mismatch */
       +#pragma warning(disable: 4761) /* integral size mismatch */
       +# endif
       +#endif
       +
       +
       +#endif /* End of not HAVE_CONFIG_H */
       +
       +/** Constants *********************************************************/
       +
       +/* Give up if a file is larger than BUFFER_MAX bytes: */
       +/* #define BUFFER_MAX 64*1024*1024 */
       +
       +#ifdef MAXPATHLEN
       +#define PATHMAX MAXPATHLEN
       +#else /* MAXPATHLEN */
       +#ifdef _MSC
       +#define PATHMAX MAX_PATH
       +#else /* _MSC */
       +#define PATHMAX 512
       +#endif /* not _MSC */
       +#endif /* not MAXPATHLEN */
       +#define LINELEN 128
       +#define BUFSIZE 4096
       +
       +/** if it is a systemwide installation defined GLOBALMIXCONF **********/
       +/* #define GLOBALMIXCONF "/etc/mix.cfg" */
       +
       +/* The path to append to a user's homedirectory for his local Mix dir */
       +#ifndef HOMEMIXDIR
       +#define HOMEMIXDIR "Mix"
       +#endif
       +
       +/** file names ********************************************************/
       +
       +#ifdef WIN32
       +#define DEFAULT_MIXCONF "mix.cfg"  /* change to mix.ini eventually  */
       +#else
       +#define DEFAULT_MIXCONF "mix.cfg"      /* mixmaster configuration file */
       +#endif
       +#define DEFAULT_DISCLAIMFILE "disclaim.txt"
       +#define DEFAULT_FROMDSCLFILE "fromdscl.txt"
       +#define DEFAULT_MSGFOOTERFILE "footer.txt"
       +#ifdef WIN32
       +#define DEFAULT_POP3CONF "pop3.cfg"  /* change to pop3.ini eventually */
       +#else
       +#define DEFAULT_POP3CONF "pop3.cfg"
       +#endif
       +#define DEFAULT_HELPFILE "help.txt"
       +#define DEFAULT_REQUESTDIR "requests"
       +#define DEFAULT_ABUSEFILE "abuse.txt"
       +#define DEFAULT_REPLYFILE "reply.txt"
       +#define DEFAULT_USAGEFILE "usage.txt"
       +#define DEFAULT_USAGELOG "usage.log"
       +#define DEFAULT_BLOCKFILE "blocked.txt"
       +#define DEFAULT_ADMKEYFILE "adminkey.txt"
       +#define DEFAULT_KEYFILE "key.txt"
       +#define DEFAULT_PGPKEY "pgpkey.txt"
       +#define DEFAULT_DSAPARAMS "dsaparam.mix"
       +#define DEFAULT_DHPARAMS "dhparam.mix"
       +#define DEFAULT_MIXRAND "mixrand.bin"
       +#define DEFAULT_SECRING "secring.mix"
       +#define DEFAULT_PUBRING "pubring.mix"
       +#define DEFAULT_IDLOG "id.log"
       +#define DEFAULT_STATS "stats.log"
       +#define DEFAULT_PGPMAXCOUNT "pgpmaxcount.log"
       +/* To enable multiple dest.blk files, edit the following line. */
       +/* Filenames must be seperated by one space.                   */
       +#define DEFAULT_DESTBLOCK "dest.blk rab.blk"
       +#define DEFAULT_DESTALLOW "dest.alw"
       +#define DEFAULT_DESTALLOW2 "dest.alw.nonpublished"
       +#define DEFAULT_SOURCEBLOCK "source.blk"
       +#define DEFAULT_HDRFILTER "header.blk"
       +#define DEFAULT_REGULAR "time.log"
       +#define DEFAULT_POOL "pool"            /* remailer pool subdirectory */
       +#define DEFAULT_TYPE1LIST "rlist.txt"
       +#define DEFAULT_TYPE2REL "mlist.txt"
       +#define DEFAULT_PIDFILE "mixmaster.pid"
       +#define DEFAULT_STATSSRC "stats-src.txt"
       +
       +#define DEFAULT_PGPREMPUBRING "pubring.pgp"
       +#define DEFAULT_PGPREMPUBASC "pubring.asc"
       +#define DEFAULT_PGPREMSECRING "secring.pgp"
       +#define DEFAULT_NYMSECRING "nymsec.pgp"
       +#define DEFAULT_NYMDB "secrets.mix"
       +#define DEFAULT_STAREX "starex.txt"
       +#define DEFAULT_ALLPINGERSURL "http://www.noreply.org/allpingers/allpingers.txt"
       +#define DEFAULT_ALLPINGERSFILE "allpingers.txt"
       +#define DEFAULT_WGET "wget"
       +
       +DLLIMPORT extern char MIXCONF[];
       +extern char DISCLAIMFILE[];
       +extern char FROMDSCLFILE[];
       +extern char MSGFOOTERFILE[];
       +extern char POP3CONF[];
       +extern char HELPFILE[];
       +extern char REQUESTDIR[];
       +extern char ABUSEFILE[];
       +extern char REPLYFILE[];
       +extern char USAGEFILE[];
       +extern char USAGELOG[];
       +extern char BLOCKFILE[];
       +extern char ADMKEYFILE[];
       +extern char KEYFILE[];
       +extern char PGPKEY[];
       +extern char DSAPARAMS[];
       +extern char DHPARAMS[];
       +extern char MIXRAND[];
       +extern char SECRING[];
       +extern char PUBRING[];
       +extern char IDLOG[];
       +extern char STATS[];
       +extern char PGPMAXCOUNT[];
       +extern char DESTBLOCK[];
       +extern char DESTALLOW[];
       +extern char DESTALLOW2[];
       +extern char SOURCEBLOCK[];
       +extern char HDRFILTER[];
       +extern char REGULAR[];
       +extern char POOL[];
       +extern char TYPE1LIST[];
       +extern char TYPE2REL[];
       +extern char PIDFILE[];
       +extern char STAREX[];
       +
       +extern char PGPREMPUBRING[];
       +extern char PGPREMPUBASC[];
       +extern char PGPREMSECRING[];
       +DLLIMPORT extern char NYMSECRING[];
       +extern char NYMDB[];
       +
       +/* string constants */
       +#define remailer_type "Remailer-Type: Mixmaster "
       +#define mixmaster_protocol "2"
       +#define begin_remailer "-----BEGIN REMAILER MESSAGE-----"
       +#define end_remailer "-----END REMAILER MESSAGE-----"
       +#define begin_key "-----Begin Mix Key-----"
       +#define end_key "-----End Mix Key-----"
       +#define begin_pgp "-----BEGIN PGP "
       +#define end_pgp "-----END PGP "
       +#define begin_pgpmsg "-----BEGIN PGP MESSAGE-----"
       +#define end_pgpmsg "-----END PGP MESSAGE-----"
       +#define begin_pgpkey "-----BEGIN PGP PUBLIC KEY BLOCK-----"
       +#define end_pgpkey "-----END PGP PUBLIC KEY BLOCK-----"
       +#define begin_pgpseckey "-----BEGIN PGP PRIVATE KEY BLOCK-----"
       +#define end_pgpseckey "-----END PGP PRIVATE KEY BLOCK-----"
       +#define begin_pgpsigned "-----BEGIN PGP SIGNED MESSAGE-----"
       +#define begin_pgpsig "-----BEGIN PGP SIGNATURE-----"
       +#define end_pgpsig "-----END PGP SIGNATURE-----"
       +#define info_beginpgp "=====BEGIN PGP MESSAGE====="
       +#define info_endpgp "=====END PGP MESSAGE====="
       +#define info_pgpsig "=====Sig: "
       +
       +
       +/***********************************************************************
       + * The following variables are read from mix.cfg, with default values
       + * defined in mix.c */
       +
       +int REMAIL;
       +int MIX;
       +int PGP;
       +int UNENCRYPTED;
       +int REMIX;
       +int REPGP;
       +extern char MIXDIR[];
       +extern char POOLDIR[];
       +extern char EXTFLAGS[];
       +extern char SENDMAIL[];
       +extern char SENDANONMAIL[];
       +extern char PRECEDENCE[];
       +extern char SMTPRELAY[];
       +extern char SMTPUSERNAME[];
       +extern char SMTPPASSWORD[];
       +extern char NEWS[];
       +extern char MAILtoNEWS[];
       +extern char ORGANIZATION[];
       +extern char MID[];
       +extern char TYPE1[];
       +extern char ERRLOG[];
       +extern char NAME[];
       +extern char ADDRESS[];
       +extern char REMAILERADDR[];
       +extern char ANONADDR[];
       +extern char REMAILERNAME[];
       +extern char ANONNAME[];
       +extern char COMPLAINTS[];
       +extern int AUTOREPLY;
       +extern char HELONAME[];
       +extern char ENVFROM[];
       +extern char SHORTNAME[];
       +extern int POOLSIZE;
       +DLLIMPORT extern int RATE;
       +extern int INDUMMYP;
       +extern int OUTDUMMYP;
       +extern int MIDDLEMAN;
       +extern int AUTOBLOCK;
       +extern int STATSDETAILS;
       +extern char FORWARDTO[];
       +extern int SIZELIMIT;
       +extern int INFLATEMAX;
       +extern int MAXRANDHOPS;
       +extern int BINFILTER;
       +extern int LISTSUPPORTED;
       +extern long PACKETEXP;
       +extern long IDEXP;
       +DLLIMPORT extern int VERBOSE;
       +DLLIMPORT extern long SENDPOOLTIME;
       +extern long MAILINTIME;
       +extern long KEYLIFETIME;
       +extern long KEYOVERLAPPERIOD;
       +extern long KEYGRACEPERIOD;
       +extern int NUMCOPIES;
       +extern char CHAIN[];
       +extern int DISTANCE;
       +extern int MINREL;
       +extern int RELFINAL;
       +extern long MAXLAT;
       +extern long MINLAT;
       +DLLIMPORT extern char PGPPUBRING[];
       +DLLIMPORT extern char PGPSECRING[];
       +DLLIMPORT extern char PASSPHRASE[];
       +extern long POP3TIME;
       +extern int POP3DEL;
       +extern int POP3SIZELIMIT;
       +extern char MAILBOX[];
       +extern char MAILIN[];
       +extern char MAILABUSE[];
       +extern char MAILBLOCK[];
       +extern char MAILUSAGE[];
       +extern char MAILANON[];
       +extern char MAILERROR[];
       +extern char MAILBOUNCE[];
       +DLLIMPORT extern int CLIENTAUTOFLUSH;
       +extern int MAXRECIPIENTS;
       +extern long TIMESKEW_FORWARD;
       +extern long TIMESKEW_BACK;
       +extern int TEMP_FAIL;
       +extern char ALLPINGERSURL[];
       +extern char ALLPINGERSFILE[];
       +
       +extern char WGET[];
       +extern char STATSSRC[];
       +extern int STATSAUTOUPDATE;
       +extern long STATSINTERVAL;
       +
       +DLLIMPORT extern char ENTEREDPASSPHRASE[LINELEN];
       +
       +#endif
   DIR diff --git a/Src/crypto.c b/Src/crypto.c
       t@@ -0,0 +1,492 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Interface to cryptographic library
       +   $Id: crypto.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include "crypto.h"
       +#include <assert.h>
       +#include <string.h>
       +#include <time.h>
       +
       +#ifdef USE_OPENSSL
       +int digestmem_md5(byte *b, int n, BUFFER *md)
       +{
       +  byte m[MD5_DIGEST_LENGTH];
       +
       +  MD5(b, n, m);
       +  buf_reset(md);
       +  buf_append(md, m, MD5_DIGEST_LENGTH);
       +  return (0);
       +}
       +
       +int digest_md5(BUFFER *b, BUFFER *md)
       +{
       +  return (digestmem_md5(b->data, b->length, md));
       +}
       +
       +int isdigest_md5(BUFFER *b, BUFFER *md)
       +{
       +  int ret;
       +  BUFFER *newmd;
       +
       +  newmd = buf_new();
       +  digest_md5(b, newmd);
       +  ret = buf_eq(md, newmd);
       +  buf_free(newmd);
       +  return (ret);
       +}
       +
       +static int digestmem_sha1(byte *b, int n, BUFFER *md)
       +{
       +  byte m[SHA_DIGEST_LENGTH];
       +
       +  SHA1(b, n, m);
       +  buf_reset(md);
       +  buf_append(md, m, SHA_DIGEST_LENGTH);
       +  return (0);
       +}
       +
       +int digest_sha1(BUFFER *b, BUFFER *md)
       +{
       +  return (digestmem_sha1(b->data, b->length, md));
       +}
       +
       +static int digestmem_rmd160(byte *b, int n, BUFFER *md)
       +{
       +  byte m[RIPEMD160_DIGEST_LENGTH];
       +
       +  RIPEMD160(b, n, m);
       +  buf_reset(md);
       +  buf_append(md, m, RIPEMD160_DIGEST_LENGTH);
       +  return (0);
       +}
       +
       +int digest_rmd160(BUFFER *b, BUFFER *md)
       +{
       +  return (digestmem_rmd160(b->data, b->length, md));
       +}
       +
       +#define MAX_RSA_MODULUS_LEN 128
       +
       +static int read_seckey(BUFFER *buf, SECKEY *key, const byte id[])
       +{
       +  BUFFER *md;
       +  int bits;
       +  int len, plen;
       +  byte *ptr;
       +  int err = 0;
       +
       +  md = buf_new();
       +  bits = buf->data[0] + 256 * buf->data[1];
       +  len = (bits + 7) / 8;
       +  plen = (len + 1) / 2;
       +
       +  /* due to encryption, buffer size is multiple of 8 */
       +  if (3 * len + 5 * plen + 8 < buf->length || 3 * len + 5 * plen > buf->length)
       +    return (-1);
       +
       +  ptr = buf->data + 2;
       +
       +  key->n = BN_bin2bn(ptr, len, NULL);
       +  buf_append(md, ptr, len);
       +  ptr += len;
       +
       +  key->e = BN_bin2bn(ptr, len, NULL);
       +  buf_append(md, ptr, len);
       +  ptr += len;
       +
       +  key->d = BN_bin2bn(ptr, len, NULL);
       +  ptr += len;
       +
       +  key->p = BN_bin2bn(ptr, plen, NULL);
       +  ptr += plen;
       +
       +  key->q = BN_bin2bn(ptr, plen, NULL);
       +  ptr += plen;
       +
       +  key->dmp1 = BN_bin2bn(ptr, plen, NULL);
       +  ptr += plen;
       +
       +  key->dmq1 = BN_bin2bn(ptr, plen, NULL);
       +  ptr += plen;
       +
       +  key->iqmp = BN_bin2bn(ptr, plen, NULL);
       +  ptr += plen;
       +
       +  digest_md5(md, md);
       +  if (id)
       +    err = (memcmp(id, md->data, 16) == 0) ? 0 : -1;
       +  buf_free(md);
       +  return (err);
       +}
       +
       +static int read_pubkey(BUFFER *buf, PUBKEY *key, const byte id[])
       +{
       +  BUFFER *md;
       +  int bits;
       +  int len;
       +  byte *ptr;
       +  int err = 0;
       +
       +  md = buf_new();
       +  bits = buf->data[0] + 256 * buf->data[1];
       +  len = (bits + 7) / 8;
       +
       +  if (2 * len + 2 != buf->length)
       +    return (-1);
       +
       +  ptr = buf->data + 2;
       +
       +  key->n = BN_bin2bn(ptr, len, NULL);
       +  buf_append(md, ptr, len);
       +  ptr += len;
       +
       +  key->e = BN_bin2bn(ptr, len, NULL);
       +  buf_append(md, ptr, len);
       +  ptr += len;
       +
       +  digest_md5(md, md);
       +  if (id)
       +    err = (memcmp(id, md->data, 16) == 0) ? 0 : -1;
       +  buf_free(md);
       +  return (err);
       +}
       +
       +static int write_seckey(BUFFER *sk, SECKEY *key, byte keyid[])
       +{
       +  byte l[128];
       +  int n;
       +  BUFFER *b, *temp;
       +
       +  b = buf_new();
       +  temp = buf_new();
       +
       +  n = BN_bn2bin(key->n, l);
       +  assert(n <= 128);
       +  if (n < 128)
       +    buf_appendzero(b, 128 - n);
       +  buf_append(b, l, n);
       +
       +  n = BN_bn2bin(key->e, l);
       +  assert(n <= 128);
       +  if (n < 128)
       +    buf_appendzero(b, 128 - n);
       +  buf_append(b, l, n);
       +
       +  digest_md5(b, temp);
       +  memcpy(keyid, temp->data, 16);
       +
       +  buf_appendc(sk, 0);
       +  buf_appendc(sk, 4);
       +  buf_cat(sk, b);
       +
       +  n = BN_bn2bin(key->d, l);
       +  assert(n <= 128);
       +  if (n < 128)
       +    buf_appendzero(sk, 128 - n);
       +  buf_append(sk, l, n);
       +
       +  n = BN_bn2bin(key->p, l);
       +  assert(n <= 64);
       +  if (n < 64)
       +    buf_appendzero(sk, 64 - n);
       +  buf_append(sk, l, n);
       +
       +  n = BN_bn2bin(key->q, l);
       +  assert(n <= 64);
       +  if (n < 64)
       +    buf_appendzero(sk, 64 - n);
       +  buf_append(sk, l, n);
       +
       +  n = BN_bn2bin(key->dmp1, l);
       +  assert(n <= 64);
       +  if (n < 64)
       +    buf_appendzero(sk, 64 - n);
       +  buf_append(sk, l, n);
       +
       +  n = BN_bn2bin(key->dmq1, l);
       +  assert(n <= 64);
       +  if (n < 64)
       +    buf_appendzero(sk, 64 - n);
       +  buf_append(sk, l, n);
       +
       +  n = BN_bn2bin(key->iqmp, l);
       +  assert(n <= 64);
       +  if (n < 64)
       +    buf_appendzero(sk, 64 - n);
       +  buf_append(sk, l, n);
       +
       +  buf_pad(sk, 712);                /* encrypt needs a block size multiple of 8 */
       +
       +  buf_free(temp);
       +  buf_free(b);
       +  return (0);
       +}
       +
       +static int write_pubkey(BUFFER *pk, PUBKEY *key, byte keyid[])
       +{
       +  byte l[128];
       +  int n;
       +
       +  buf_appendc(pk, 0);
       +  buf_appendc(pk, 4);
       +  n = BN_bn2bin(key->n, l);
       +  assert(n <= 128);
       +  if (n < 128)
       +    buf_appendzero(pk, 128 - n);
       +  buf_append(pk, l, n);
       +  n = BN_bn2bin(key->e, l);
       +  assert(n <= 128);
       +  if (n < 128)
       +    buf_appendzero(pk, 128 - n);
       +  buf_append(pk, l, n);
       +  return (0);
       +}
       +
       +int seckeytopub(BUFFER *pub, BUFFER *sec, byte keyid[])
       +{
       +  RSA *k;
       +  int err = 0;
       +
       +  k = RSA_new();
       +  err = read_seckey(sec, k, keyid);
       +  if (err == 0)
       +    err = write_pubkey(pub, k, keyid);
       +  RSA_free(k);
       +  return (err);
       +}
       +
       +int check_pubkey(BUFFER *buf, const byte id[])
       +{
       +  RSA *tmp;
       +  int ret;
       +
       +  tmp = RSA_new();
       +  ret = read_pubkey(buf, tmp, id);
       +  RSA_free(tmp);
       +  return (ret);
       +}
       +
       +int check_seckey(BUFFER *buf, const byte id[])
       +{
       +  RSA *tmp;
       +  int ret;
       +
       +  tmp = RSA_new();
       +  ret = read_seckey(buf, tmp, id);
       +  RSA_free(tmp);
       +  return (ret);
       +}
       +
       +int v2createkey(void)
       +{
       +  RSA *k;
       +  BUFFER *b, *ek, *iv;
       +  int err;
       +  FILE *f;
       +  byte keyid[16];
       +  char line[33];
       +
       +  b = buf_new();
       +  ek = buf_new();
       +  iv = buf_new();
       +
       +  errlog(NOTICE, "Generating RSA key.\n");
       +  k = RSA_generate_key(1024, 65537, NULL, NULL);
       +  err = write_seckey(b, k, keyid);
       +  RSA_free(k);
       +  if (err == 0) {
       +    f = mix_openfile(SECRING, "a");
       +    if (f != NULL) {
       +      time_t now = time(NULL);
       +      struct tm *gt;
       +      gt = gmtime(&now);
       +      strftime(line, LINELEN, "%Y-%m-%d", gt);
       +      fprintf(f, "%s\nCreated: %s\n", begin_key, line);
       +      if (KEYLIFETIME) {
       +        now += KEYLIFETIME;
       +        gt = gmtime(&now);
       +        strftime(line, LINELEN, "%Y-%m-%d", gt);
       +        fprintf(f, "Expires: %s\n", line);
       +      }
       +      id_encode(keyid, line);
       +      buf_appends(ek, PASSPHRASE);
       +      digest_md5(ek, ek);
       +      buf_setrnd(iv, 8);
       +      buf_crypt(b, ek, iv, ENCRYPT);
       +      encode(b, 40);
       +      encode(iv, 0);
       +      fprintf(f, "%s\n0\n%s\n", line, iv->data);
       +      buf_write(b, f);
       +      fprintf(f, "%s\n\n", end_key);
       +      fclose(f);
       +    } else
       +      err = -1;
       +  }
       +  if (err != 0)
       +    errlog(ERRORMSG, "Key generation failed.\n");
       +
       +  buf_free(b);
       +  buf_free(ek);
       +  buf_free(iv);
       +  return (err);
       +}
       +
       +int pk_decrypt(BUFFER *in, BUFFER *keybuf)
       +{
       +  int err = 0;
       +  BUFFER *out;
       +  RSA *key;
       +
       +  out = buf_new();
       +  key = RSA_new();
       +  read_seckey(keybuf, key, NULL);
       +
       +  buf_prepare(out, in->length);
       +  out->length = RSA_private_decrypt(in->length, in->data, out->data, key,
       +                                    RSA_PKCS1_PADDING);
       +  if (out->length == -1)
       +    err = -1, out->length = 0;
       +
       +  RSA_free(key);
       +  buf_move(in, out);
       +  buf_free(out);
       +  return (err);
       +}
       +
       +int pk_encrypt(BUFFER *in, BUFFER *keybuf)
       +{
       +  BUFFER *out;
       +  RSA *key;
       +  int err = 0;
       +
       +  out = buf_new();
       +  key = RSA_new();
       +  read_pubkey(keybuf, key, NULL);
       +
       +  buf_prepare(out, RSA_size(key));
       +  out->length = RSA_public_encrypt(in->length, in->data, out->data, key,
       +                                   RSA_PKCS1_PADDING);
       +  if (out->length == -1)
       +    out->length = 0, err = -1;
       +  buf_move(in, out);
       +  buf_free(out);
       +  RSA_free(key);
       +  return (err);
       +}
       +int buf_crypt(BUFFER *buf, BUFFER *key, BUFFER *iv, int enc)
       +{
       +  des_key_schedule ks1;
       +  des_key_schedule ks2;
       +  des_key_schedule ks3;
       +  des_cblock i;
       +
       +  assert(enc == ENCRYPT || enc == DECRYPT);
       +  assert((key->length == 16 || key->length == 24) && iv->length == 8);
       +  assert(buf->length % 8 == 0);
       +
       +  memcpy(i, iv->data, 8);        /* leave iv buffer unchanged */
       +  des_set_key((const_des_cblock *) key->data, ks1);
       +  des_set_key((const_des_cblock *) (key->data + 8), ks2);
       +  if (key->length == 16)
       +    des_set_key((const_des_cblock *) key->data, ks3);
       +  else
       +    des_set_key((const_des_cblock *) (key->data + 16), ks3);
       +  des_ede3_cbc_encrypt(buf->data, buf->data, buf->length, ks1, ks2, ks3,
       +                       &i, enc);
       +  return (0);
       +}
       +
       +int buf_3descrypt(BUFFER *buf, BUFFER *key, BUFFER *iv, int enc)
       +{
       +  int n = 0;
       +  des_key_schedule ks1;
       +  des_key_schedule ks2;
       +  des_key_schedule ks3;
       +
       +  assert(enc == ENCRYPT || enc == DECRYPT);
       +  assert(key->length == 24 && iv->length == 8);
       +
       +  des_set_key((const_des_cblock *) key->data, ks1);
       +  des_set_key((const_des_cblock *) (key->data + 8), ks2);
       +  des_set_key((const_des_cblock *) (key->data + 16), ks3);
       +  des_ede3_cfb64_encrypt(buf->data, buf->data, buf->length, ks1, ks2, ks3,
       +                        (des_cblock *) iv->data, &n, enc);
       +  return (0);
       +}
       +
       +int buf_bfcrypt(BUFFER *buf, BUFFER *key, BUFFER *iv, int enc)
       +{
       +  int n = 0;
       +  BF_KEY ks;
       +
       +  if (key == NULL || key->length == 0)
       +    return (-1);
       +
       +  assert(enc == ENCRYPT || enc == DECRYPT);
       +  assert(key->length == 16 && iv->length == 8);
       +  BF_set_key(&ks, key->length, key->data);
       +  BF_cfb64_encrypt(buf->data, buf->data, buf->length, &ks, iv->data, &n,
       +                     enc == ENCRYPT ? BF_ENCRYPT : BF_DECRYPT);
       +  return (0);
       +}
       +
       +int buf_castcrypt(BUFFER *buf, BUFFER *key, BUFFER *iv, int enc)
       +{
       +  int n = 0;
       +  CAST_KEY ks;
       +
       +  if (key == NULL || key->length == 0)
       +    return (-1);
       +
       +  assert(enc == ENCRYPT || enc == DECRYPT);
       +  assert(key->length == 16 && iv->length == 8);
       +  CAST_set_key(&ks, 16, key->data);
       +  CAST_cfb64_encrypt(buf->data, buf->data, buf->length, &ks, iv->data, &n,
       +                     enc == ENCRYPT ? CAST_ENCRYPT : CAST_DECRYPT);
       +  return (0);
       +}
       +
       +#ifdef USE_AES
       +int buf_aescrypt(BUFFER *buf, BUFFER *key, BUFFER *iv, int enc)
       +{
       +  int n = 0;
       +  AES_KEY ks;
       +
       +  if (key == NULL || key->length == 0)
       +    return (-1);
       +
       +  assert(enc == ENCRYPT || enc == DECRYPT);
       +  assert((key->length == 16 || key->length == 24 || key->length == 32) && iv->length == 16);
       +  AES_set_encrypt_key(key->data, key->length<<3, &ks);
       +  AES_cfb128_encrypt(buf->data, buf->data, buf->length, &ks, iv->data, &n,
       +                     enc == ENCRYPT ? AES_ENCRYPT : AES_DECRYPT);
       +  return (0);
       +}
       +#endif /* USE_AES */
       +
       +#ifdef USE_IDEA
       +int buf_ideacrypt(BUFFER *buf, BUFFER *key, BUFFER *iv, int enc)
       +{
       +  int n = 0;
       +  IDEA_KEY_SCHEDULE ks;
       +
       +  if (key == NULL || key->length == 0)
       +    return (-1);
       +
       +  assert(enc == ENCRYPT || enc == DECRYPT);
       +  assert(key->length == 16 && iv->length == 8);
       +  idea_set_encrypt_key(key->data, &ks);
       +  idea_cfb64_encrypt(buf->data, buf->data, buf->length, &ks, iv->data, &n,
       +                     enc == ENCRYPT ? IDEA_ENCRYPT : IDEA_DECRYPT);
       +  return (0);
       +}
       +#endif /* USE_IDEA */
       +#endif /* USE_OPENSSL */
   DIR diff --git a/Src/crypto.h b/Src/crypto.h
       t@@ -0,0 +1,48 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Interface to cryptographic library
       +   $Id: crypto.h 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#ifndef _CRYPTO_H
       +#define _CRYPTO_H
       +#include "mix3.h"
       +
       +#ifdef USE_OPENSSL
       +#include <openssl/opensslv.h>
       +#if (OPENSSL_VERSION_NUMBER < 0x0903100)
       +#error "This version of OpenSSL is not supported. Please get a more current version from http://www.openssl.org"
       +#endif /* version check */
       +#include <openssl/des.h>
       +#include <openssl/blowfish.h>
       +#include <openssl/md5.h>
       +#include <openssl/sha.h>
       +#include <openssl/ripemd.h>
       +#include <openssl/bn.h>
       +#include <openssl/dh.h>
       +#include <openssl/dsa.h>
       +#include <openssl/rsa.h>
       +#ifdef USE_IDEA
       +#include <openssl/idea.h>
       +#endif /* USE_IDEA */
       +#ifdef USE_AES
       +#include <openssl/aes.h>
       +#endif /* USE_AES */
       +#include <openssl/cast.h>
       +#include <openssl/rand.h>
       +
       +typedef RSA PUBKEY;
       +typedef RSA SECKEY;
       +
       +#else /* end of USE_OPENSSL */
       +/* #error "No crypto library." */
       +typedef void PUBKEY;
       +typedef void SECKEY;
       +#endif /* else not USE_OPENSSL */
       +
       +#endif /* ifndef _CRYPTO_H */
   DIR diff --git a/Src/dllmain.c b/Src/dllmain.c
       t@@ -0,0 +1,35 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Mixmaster DLL startup
       +   $Id: dllmain.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#ifdef WIN32
       +int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
       +{
       +  switch (fdwReason) {
       +  case DLL_PROCESS_ATTACH:
       +    if(!is_nt_service()) {
       +      rnd_state = RND_WILLSEED;
       +      mix_init(NULL);
       +      if (rnd_state == RND_WILLSEED)
       +        rnd_state = RND_NOTSEEDED;
       +    }
       +    break;
       +  case DLL_PROCESS_DETACH:
       +    if(!is_nt_service())
       +      mix_exit();
       +    break;
       +  case DLL_THREAD_ATTACH:
       +  case DLL_THREAD_DETACH:
       +    return(0);
       +  }
       +  return(1);
       +}
       +#endif /* WIN32 */
   DIR diff --git a/Src/dummy.c b/Src/dummy.c
       t@@ -0,0 +1,16 @@
       +/* Dummy function for programs that don't use menuutil.c */
       +
       +#include "mix3.h"
       +
       +int menu_getuserpass(BUFFER *b, int i)
       +{
       +  return -1;
       +}
       +
       +void cl(int y, int x)
       +{}
       +
       +int download_stats(char *sourcename)
       +{
       +    return -1;
       +}
   DIR diff --git a/Src/keymgt.c b/Src/keymgt.c
       t@@ -0,0 +1,434 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Key management
       +   $Id: keymgt.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include <string.h>
       +#include <time.h>
       +#include <assert.h>
       +
       +int getv2seckey(byte keyid[], BUFFER *key);
       +static int getv2pubkey(byte keyid[], BUFFER *key);
       +
       +int db_getseckey(byte keyid[], BUFFER *key)
       +{
       +  if (getv2seckey(keyid, key) == -1)
       +    return (-1);
       +  else
       +    return (0);
       +}
       +
       +int db_getpubkey(byte keyid[], BUFFER *key)
       +{
       +  if (getv2pubkey(keyid, key) == -1)
       +    return (-1);
       +  else
       +    return (0);
       +}
       +
       +/* now accepts NULL keyid too, with NULL keyid any key
       + * will be matched, with valid passphrase of course */
       +int getv2seckey(byte keyid[], BUFFER *key)
       +{
       +  FILE *keyring;
       +  BUFFER *iv, *pass, *temp;
       +  char idstr[KEY_ID_LEN+2];
       +  char line[LINELEN];
       +  int err = -1;
       +  char *res;
       +  time_t created, expires;
       +
       +  pass = buf_new();
       +  iv = buf_new();
       +  temp = buf_new();
       +  if (keyid)
       +    id_encode(keyid, idstr);
       +  else
       +    idstr[0] = 0;
       +  strcat(idstr, "\n");
       +  if ((keyring = mix_openfile(SECRING, "r")) == NULL) {
       +    errlog(ERRORMSG, "No secret key file!\n");
       +  } else {
       +    while (err == -1) {
       +      buf_clear(key);
       +      if (fgets(line, sizeof(line), keyring) == NULL)
       +        break;
       +      if (strleft(line, begin_key)) {
       +        expires = 0;
       +        created = 0;
       +        do {
       +          res = fgets(line, sizeof(line), keyring);
       +          if (strileft(line, "created:")) {
       +            created = parse_yearmonthday(strchr(line, ':')+1);
       +            if (created == -1)
       +              created = 0;
       +          } else if (strileft(line, "expires:")) {
       +            expires = parse_yearmonthday(strchr(line, ':')+1);
       +            if (expires == -1)
       +              expires = 0;
       +          }
       +          /* Fetch lines until we fail or get a non-header line */
       +        } while ( res != NULL && strchr(line, ':') != NULL );
       +        if (res == NULL)
       +          break;
       +        if (keyid && (strncmp(line, idstr, KEY_ID_LEN) != 0))
       +          continue;
       +        if (created != 0 && (created > time(NULL))) {
       +          errlog(ERRORMSG, "Key is not valid yet (creation date in the future): %s", idstr);
       +          break;
       +        }
       +        if (expires != 0 && (expires + KEYGRACEPERIOD < time(NULL))) {
       +          errlog(ERRORMSG, "Key is expired: %s", idstr);
       +          break;
       +        }
       +        fgets(line, sizeof(line), keyring);
       +        fgets(line, sizeof(line), keyring);
       +        buf_sets(iv, line);
       +        decode(iv, iv);
       +        for (;;) {
       +          if (fgets(line, sizeof(line), keyring) == NULL)
       +            break;
       +          if (strleft(line, end_key)) {
       +            if (decode(key, key) == -1) {
       +              errlog(ERRORMSG, "Corrupt secret key.\n");
       +              break;
       +            }
       +            buf_sets(pass, PASSPHRASE);
       +            digest_md5(pass, pass);
       +            buf_crypt(key, pass, iv, DECRYPT);
       +            err = check_seckey(key, keyid);
       +            if (err == -1)
       +              errlog(ERRORMSG, "Corrupt secret key. Bad passphrase?\n");
       +            break;
       +          }
       +          buf_append(key, line, strlen(line) - 1);
       +        }
       +        break;
       +      }
       +    }
       +    fclose(keyring);
       +  }
       +
       +  buf_free(pass);
       +  buf_free(iv);
       +  buf_free(temp);
       +  return (err);
       +}
       +
       +static int getv2pubkey(byte keyid[], BUFFER *key)
       +{
       +  FILE *keyring;
       +  BUFFER *b, *temp, *iv;
       +  char idstr[KEY_ID_LEN+2];
       +  char line[LINELEN];
       +  int err = 0;
       +
       +  b = buf_new();
       +  iv = buf_new();
       +  temp = buf_new();
       +  id_encode(keyid, idstr);
       +  if ((keyring = mix_openfile(PUBRING, "r")) == NULL) {
       +    errlog(ERRORMSG, "Can't open %s!\n", PUBRING);
       +    err = -1;
       +    goto end;
       +  }
       +  for (;;) {
       +    if (fgets(line, sizeof(line), keyring) == NULL)
       +      break;
       +    if (strleft(line, begin_key)) {
       +      if (fgets(line, sizeof(line), keyring) == NULL)
       +        break;
       +      if ((strlen(line) > 0) && (line[strlen(line)-1] == '\n'))
       +        line[strlen(line)-1] = '\0';
       +      if ((strlen(line) > 0) && (line[strlen(line)-1] == '\r'))
       +        line[strlen(line)-1] = '\0';
       +      if (strncmp(line, idstr, KEY_ID_LEN) != 0)
       +        continue;
       +      fgets(line, sizeof(line), keyring);        /* ignore length */
       +      for (;;) {
       +        if (fgets(line, sizeof(line), keyring) == NULL)
       +          goto done;
       +        if (strleft(line, end_key))
       +          goto done;
       +        buf_append(key, line, strlen(line));
       +      }
       +      break;
       +    }
       +  }
       +done:
       +  fclose(keyring);
       +
       +  if (key->length == 0) {
       +    errlog(ERRORMSG, "No such public key: %s\n", idstr);
       +    err = -1;
       +    goto end;
       +  }
       +  err = decode(key, key);
       +  if (err != -1)
       +    err = check_pubkey(key, keyid);
       +  if (err == -1)
       +    errlog(ERRORMSG, "Corrupt public key %s\n", idstr);
       +end:
       +  buf_free(b);
       +  buf_free(iv);
       +  buf_free(temp);
       +  return (err);
       +}
       +
       +int key(BUFFER *out)
       +{
       +  int err = -1;
       +  FILE *f;
       +  BUFFER *tmpkey;
       +
       +  tmpkey = buf_new();
       +
       +  buf_sets(out, "Subject: Remailer key for ");
       +  buf_appends(out, SHORTNAME);
       +  buf_appends(out, "\n\n");
       +
       +  keymgt(0);
       +
       +  conf_premail(out);
       +  buf_nl(out);
       +
       +#ifdef USE_PGP
       +  if (PGP) {
       +    if (pgp_latestkeys(tmpkey, PGP_ES_RSA) == 0) {
       +      buf_appends(out, "Here is the RSA PGP key:\n\n");
       +      buf_cat(out, tmpkey);
       +      buf_nl(out);
       +      err = 0;
       +    }
       +    if (pgp_latestkeys(tmpkey, PGP_S_DSA) == 0) {
       +      buf_appends(out, "Here is the DSA PGP key:\n\n");
       +      buf_cat(out, tmpkey);
       +      buf_nl(out);
       +      err = 0;
       +    }
       +  }
       +#endif /* USE_PGP */
       +  if (MIX) {
       +    if ((f = mix_openfile(KEYFILE, "r")) != NULL) {
       +      buf_appends(out, "Here is the Mixmaster key:\n\n");
       +      buf_appends(out, "=-=-=-=-=-=-=-=-=-=-=-=\n");
       +      buf_read(out, f);
       +      buf_nl(out);
       +      fclose(f);
       +      err = 0;
       +    }
       +  }
       +  if (err == -1 && UNENCRYPTED) {
       +    buf_appends(out, "The remailer accepts unencrypted messages.\n");
       +    err = 0;
       +  }
       +  if (err == -1)
       +    errlog(ERRORMSG, "Cannot create remailer keys!");
       +
       +  buf_free(tmpkey);
       +
       +  return (err);
       +}
       +
       +int adminkey(BUFFER *out)
       +{
       +        int err = -1;
       +        FILE *f;
       +
       +        buf_sets( out, "Subject: Admin key for the " );
       +        buf_appends( out, SHORTNAME );
       +        buf_appends( out, " remailer\n\n" );
       +
       +        if ( (f = mix_openfile( ADMKEYFILE, "r" )) != NULL ) {
       +                buf_read( out, f );
       +                buf_nl( out );
       +                fclose( f );
       +                err = 0;
       +        }
       +
       +        if ( err == -1 )
       +                errlog( ERRORMSG, "Can not read admin key file!\n" );
       +
       +        return err;
       +}
       +
       +int v2keymgt(int force)
       +/*
       + * Mixmaster v2 Key Management
       + *
       + * This function triggers creation of mix keys (see parameter force) which are
       + * stored in secring.mix. One public mix key is also written to key.txt. This
       + * is the key with the latest expiration date (keys with no expiration date
       + * are always considered newer if they appear later in the secret mix file 
       + * - key creation appends keys).
       + *
       + * force:
       + *   0, 1: create key when necessary:
       + *          - no key exists as of yet
       + *          - old keys are due to expire/already expired
       + *   2: always create a new mix key.
       + *
       + *   (force = 0 is used in mix_daily, and before remailer-key replies)
       + *   (force = 1 is used by mixmaster -K)
       + *   (force = 2 is used by mixmaster -G)
       + */
       +{
       +  FILE *keyring, *f;
       +  char line[LINELEN];
       +  byte k1[16], k1_found[16];
       +  BUFFER *b, *temp, *iv, *pass, *pk, *pk_found;
       +  int err = 0;
       +  int found, foundnonexpiring;
       +  time_t created, expires, created_found, expires_found;
       +  char *res;
       +
       +  b = buf_new();
       +  temp = buf_new();
       +  iv = buf_new();
       +  pass = buf_new();
       +  pk = buf_new();
       +  pk_found = buf_new();
       +
       +  foundnonexpiring = 0;
       +  for (;;) {
       +    found = 0;
       +    created_found = 0;
       +    expires_found = 0;
       +
       +    keyring = mix_openfile(SECRING, "r");
       +    if (keyring != NULL) {
       +      for (;;) {
       +        if (fgets(line, sizeof(line), keyring) == NULL)
       +          break;
       +        if (strleft(line, begin_key)) {
       +          expires = 0;
       +          created = 0;
       +          do {
       +            res = fgets(line, sizeof(line), keyring);
       +            if (strileft(line, "created:")) {
       +              created = parse_yearmonthday(strchr(line, ':')+1);
       +              if (created == -1)
       +                created = 0;
       +            } else if (strileft(line, "expires:")) {
       +              expires = parse_yearmonthday(strchr(line, ':')+1);
       +              if (expires == -1)
       +                expires = 0;
       +            }
       +            /* Fetch lines until we fail or get a non-header line */
       +          } while ( res != NULL && strchr(line, ':') != NULL );
       +          if (res == NULL)
       +            break;
       +          if (((created != 0) && (created > time(NULL))) ||
       +              ((expires != 0) && (expires < time(NULL)))) {
       +            /* Key already is expired or has creation date in the future */
       +            continue;
       +          }
       +          id_decode(line, k1);
       +          fgets(line, sizeof(line), keyring);
       +          if (fgets(line, sizeof(line), keyring) == NULL)
       +            break;
       +          buf_sets(iv, line);
       +          decode(iv, iv);
       +          buf_reset(b);
       +          for (;;) {
       +            if (fgets(line, sizeof(line), keyring) == NULL)
       +              break;
       +            if (strleft(line, end_key))
       +              break;
       +            buf_append(b, line, strlen(line) - 1);
       +          }
       +          if (decode(b, b) == -1)
       +            break;
       +          buf_sets(temp, PASSPHRASE);
       +          digest_md5(temp, pass);
       +          buf_crypt(b, pass, iv, DECRYPT);
       +          buf_clear(pk);
       +          if (seckeytopub(pk, b, k1) == 0) {
       +            found = 1;
       +            if (expires == 0 || (expires - KEYOVERLAPPERIOD >= time(NULL)))
       +              foundnonexpiring = 1;
       +            if (expires == 0 || (expires_found <= expires)) {
       +              buf_clear(pk_found);
       +              buf_cat(pk_found, pk);
       +              memcpy(&k1_found, &k1, sizeof(k1));
       +              expires_found = expires;
       +              created_found = created;
       +            }
       +          }
       +        }
       +      }
       +      fclose(keyring);
       +    }
       +
       +    if (!foundnonexpiring || (force == 2)) {
       +      v2createkey();
       +      foundnonexpiring = 1;
       +      force = 1;
       +    } else
       +      break;
       +  };
       +
       +  if (found) {
       +    if ((f = mix_openfile(KEYFILE, "w")) != NULL) {
       +      id_encode(k1_found, line);
       +      fprintf(f, "%s %s %s %s:%s %s%s", SHORTNAME,
       +              REMAILERADDR, line, mixmaster_protocol, VERSION,
       +              MIDDLEMAN ? "M" : "",
       +              NEWS[0] == '\0' ? "C" : (strchr(NEWS, '@') ? "CNm" : "CNp"));
       +      if (created_found) {
       +        struct tm *gt;
       +        gt = gmtime(&created_found);
       +        strftime(line, LINELEN, "%Y-%m-%d", gt);
       +        fprintf(f, " %s", line);
       +        if (expires_found) {
       +          struct tm *gt;
       +          gt = gmtime(&expires_found);
       +          strftime(line, LINELEN, "%Y-%m-%d", gt);
       +          fprintf(f, " %s", line);
       +        }
       +      }
       +      fprintf(f, "\n\n%s\n", begin_key);
       +      id_encode(k1_found, line);
       +      fprintf(f, "%s\n258\n", line);
       +      encode(pk_found, 40);
       +      buf_write(pk_found, f);
       +      fprintf(f, "%s\n\n", end_key);
       +      fclose(f);
       +    }
       +  } else
       +    err = -1;
       +
       +  buf_free(b);
       +  buf_free(temp);
       +  buf_free(iv);
       +  buf_free(pass);
       +  buf_free(pk);
       +  buf_free(pk_found);
       +
       +  return (err);
       +}
       +
       +int keymgt(int force)
       +{
       +  /* force = 0: write key file if there is none
       +     force = 1: update key file
       +     force = 2: generate new key */
       +  int err = 0;
       +
       +  if (REMAIL || force == 2) {
       +    if (MIX && (err = v2keymgt(force)) == -1)
       +      err = -1;
       +#ifdef USE_PGP
       +    if (PGP && (err = pgp_keymgt(force)) == -1)
       +      err = -1;
       +#endif /* USE_PGP */
       +  }
       +  return (err);
       +}
   DIR diff --git a/Src/mail.c b/Src/mail.c
       t@@ -0,0 +1,898 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Socket-based mail transport services
       +   $Id: mail.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +
       +#if defined(UNIX) && defined(USE_SOCK)
       +#include <unistd.h>
       +#include <sys/types.h>
       +#include <sys/socket.h>
       +#include <netinet/in.h>
       +#include <arpa/inet.h>
       +#include <netdb.h>
       +#endif /* defined(UNIX) && defined(USE_SOCK) */
       +
       +#include <fcntl.h>
       +#include <time.h>
       +#include <sys/stat.h>
       +#include <errno.h>
       +
       +
       +int sendinfofile(char *name, char *logname, BUFFER *address, BUFFER *header)
       +{
       +  FILE *f = NULL, *log = NULL;
       +  BUFFER *msg, *addr;
       +  char line[LINELEN];
       +  int ret = -1;
       +
       +  if (bufeq(address, ANONNAME))
       +    return (0);                        /* don't reply to our own anon messages */
       +  f = mix_openfile(name, "r");
       +  if (f == NULL)
       +    return (-1);
       +
       +  addr = buf_new();
       +  rfc822_addr(address, addr);
       +  if (addr->length == 0)
       +    buf_set(addr, address), buf_nl(addr);
       +
       +  if (logname != NULL) {
       +    if ((log = mix_openfile(logname, "r+")) != NULL) {
       +      /* log recipients to prevent mail loop */
       +      while (fgets(line, sizeof(line), log) != NULL)
       +        if (strieq(line, addr->data))
       +          goto end;
       +    } else if ((log = mix_openfile(logname, "w")) == NULL) {
       +      errlog(ERRORMSG, "Can't create %s.\n", logname);
       +      ret = -1;
       +      goto end;
       +    }
       +    fprintf(log, "%s", addr->data);
       +  }
       +  msg = buf_new();
       +  if (header)
       +    buf_cat(msg, header), buf_nl(msg);
       +  while (fgets(line, sizeof(line), f) != NULL) {
       +    if (streq(line, "DESTINATION-BLOCK\n"))
       +      buf_appendf(msg, "destination-block %b", addr);
       +    else
       +      buf_appends(msg, line);
       +  }
       +  ret = sendmail(msg, REMAILERNAME, address);
       +  buf_free(msg);
       +end:
       +  if (f)
       +    fclose(f);
       +  if (log)
       +    fclose(log);
       +  buf_free(addr);
       +  return (ret);
       +}
       +
       +int smtpsend(BUFFER *head, BUFFER *message, char *from);
       +
       +
       +int sendmail_loop(BUFFER *message, char *from, BUFFER *address)
       +{
       +  BUFFER *msg;
       +  int err;
       +
       +  msg = buf_new();
       +  buf_appendf(msg, "X-Loop: %s\n", REMAILERADDR);
       +  buf_cat(msg, message);
       +  err = sendmail(msg, from, address);
       +  buf_free(msg);
       +
       +  return(err);
       +}
       +
       +/* Returns true if more than one of the recipients in the
       + * rcpt buffer is a remailer
       + */
       +int has_more_than_one_remailer(BUFFER *rcpts)
       +{
       +  BUFFER *newlinelist;
       +  BUFFER *line;
       +  int remailers = 0;
       +  REMAILER type1[MAXREM];
       +  REMAILER type2[MAXREM];
       +  int num1;
       +  int num2;
       +  int i;
       +
       +  newlinelist = buf_new();
       +  line = buf_new();
       +
       +  num1 = t1_rlist(type1, NULL);
       +  num2 = mix2_rlist(type2, NULL);
       +
       +  rfc822_addr(rcpts, newlinelist);
       +
       +  while (buf_getline(newlinelist, line) != -1) {
       +    int found = 0;
       +    printf("%s\n", line->data);
       +
       +    for (i = 0; i < num2; i++)
       +      if (strcmp(type2[i].addr, line->data) == 0) {
       +        found = 1;
       +        break;
       +      }
       +    if (!found)
       +      for (i = 0; i < num1; i++)
       +        if (strcmp(type1[i].addr, line->data) == 0) {
       +          found = 1;
       +          break;
       +        }
       +    if (found)
       +      remailers++;
       +  }
       +  printf("found %d\n", remailers);
       +
       +  buf_free(newlinelist);
       +  buf_free(line);
       +
       +  return(remailers > 1);
       +}
       +
       +int sendmail(BUFFER *message, char *from, BUFFER *address)
       +{
       +  /* returns: 0: ok  1: problem, try again  -1: failed */
       +
       +  BUFFER *head, *block, *rcpt;
       +  FILE *f;
       +  int err = -1;
       +  int rcpt_cnt;
       +
       +  head = buf_new();
       +  rcpt = buf_new();
       +
       +  block = readdestblk( );
       +  if ( !block ) block = buf_new( );
       +
       +  if (address != NULL &&
       +      (address->length == 0 || doblock(address, block, 1) == -1))
       +    goto end;
       +
       +  if (from != NULL) {
       +    buf_setf(head, "From: %s", from);
       +    hdr_encode(head, 255);
       +    buf_nl(head);
       +  }
       +  if (address != NULL)
       +    buf_appendf(head, "To: %b\n", address);
       +
       +  if (PRECEDENCE[0])
       +        buf_appendf(head, "Precedence: %s\n", PRECEDENCE);
       +
       +  buf_rewind(message);
       +
       +  /* search recipient addresses */
       +  if (address == NULL) {
       +    BUFFER *field, *content;
       +    field = buf_new();
       +    content = buf_new();
       +
       +    rcpt_cnt = 0;
       +    while (buf_getheader(message, field, content) == 0) {
       +      if (bufieq(field, "to") || bufieq(field, "cc") || bufieq(field, "bcc")) {
       +        int thislinercpts = 1;
       +        char *tmp = content->data;
       +        while ((tmp = strchr(tmp+1, ',')))
       +          thislinercpts ++;
       +        rcpt_cnt += thislinercpts;
       +
       +        if ( rcpt->data[0] )
       +          buf_appends(rcpt, ", ");
       +        buf_cat(rcpt, content);
       +      }
       +    }
       +    buf_free(field);
       +    buf_free(content);
       +  } else if (address->data[0]) {
       +    char *tmp = address->data;
       +    rcpt_cnt = 1;
       +    while ((tmp = strchr(tmp+1, ',')))
       +      rcpt_cnt ++;
       +
       +    buf_set(rcpt, address);
       +  } else
       +    rcpt_cnt = 0;
       +
       +  buf_rewind(message);
       +
       +  if ( ! rcpt_cnt ) {
       +    errlog(NOTICE, "No recipients found.\n");
       +    err = 0;
       +  } else if ( rcpt_cnt > MAXRECIPIENTS ) { 
       +    errlog(NOTICE, "Too many recipients.  Dropping message.\n");
       +    err = 0;
       +  } else if ( rcpt_cnt > 1 && has_more_than_one_remailer(rcpt) ) {
       +    errlog(NOTICE, "Message is destined to more than one remailer.  Dropping.\n");
       +    err = 0;
       +  } else if ( REMAIL && strcmp(REMAILERADDR, rcpt->data) == 0) {
       +    buf_cat(head, message);
       +    errlog(LOG, "Message loops back to us; storing in pool rather than sending it.\n");
       +    err = pool_add(head, "inf");
       +  } else if (SMTPRELAY[0])
       +    err = smtpsend(head, message, from);
       +  else if (strieq(SENDMAIL, "outfile")) {
       +    char path[PATHMAX];
       +    FILE *f = NULL;
       +#ifdef SHORTNAMES
       +    int i;
       +    for (i = 0; i < 10000; i++) {
       +      snprintf(path, PATHMAX, "%s%cout%i.txt", POOLDIR, DIRSEP, i);
       +      f = fopen(path, "r");
       +      if (f)
       +        fclose(f);
       +      else
       +        break;
       +    }
       +    f = fopen(path, "w");
       +#else /* end of SHORTNAMES */
       +    static unsigned long namecounter = 0;
       +    struct stat statbuf;
       +    int count;
       +    char hostname[64];
       +
       +    hostname[0] = '\0';
       +    gethostname(hostname, 63);
       +    hostname[63] = '\0';
       +
       +    /* Step 2:  Stat the file.  Wait for ENOENT as a response. */
       +    for (count = 0;; count++) {
       +      snprintf(path, PATHMAX, "%s%cout.%lu.%u_%lu.%s,S=%lu.txt",
       +        POOLDIR, DIRSEP, time(NULL), getpid(), namecounter++, hostname, head->length + message->length);
       +
       +      if (stat(path, &statbuf) == 0)
       +        errno = EEXIST;
       +      else if (errno == ENOENT) { /* create the file (at least try) */
       +        f = fopen(path, "w");
       +        if (f != NULL)
       +          break; /* we managed to open the file */
       +      }
       +      if (count > 5)
       +        break; /* Too many retries - give up */
       +      sleep(2); /* sleep and retry */
       +    }
       +#endif /* else not SHORTNAMES */
       +    if (f != NULL) {
       +      err = buf_write(head, f);
       +      err = buf_write(message, f);
       +      fclose(f);
       +    } else
       +      errlog(ERRORMSG, "Can't create %s!\n", path);
       +  } else {
       +    if (SENDANONMAIL[0] != '\0' && (from == NULL || streq(from, ANONNAME)))
       +      f = openpipe(SENDANONMAIL);
       +    else
       +      f = openpipe(SENDMAIL);
       +    if (f != NULL) {
       +      err = buf_write(head, f);
       +      err = buf_write(message, f);
       +      closepipe(f);
       +    }
       +  }
       +  if (err != 0) {
       +    errlog(ERRORMSG, "Unable to execute sendmail. Check path!\n");
       +    err = 1;                        /* error while sending, retry later */
       +  }
       +
       +end:
       +  buf_free(block);
       +  buf_free(head);
       +  buf_free(rcpt);
       +  return (err);
       +}
       +
       +/* socket communication **********************************************/
       +
       +#ifdef USE_SOCK
       +#ifdef WIN32
       +WSADATA w;
       +
       +int sock_init()
       +{
       +  if (WSAStartup(MAKEWORD(2, 0), &w) != 0) {
       +    errlog(ERRORMSG, "Unable to initialize WINSOCK.\n");
       +    return 0;
       +  }
       +  return 1;
       +}
       +
       +void sock_exit(void)
       +{
       +  WSACleanup();
       +}
       +#endif /* WIN32 */
       +
       +SOCKET opensocket(char *hostname, int port)
       +{
       +  struct hostent *hp;
       +  struct sockaddr_in server;
       +  SOCKET s;
       +
       +  if ((hp = gethostbyname(hostname)) == NULL)
       +    return (INVALID_SOCKET);
       +
       +  memset((char *) &server, 0, sizeof(server));
       +  server.sin_family = AF_INET;
       +  server.sin_addr.s_addr = *(unsigned long *) hp->h_addr;
       +  server.sin_port = htons((unsigned short) port);
       +
       +  s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
       +  if (s != INVALID_SOCKET)
       +    if (connect(s, (struct sockaddr *) &server, sizeof(server)) < 0) {
       +      closesocket(s);
       +      return (INVALID_SOCKET);
       +    }
       +  return (s);
       +}
       +
       +#ifndef WIN32
       +int closesocket(SOCKET s)
       +{
       +  return (close(s));
       +}
       +#endif /* ifndef WIN32 */
       +
       +int sock_getline(SOCKET s, BUFFER *line)
       +{
       +  char c;
       +  int ok;
       +
       +  buf_clear(line);
       +  while ((ok = recv(s, &c, 1, 0)) > 0) {
       +    if (c == '\n')
       +      break;
       +    if (c != '\r')
       +      buf_appendc(line, c);
       +  }
       +  if (ok <= 0)
       +    return (-1);
       +  if (line->length == 0)
       +    return (1);
       +  return (0);
       +}
       +
       +int sock_cat(SOCKET s, BUFFER *b)
       +{
       +  int p = 0, n;
       +
       +  do {
       +    n = send(s, b->data, b->length, 0);
       +    if (n < 0)
       +      return (-1);
       +    p += n;
       +  } while (p < b->length);
       +  return (0);
       +}
       +#else /* end of USE_SOCK */
       +SOCKET opensocket(char *hostname, int port)
       +{
       +  return (INVALID_SOCKET);
       +}
       +
       +int closesocket(SOCKET s)
       +{
       +  return (INVALID_SOCKET);
       +}
       +
       +int sock_getline(SOCKET s, BUFFER *line)
       +{
       +  return (-1);
       +}
       +
       +int sock_cat(SOCKET s, BUFFER *b)
       +{
       +  return (-1);
       +}
       +#endif /* else not USE_SOCK */
       +
       +/* send messages by SMTP ************************************************/
       +
       +static int sock_getsmtp(SOCKET s, BUFFER *response)
       +{
       +  int ret;
       +  BUFFER *line;
       +  line = buf_new();
       +
       +  buf_clear(response);
       +  do {
       +    ret = sock_getline(s, line);
       +    buf_cat(response, line);
       +  } while (line->length >= 4 && line->data[3] == '-');
       +  buf_free(line);
       +  return (ret);
       +}
       +
       +SOCKET smtp_open(void)
       +{
       +  int s = INVALID_SOCKET;
       +  int esmtp = 0;
       +  BUFFER *line;
       +
       +#ifdef USE_SOCK
       +  if (SMTPRELAY[0] != '\0')
       +    s = opensocket(SMTPRELAY, 25);
       +  if (s != INVALID_SOCKET) {
       +    line = buf_new();
       +    sock_getsmtp(s, line);
       +    if (bufifind(line, "ESMTP"))
       +      esmtp = 1;
       +    if (line->data[0] != '2') {
       +      errlog(ERRORMSG, "SMTP relay not ready. %b\n", line);
       +      closesocket(s);
       +      s = INVALID_SOCKET;
       +    } else {
       +      errlog(DEBUGINFO, "Opening SMTP connection.\n");
       +      if (esmtp)
       +        buf_sets(line, "EHLO ");
       +      else
       +        buf_sets(line, "HELO ");
       +      if (HELONAME[0])
       +        buf_appends(line, HELONAME);
       +      else if (strchr(ENVFROM, '@'))
       +        buf_appends(line, strchr(ENVFROM, '@') + 1);
       +      else {
       +        struct sockaddr_in sa;
       +        int len = sizeof(sa);
       +        struct hostent *hp;
       +
       +        if (getsockname(s, (struct sockaddr *) &sa, &len) == 0 &&
       +            (hp = gethostbyaddr((char *) &sa.sin_addr, sizeof(sa.sin_addr),
       +                                AF_INET)) != NULL)
       +          buf_appends(line, (char *) hp->h_name);
       +        else if (strchr(REMAILERADDR, '@'))
       +          buf_appends(line, strchr(REMAILERADDR, '@') + 1);
       +        else
       +          buf_appends(line, SHORTNAME);
       +      }
       +      buf_chop(line);
       +      buf_appends(line, "\r\n");
       +      sock_cat(s, line);
       +      sock_getsmtp(s, line);
       +      if (line->data[0] != '2') {
       +        errlog(ERRORMSG, "SMTP relay refuses HELO: %b\n", line);
       +        closesocket(s);
       +        s = INVALID_SOCKET;
       +      } else if (SMTPUSERNAME[0] && esmtp && bufifind(line, "AUTH") && bufifind(line, "LOGIN")) {
       +        buf_sets(line, "AUTH LOGIN\r\n");
       +        sock_cat(s, line);
       +        sock_getsmtp(s, line);
       +        if (!bufleft(line, "334")) {
       +          errlog(ERRORMSG, "SMTP AUTH fails: %b\n", line);
       +          goto err;
       +        }
       +        buf_sets(line, SMTPUSERNAME);
       +        encode(line, 0);
       +        buf_appends(line, "\r\n");
       +        sock_cat(s, line);
       +        sock_getsmtp(s, line);
       +        if (!bufleft(line, "334")) {
       +          errlog(ERRORMSG, "SMTP username rejected: %b\n", line);
       +          goto err;
       +        }
       +        buf_sets(line, SMTPPASSWORD);
       +        encode(line, 0);
       +        buf_appends(line, "\r\n");
       +        sock_cat(s, line);
       +        sock_getsmtp(s, line);
       +        if (!bufleft(line, "235"))
       +          errlog(ERRORMSG, "SMTP authentication failed: %b\n", line);
       +      }
       +    }
       +err:
       +    buf_free(line);
       +  }
       +#endif /* USE_SOCK */
       +  return (s);
       +}
       +
       +int smtp_close(SOCKET s)
       +{
       +  BUFFER *line;
       +  int ret = -1;
       +
       +#ifdef USE_SOCK
       +  line = buf_new();
       +  buf_sets(line, "QUIT\r\n");
       +  sock_cat(s, line);
       +  if (sock_getsmtp(s, line) == 0 && line->data[0] == '2') {
       +    errlog(DEBUGINFO, "Closing SMTP connection.\n");
       +    ret = 0;
       +  } else
       +    errlog(WARNING, "SMTP quit failed: %b\n", line);
       +  closesocket(s);
       +  buf_free(line);
       +#endif /* USE_SOCK */
       +  return (ret);
       +}
       +
       +int smtp_send(SOCKET relay, BUFFER *head, BUFFER *message, char *from)
       +{
       +  BUFFER *rcpt, *line, *field, *content;
       +  int ret = -1;
       +
       +#ifdef USE_SOCK
       +  line = buf_new();
       +  field = buf_new();
       +  content = buf_new();
       +  rcpt = buf_new();
       +
       +  while (buf_getheader(head, field, content) == 0)
       +    if (bufieq(field, "to"))
       +#ifdef BROKEN_MTA
       +      if (!bufifind(rcpt, content->data))
       +      /* Do not add the same recipient twice.
       +         Needed for brain-dead MTAs.      */
       +#endif /* BROKEN_MTA */
       +        rfc822_addr(content, rcpt);
       +  buf_rewind(head);
       +
       +  while (buf_isheader(message) && buf_getheader(message, field, content) == 0) {
       +    if (bufieq(field, "to") || bufieq(field, "cc") || bufieq(field, "bcc")) {
       +#ifdef BROKEN_MTA
       +      if (!bufifind(rcpt, content->data))
       +      /* Do not add the same recipient twice.
       +         Needed for brain-dead MTAs.      */
       +#endif /* BROKEN_MTA */
       +        rfc822_addr(content, rcpt);
       +    }
       +    if (!bufieq(field, "bcc"))
       +      buf_appendheader(head, field, content);
       +  }
       +  buf_nl(head);
       +
       +  buf_clear(content);
       +  if (from) {
       +    buf_sets(line, from);
       +    rfc822_addr(line, content);
       +    buf_chop(content);
       +  }
       +  if (bufieq(content, REMAILERADDR) || bufieq(content, ANONADDR))
       +    buf_clear(content);
       +  if (content->length == 0)
       +    buf_sets(content, ENVFROM[0] ? ENVFROM : ANONADDR);
       +
       +  buf_setf(line, "MAIL FROM:<%b>\r\n", content);
       +  sock_cat(relay, line);
       +  sock_getsmtp(relay, line);
       +  if (!line->data[0] == '2') {
       +    errlog(ERRORMSG, "SMTP relay does not accept mail: %b\n", line);
       +    goto end;
       +  }
       +  while (buf_getline(rcpt, content) == 0) {
       +    buf_setf(line, "RCPT TO:<%b>\r\n", content);
       +    sock_cat(relay, line);
       +    sock_getsmtp(relay, line);
       +    if (bufleft(line, "421")) {
       +      errlog(ERRORMSG, "SMTP relay error: %b\n", line);
       +      goto end;
       +    }
       +    if (bufleft(line, "530")) {
       +      errlog(ERRORMSG, "SMTP authentication required: %b\n", line);
       +      goto end;
       +    }
       +  }
       +
       +  buf_sets(line, "DATA\r\n");
       +  sock_cat(relay, line);
       +  sock_getsmtp(relay, line);
       +  if (!bufleft(line, "354")) {
       +    errlog(WARNING, "SMTP relay does not accept message: %b\n", line);
       +    goto end;
       +  }
       +  while (buf_getline(head, line) >= 0) {
       +    buf_appends(line, "\r\n");
       +    if (bufleft(line, ".")) {
       +      buf_setf(content, ".%b", line);
       +      buf_move(line, content);
       +    }
       +    sock_cat(relay, line);
       +  }
       +  while (buf_getline(message, line) >= 0) {
       +    buf_appends(line, "\r\n");
       +    if (bufleft(line, ".")) {
       +      buf_setf(content, ".%b", line);
       +      buf_move(line, content);
       +    }
       +    sock_cat(relay, line);
       +  }
       +  buf_sets(line, ".\r\n");
       +  sock_cat(relay, line);
       +  sock_getsmtp(relay, line);
       +  if (bufleft(line, "2"))
       +    ret = 0;
       +  else
       +    errlog(WARNING, "SMTP relay will not send message: %b\n", line);
       +end:
       +  buf_free(line);
       +  buf_free(field);
       +  buf_free(content);
       +  buf_free(rcpt);
       +#endif /* USE_SOCK */
       +  return (ret);
       +}
       +
       +static SOCKET sendmail_state = INVALID_SOCKET;
       +
       +void sendmail_begin(void)
       +{
       +  /* begin mail sending session */
       +  if (sendmail_state == INVALID_SOCKET)
       +    sendmail_state = smtp_open();
       +}
       +void sendmail_end(void)
       +{
       +  /* end mail sending session */
       +  if (sendmail_state != INVALID_SOCKET) {
       +    smtp_close(sendmail_state);
       +    sendmail_state = INVALID_SOCKET;
       +  }
       +}
       +
       +int smtpsend(BUFFER *head, BUFFER *message, char *from)
       +{
       +  SOCKET s;
       +  int ret = -1;
       +
       +  if (sendmail_state != INVALID_SOCKET)
       +    ret = smtp_send(sendmail_state, head, message, from);
       +  else {
       +    s = smtp_open();
       +    if (s != INVALID_SOCKET) {
       +      ret = smtp_send(s, head, message, from);
       +      smtp_close(s);
       +    }
       +  }
       +  return (ret);
       +}
       +
       +/* retrieve mail with POP3 **********************************************/
       +#ifdef USE_SOCK
       +int pop3_close(SOCKET s);
       +
       +#define POP3_ANY 0
       +#define POP3_APOP 1
       +#define POP3_PASS 2
       +
       +SOCKET pop3_open(char *user, char *host, char *pass, int auth)
       +{
       +  SOCKET server = INVALID_SOCKET;
       +  BUFFER *line;
       +  int authenticated = 0;
       +  char md[33];
       +  int c;
       +
       +  line = buf_new();
       +  server = opensocket(host, 110);
       +  if (server == INVALID_SOCKET)
       +    errlog(NOTICE, "Can't connect to POP3 server %s.\n", host);
       +  else {
       +    sock_getline(server, line);
       +    if (!bufleft(line, "+")) {
       +      errlog(WARNING, "No POP3 service at %s.\n", host);
       +      closesocket(server);
       +      server = INVALID_SOCKET;
       +    }
       +  }
       +  if (server != INVALID_SOCKET) {
       +    errlog(DEBUGINFO, "Opening POP3 connection to %s.\n", host);
       +    do
       +      c = buf_getc(line);
       +    while (c != '<' && c != -1);
       +    while (c != '>' && c != -1) {
       +      buf_appendc(line, c);
       +      c = buf_getc(line);
       +    }
       +    if (c == '>' && (auth == POP3_ANY || auth == POP3_APOP)) {
       +      buf_appendc(line, c);
       +      buf_appends(line, pass);
       +      digest_md5(line, line);
       +      id_encode(line->data, md);
       +      buf_setf(line, "APOP %s %s\r\n", user, md);
       +      sock_cat(server, line);
       +      sock_getline(server, line);
       +      if (bufleft(line, "+"))
       +        authenticated = 1;
       +      else {
       +          errlog(auth == POP3_APOP ? ERRORMSG : NOTICE,
       +                 "POP3 APOP auth at %s failed: %b\n", host, line);
       +        buf_sets(line, "QUIT\r\n");
       +        sock_cat(server, line);
       +        closesocket(server);
       +        server = pop3_open(user, host, pass, POP3_PASS);
       +        goto end;
       +      }
       +    }
       +    if (!authenticated) {
       +      buf_setf(line, "USER %s\r\n", user);
       +      sock_cat(server, line);
       +      sock_getline(server, line);
       +      if (!bufleft(line, "+"))
       +        errlog(ERRORMSG, "POP3 USER command at %s failed: %b\n", host, line);
       +      else {
       +        buf_setf(line, "PASS %s\r\n", pass);
       +        sock_cat(server, line);
       +        sock_getline(server, line);
       +        if (bufleft(line, "+"))
       +          authenticated = 1;
       +        else
       +          errlog(ERRORMSG, "POP3 auth at %s failed: %b\n", host, line);
       +      }
       +    }
       +    if (!authenticated) {
       +      pop3_close(server);
       +      closesocket(server);
       +      server = INVALID_SOCKET;
       +    }
       +  }
       + end:
       +  buf_free(line);
       +  return (server);
       +}
       +
       +int pop3_close(SOCKET s)
       +{
       +  BUFFER *line;
       +  int ret = -1;
       +
       +  line = buf_new();
       +  buf_sets(line, "QUIT\r\n");
       +  sock_cat(s, line);
       +  sock_getline(s, line);
       +  if (bufleft(line, "+")) {
       +    ret = 0;
       +    errlog(DEBUGINFO, "Closing POP3 connection.\n");
       +  } else
       +    errlog(ERRORMSG, "POP3 QUIT failed:\n", line->data);
       +  buf_free(line);
       +  return (ret);
       +}
       +
       +int pop3_stat(SOCKET s)
       +{
       +  BUFFER *line;
       +  int val = -1;
       +
       +  line = buf_new();
       +  buf_sets(line, "STAT\r\n");
       +  sock_cat(s, line);
       +  sock_getline(s, line);
       +  if (bufleft(line, "+"))
       +    sscanf(line->data, "+%*s %d", &val);
       +  buf_free(line);
       +  return (val);
       +}
       +
       +int pop3_list(SOCKET s, int n)
       +{
       +  BUFFER *line;
       +  int val = -1;
       +
       +  line = buf_new();
       +  buf_setf(line, "LIST %d\r\n", n);
       +  sock_cat(s, line);
       +  sock_getline(s, line);
       +  if (bufleft(line, "+"))
       +    sscanf(line->data, "+%*s %d", &val);
       +  buf_free(line);
       +  return (val);
       +}
       +
       +int pop3_dele(SOCKET s, int n)
       +{
       +  BUFFER *line;
       +  int ret = 0;
       +
       +  line = buf_new();
       +  buf_setf(line, "DELE %d\r\n", n);
       +  sock_cat(s, line);
       +  sock_getline(s, line);
       +  if (!bufleft(line, "+"))
       +    ret = -1;
       +  buf_free(line);
       +  return (ret);
       +}
       +
       +int pop3_retr(SOCKET s, int n, BUFFER *msg)
       +{
       +  BUFFER *line;
       +  int ret = -1;
       +
       +  line = buf_new();
       +  buf_clear(msg);
       +  buf_setf(line, "RETR %d\r\n", n);
       +  sock_cat(s, line);
       +  sock_getline(s, line);
       +  if (bufleft(line, "+")) {
       +    for (;;) {
       +      if (sock_getline(s, line) == -1)
       +        break;
       +      if (bufeq(line, ".")) {
       +        ret = 0;
       +        break;
       +      } else if (bufleft(line, ".")) {
       +        buf_append(msg, line->data + 1, line->length - 1);
       +      } else
       +        buf_cat(msg, line);
       +      buf_nl(msg);
       +    }
       +  }
       +  buf_free(line);
       +  return (ret);
       +}
       +
       +void pop3get(void)
       +{
       +  FILE *f;
       +  char cfg[LINELEN], user[LINELEN], host[LINELEN], pass[LINELEN], auth[5];
       +  SOCKET server;
       +  BUFFER *line, *msg;
       +  int i = 0, num = 0;
       +
       +  line = buf_new();
       +  msg = buf_new();
       +  f = mix_openfile(POP3CONF, "r");
       +  if (f != NULL)
       +    while (fgets(cfg, sizeof(cfg), f) != NULL) {
       +      if (cfg[0] == '#')
       +        continue;
       +      if (strchr(cfg, '@'))
       +        strchr(cfg, '@')[0] = ' ';
       +      if (sscanf(cfg, "%127s %127s %127s %4s", user, host, pass, auth) < 3)
       +        continue;
       +      i = POP3_ANY;
       +      if (strileft(auth, "apop"))
       +        i = POP3_APOP;
       +      if (strileft(auth, "pass"))
       +        i = POP3_PASS;
       +      server = pop3_open(user, host, pass, i);
       +      if (server != INVALID_SOCKET) {
       +        num = pop3_stat(server);
       +        if (num < 0)
       +          errlog(WARNING, "POP3 protocol error at %s.\n", host);
       +        else if (num == 0)
       +          errlog(DEBUGINFO, "No mail at %s.\n", host);
       +        else
       +          for (i = 1; i <= num; i++) {
       +            if (POP3SIZELIMIT > 0 &&
       +                pop3_list(server, i) > POP3SIZELIMIT * 1024) {
       +              errlog(WARNING, "Over size message on %s.", host);
       +              if (POP3DEL == 1)
       +                pop3_dele(server, i);
       +            } else {
       +              if (pop3_retr(server, i, msg) == 0 &&
       +                  pool_add(msg, "inf") == 0)
       +                pop3_dele(server, i);
       +              else {
       +                errlog(WARNING, "POP3 error while getting mail from %s.",
       +                       host);
       +                closesocket(server);
       +                goto end;
       +              }
       +            }
       +          }
       +        pop3_close(server);
       +        closesocket(server);
       +      }
       +    }
       + end:
       +  if (f != NULL)
       +    fclose(f);
       +  buf_free(line);
       +  buf_free(msg);
       +}
       +#endif /* USE_SOCK */
   DIR diff --git a/Src/maildir.c b/Src/maildir.c
       t@@ -0,0 +1,323 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Maildir support routines
       +   $Id: $ */
       +
       +
       +/* Maildir support for Mixmaster 3 - see
       +   http://www.qmail.org/man/man5/maildir.html and
       +   http://cr.yp.to/proto/maildir.html
       +
       +   Added by and (C) 2001 Doobee R. Tzeck 
       +   drt@un.bewaff.net - http://c0re.jp/
       +
       +   To test it try:
       +   $ gcc maildir.c -DUNITTEST -o test_maildir
       +   $ ./test_maildir
       +   this should print a single line saying "OK"
       +*/
       +
       +#include "mix3.h"
       +
       +#ifdef WIN32
       +#include <io.h>
       +#include <direct.h>
       +#include <process.h>
       +#define S_IWUSR _S_IWRITE
       +#define S_IRUSR _S_IREAD
       +#else /* end of WIN32 */
       +#include <unistd.h>
       +#endif /* else not WIN32 */
       +#include <fcntl.h>
       +#include <time.h>
       +#include <string.h>
       +#include <sys/stat.h>
       +#include <sys/types.h>
       +#include <errno.h>
       +#include <stdarg.h>
       +#include <assert.h>
       +
       +#if defined(S_IFDIR) && !defined(S_ISDIR)
       +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
       +#endif /* defined(S_IFDIR) && !defined(S_ISDIR) */
       +
       +#ifndef SHORTNAMES
       +
       +static unsigned long namecounter = 0;
       +
       +int checkDirectory(char *dir, char *append, int create) {
       +  char tmp[PATHMAX];
       +  struct stat buf;
       +  int err;
       +
       +  tmp[0] = '\0';
       +  strcatn(tmp, dir, PATHMAX);
       +  if (append)
       +    strcatn(tmp, append, PATHMAX);
       +
       +  err = stat(tmp, &buf);
       +  if (err == -1) {
       +    if (create) {
       +#ifndef POSIX
       +      err = mkdir(tmp);
       +#else /* end of not POSIX */
       +      err = mkdir(tmp, S_IRWXU);
       +#endif /* else if POSIX */
       +      if (err == 0)
       +        errlog(NOTICE, "Creating directory %s.\n", tmp);
       +    } else
       +      err = 1;
       +  } else if (!S_ISDIR(buf.st_mode))
       +    err = -1;
       +
       +  return err;
       +}
       +
       +/* Write "message" to "maildir", retunr 0 on success, -1 on failure */
       +#define MAX_BASENAME 113 /* actual length should be smaller than 111 bytes */
       +#define MAX_SUBNAME 123 /* actual length should be smaller than 115 bytes */
       +int maildirWrite(char *maildir, BUFFER *message, int create) {
       +  int fd;
       +  int count;
       +  int returnValue;
       +  char hostname[64];
       +  struct stat statbuf;
       +  char basename[MAX_BASENAME];
       +  char tmpname[MAX_SUBNAME];
       +  char newname[MAX_SUBNAME];
       +  int messagesize;
       +  char olddirectory[PATHMAX] = "";
       +  char normalizedmaildir[PATHMAX];
       +
       +  /* Declare a handler for SIGALRM so we can time out. */
       +  /* set_handler(SIGALRM, alarm_handler);  */
       +  /* alarm(86400); */
       +
       +  hostname[0] = '\0';
       +  gethostname(hostname, 63);
       +  hostname[63] = '\0';
       +
       +  mixfile(normalizedmaildir, maildir);
       +  if ((checkDirectory(normalizedmaildir, NULL, create) != 0) ||
       +      (checkDirectory(normalizedmaildir, "tmp", create) != 0) ||
       +      (checkDirectory(normalizedmaildir, "cur", create) != 0) ||
       +      (checkDirectory(normalizedmaildir, "new", create) != 0)) {
       +    returnValue = -1;
       +    goto realend;
       +  }
       +
       +  messagesize = message->length;
       +
       +  /* Step 1: chdir to maildir (and save current dir) */
       +  if (getcwd(olddirectory, PATHMAX) == NULL) {
       +    returnValue = -1;
       +    goto realend;
       +  }
       +  olddirectory[PATHMAX-1] = '\0';
       +  if(chdir(normalizedmaildir) != 0) {
       +    returnValue = -1;
       +    goto functionExit;
       +  }
       +
       +  /* Step 2:  Stat the temporary file.  Wait for ENOENT as a response. */
       +  for (count = 0;; count++) {
       +    tmpname[0] = '\0';
       +    newname[0] = '\0';
       +    snprintf(basename, MAX_BASENAME, "%lu.%u_%lu.%s,S=%u",
       +      time(NULL), getpid(), namecounter++, hostname, messagesize);
       +    basename[MAX_BASENAME-1] = '\0';
       +    strcatn(tmpname, "tmp" DIRSEPSTR, MAX_SUBNAME);
       +    strcatn(tmpname, basename, MAX_SUBNAME);
       +    strcatn(newname, "new" DIRSEPSTR, MAX_SUBNAME);
       +    strcatn(newname, basename, MAX_SUBNAME);
       +
       +    if (stat(tmpname, &statbuf) == 0)
       +      errno = EEXIST;
       +    else if (errno == ENOENT) {
       +      /* Step 4: create the file (at least try) */
       +      fd = open(tmpname, O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR);
       +      if (fd >= 0)
       +        break; /* we managed to open the file */
       +    }
       +
       +    if (count > 5) {
       +      /* Too many retries - give up */
       +      errlog(ERRORMSG, "Can't create message in %s\n", maildir);
       +      returnValue = -1;
       +      goto functionExit;
       +    }
       +
       +    /* Step 3: sleep and retry */
       +    sleep(2);
       +  }
       +
       +  /* Step 5:  write file */
       +  if(write(fd, message->data, message->length) != message->length) {
       +    returnValue = -1;
       +    goto functionExit;
       +  }
       +
       +  /* on NFS this could fail */
       +#ifndef WIN32
       +  if((fsync(fd) != 0) || (close(fd) != 0)) {
       +#else /* end of not WIN32 */
       +  if((_commit(fd) != 0) || (close(fd) != 0)) {
       +#endif /* else if WIN32 */
       +    returnValue = -1;
       +    goto functionExit;
       +  }
       +
       +  /* Step 6: move message to 'cur' */
       +#ifdef POSIX
       +  for (count = 0;; count++) {
       +    if(link(tmpname, newname) != 0) {
       +      if (errno == EXDEV || errno == EPERM) {
       +        /* We probably are on coda or some other filesystem that does not allow
       +         * hardlinks. rename() the file instead of link() and unlink()
       +         * I know, It's evil (PP).
       +         */
       +        if (rename(tmpname, newname) != 0) {
       +          returnValue = -1;
       +          goto functionExit;
       +        };
       +        break;
       +      } else if (errno != EEXIST) {
       +        returnValue = -1;
       +        goto functionExit;
       +      }
       +    } else {
       +      /* We successfully linked the message in new/. Now let's get
       +       * rid of our tmp/ entry
       +       */
       +      if(unlink(tmpname) != 0) {
       +        /* unlinking failed */
       +        returnValue = -1;
       +        goto functionExit;
       +      }
       +      break;
       +    }
       +
       +    if (count > 5) {
       +      /* Too many retries - give up */
       +      errlog(ERRORMSG, "Can't move message to %s/new/\n", maildir);
       +      returnValue = -1;
       +      goto functionExit;
       +    }
       +
       +    sleep(2);
       +    newname[0] = '\0';
       +    snprintf(basename, MAX_BASENAME, "%lu.%u_%lu.%s,S=%u",
       +      time(NULL), getpid(), namecounter++, hostname, messagesize);
       +    basename[MAX_BASENAME-1] = '\0';
       +    strcatn(newname, "new" DIRSEPSTR, MAX_SUBNAME);
       +    strcatn(newname, basename, MAX_SUBNAME);
       +  }
       +#else /* end of POSIX */
       +  /* On non POSIX systems we simply use rename(). Let's hope DJB
       +   * never finds out
       +   */
       +  if (rename(tmpname, newname) != 0) {
       +    returnValue = -1;
       +    goto functionExit;
       +  };
       +#endif /* else if not POSIX */
       +
       +  returnValue = 0;
       +
       +functionExit:
       +  /* return to original directory */
       +  assert(olddirectory[0] != '\0');
       +  if(chdir(olddirectory) != 0)
       +    returnValue = -1;
       +
       +realend:
       +
       +  return returnValue;
       +}
       +
       +#else /* end of SHORTNAMES */
       +int maildirWrite(char *maildir, BUFFER *message, int create) {
       +{
       +  errlog(ERRORMSG, "Maildir delivery does not work with SHORTNAMES.\n");
       +  return -1;
       +}
       +#endif /* else if not SHORTNAMES */
       +
       +
       +#ifdef UNITTEST
       +
       +#ifdef NDEBUG
       +#undef NDEBUG
       +#endif /* NDEBUG */
       +
       +#include <dirent.h>
       +
       +/* mock-up of errlog for unittest */
       +void errlog(int type, char *fmt,...)
       +{
       +  va_list ap;
       +
       +  va_start(ap, fmt);
       +  vfprintf(stderr, fmt, ap);
       +  va_end(ap);
       +}
       +
       +/* main for unittest */
       +int main()
       +{
       +  int i, count = 23;
       +  int fd;
       +  DIR *d;
       +  struct dirent *de;
       +  BUFFER message;
       +  char text[] = "From: nobody@un.bewaff.net\nTo: hackers@c0re.jp\nSubject: testing\n\nthis is just a test\n";
       +  char buf[1024];
       +
       +  /* create buffer with test data */
       +  message.data = text;
       +  message.length = strlen(text);
       +
       +  /* write <count> messages to maildir */
       +  for(i = 0; i < count; i++)
       +    assert(maildirWrite("Maildir.test_maildir", message, 1) == 0);
       +
       +  /* read them back */
       +  assert((d = opendir("Maildir.test_maildir/new")) != NULL);
       +  for (i = 0; i < count + 2; i++)
       +    {
       +      de = readdir(d);
       +      if(de->d_name[0] != '.')
       +        {
       +          buf[0] = '\0';
       +          strcat(buf, "Maildir.test_maildir/new/");
       +          strcat(buf, de->d_name);
       +          fd = open(buf, O_RDONLY);
       +          assert(unlink(buf) == 0);
       +          assert(read(fd, buf, strlen(text)) == strlen(text));
       +          buf[strlen(text)] = '\0';
       +          /* check if they match the original message */
       +          assert(strcmp(text, buf) == 0);
       +          close(fd);
       +        }
       +    }
       +
       +  /* no files left in directory? */
       +  assert(readdir(d) == NULL);
       +
       +  /* delete maildir */
       +  assert(rmdir("Maildir.test_maildir/tmp") == 0);
       +  assert(rmdir("Maildir.test_maildir/new") == 0);
       +  assert(rmdir("Maildir.test_maildir/cur") == 0);
       +  assert(rmdir("Maildir.test_maildir") == 0);
       +
       +  /* check if writing to a non existant maildir yilds an error */
       +  assert(maildirWrite("Maildir.test_maildir", &message, 0) == -1);
       +
       +  puts("OK");
       +}
       +#endif /* UNITTEST */
   DIR diff --git a/Src/main.c b/Src/main.c
       t@@ -0,0 +1,820 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Command-line based frontend
       +   $Id: main.c 937 2006-06-24 15:52:20Z colin $ */
       +
       +
       +#include "mix3.h"
       +#include "pgp.h"
       +#include <stdio.h>
       +#include <string.h>
       +#include <ctype.h>
       +#include <stdlib.h>
       +#ifdef POSIX
       +#include <unistd.h>
       +#else /* end of POSIX */
       +#include <io.h>
       +#endif /* else if not POSIX */
       +#include <assert.h>
       +
       +static char *largopt(char *p, char *opt, char *name, int *error);
       +static void noarg(char *name, char p);
       +static int check_get_pass(int force, int never_ask_for_passphrase);
       +
       +/** main *****************************************************************/
       +
       +/* Returns:
       + 0 successful operation
       + 1 command line error
       + 2 client error condition */
       +
       +#ifdef WIN32SERVICE
       +int mix_main(int argc, char *argv[])
       +#else
       +int main(int argc, char *argv[])
       +#endif /* WIN32SERVICE */
       +{
       +  int error = 0, deflt = 1, help = 0, readmail = 0, send = -1, sendpool = 0,
       +  header = 1, maint = 0, keygen = 0, verbose = 0, sign = 0, encrypt = 0,
       +  redirect_mail = 0, about=0, version=0;
       +  int daemon = 0, type_list = 0, nodetach = 0;
       +  int update_stats = 0, update_pingerlist = 0;
       +  int never_ask_for_passphrase = 0;
       +
       +#ifdef USE_SOCK
       +  int pop3 = 0;
       +
       +#endif /* USE_SOCK */
       +  char *filename = NULL;
       +  int i;
       +  int ret = 0;
       +  char *p, *q;
       +  char chain[1024] = "";
       +  char nym[LINELEN] = "";
       +  BUFFER *nymopt, *pseudonym, *attachments, *statssrc;
       +  int numcopies = 0;                /* default value set in mix.cfg */
       +  BUFFER *msg, *chainlist, *field, *content;
       +  FILE *f;
       +  char pingpath[PATHMAX];
       +
       +  /* Check if parse_yearmonthday works */
       +  assert(parse_yearmonthday("2003-04-01") == 1049155200);
       +
       +  mix_init(NULL);
       +
       +  msg = buf_new();
       +  chainlist = buf_new();
       +  nymopt = buf_new();
       +  pseudonym = buf_new();
       +  attachments = buf_new();
       +  field = buf_new();
       +  content = buf_new();
       +  statssrc = buf_new();
       +
       +#ifdef USE_NCURSES
       +  if (argc == 1) {
       +    if (isatty(fileno(stdin)))
       +      menu_main();
       +    else
       +      menu_folder(0, NULL);
       +    goto clientpool;
       +  }
       +#endif /* USE_NCURSES */
       +  if (argc > 1 && strleft(argv[1], "-f")) {
       +    menu_folder(strlen(argv[1]) > 2 ? argv[1][2] : 0, argc < 3 ? NULL : argv[2]);
       +    goto clientpool;
       +  }
       +  for (i = 1; i < argc; i++) {
       +    p = argv[i];
       +    if (p[0] == '-' && p[1] != '\0') {
       +      if (p[1] == '-') {
       +        p += 2;
       +        if (strieq(p, "help"))
       +          help = 1, deflt = 0;
       +        else if (streq(p, "version"))
       +          version = 1, deflt = 0;
       +        else if (streq(p, "about"))
       +          about = 1, deflt = 0;
       +        else if (streq(p, "verbose"))
       +          verbose = 1;
       +        else if (streq(p, "type-list"))
       +          type_list = 1;
       +        else if (streq(p, "dummy"))
       +          send = MSG_NULL, deflt = 0;
       +        else if (streq(p, "remailer"))
       +          maint = 1, deflt = 0;
       +        else if (streq(p, "generate-key"))
       +          keygen = 2, deflt = 0;
       +        else if (streq(p, "update-keys"))
       +          keygen = 1, deflt = 0;
       +        else if (streq(p, "send"))
       +          sendpool = 1, deflt = 0;
       +        else if (streq(p, "read-mail"))
       +          readmail = 1, deflt = 0;
       +        else if (streq(p, "redirect"))
       +          redirect_mail = 1, deflt = 0;
       +        else if (streq(p, "store-mail"))
       +          readmail = 2, deflt = 0;
       +#ifdef USE_SOCK
       +        else if (streq(p, "pop-mail"))
       +          pop3 = 1, deflt = 0;
       +#endif /* USE_SOCK */
       +        else if (streq(p, "daemon"))
       +          daemon = 1, deflt = 0;
       +        else if (streq(p, "no-detach"))
       +          nodetach = 1;
       +        else if (streq(p, "post"))
       +          send = MSG_POST;
       +        else if (streq(p, "mail"))
       +          send = MSG_MAIL;
       +        else if (streq(p, "sign"))
       +          sign = 1;
       +        else if (streq(p, "encrypt"))
       +          encrypt = 1;
       +        else if (streq(p, "no-ask-passphrase"))
       +          never_ask_for_passphrase = 1;
       +        else if (streq(p, "update-pinger-list"))
       +          update_pingerlist = 1;
       +        else if (streq(p, "update-stats")) {
       +          buf_clear(statssrc);
       +          f = mix_openfile(STATSSRC, "r");
       +          if (f != NULL) {
       +            buf_read(statssrc, f);
       +            fclose(f);
       +          }
       +          if (statssrc->length > 0) {
       +            update_stats = 1;
       +          } else {
       +            deflt = 0;
       +            fprintf(stderr, "%s: No current stats source --%s\n", argv[0], p);
       +          }
       +        } else if (strleft(p, "update-stats") && p[strlen("update-stats")] == '=') {
       +          buf_clear(statssrc);
       +          buf_appendf(statssrc, "%s", (p + strlen("update-stats") + 1));
       +          if (statssrc->length > 0) {
       +            update_stats = 1;
       +          } else {
       +            fprintf(stderr, "%s: No stats source specified --%s\n", argv[0], p);
       +          }
       +        } else if ((q = largopt(p, "to", argv[0], &error)) != NULL) {
       +          header = 0;
       +          buf_appendf(msg, "To: %s\n", q);
       +        } else if ((q = largopt(p, "post-to", argv[0], &error)) != NULL) {
       +          send = MSG_POST, header = 0;
       +          buf_appendf(msg, "Newsgroups: %s\n", q);
       +        } else if ((q = largopt(p, "subject", argv[0], &error)) != NULL) {
       +          buf_appendf(msg, "Subject: %s\n", q);
       +        } else if ((q = largopt(p, "header", argv[0], &error)) != NULL) {
       +          buf_appendf(msg, "%s\n", q);
       +        } else if ((q = largopt(p, "chain", argv[0], &error)) != NULL) {
       +          buf_appendf(msg, "Chain: %s\n", q);
       +        }
       +#ifdef USE_PGP
       +        else if ((q = largopt(p, "reply-chain", argv[0], &error)) != NULL) {
       +          buf_appendf(msg, "Reply-Chain: %s\n", q);
       +        } else if ((q = largopt(p, "latency", argv[0], &error)) != NULL) {
       +          buf_appendf(msg, "Latency: %s\n", q);
       +        } else if ((q = largopt(p, "attachment", argv[0], &error)) != NULL) {
       +          buf_appendf(attachments, "%s\n", q);
       +#ifdef NYMSUPPORT
       +        } else if ((q = largopt(p, "nym-config", argv[0], &error)) != NULL) {
       +          deflt = 0;
       +          strncpy(nym, q, sizeof(nym));
       +          if (i > argc && strileft(argv[i + 1], "name="))
       +            buf_sets(pseudonym, argv[++i] + 5);
       +          else if (i > argc && strileft(argv[i + 1], "opt="))
       +            buf_appends(nymopt, argv[++i] + 5);
       +        } else if ((q = largopt(p, "nym", argv[0], &error)) != NULL) {
       +          buf_appendf(msg, "Nym: %s\n", q);
       +#endif /* NYMSUPPORT */
       +        }
       +#endif /* USE_PGP */
       +        else if ((q = largopt(p, "copies", argv[0], &error)) != NULL) {
       +          sscanf(q, "%d", &numcopies);
       +        } else if ((q = largopt(p, "config", argv[0], &error)) != NULL) {
       +          strncpy(MIXCONF, q, PATHMAX);
       +          MIXCONF[PATHMAX-1] = 0;
       +          mix_config(); /* configuration file changed - reread it */
       +        } else if (error == 0 && mix_configline(p) == 0) {
       +          fprintf(stderr, "%s: Invalid option %s\n", argv[0], argv[i]);
       +          error = 1;
       +        }
       +      } else {
       +        while (*++p) {
       +          switch (*p) {
       +          case 'd':
       +            send = MSG_NULL, deflt = 0;
       +            break;
       +          case 'R':
       +            readmail = 1, deflt = 0;
       +            break;
       +          case 'I':
       +            readmail = 2, deflt = 0;
       +            break;
       +          case 'S':
       +            sendpool = 1, deflt = 0;
       +            break;
       +          case 'M':
       +            maint = 1, deflt = 0;
       +            break;
       +#ifdef USE_SOCK
       +          case 'P':
       +            pop3 = 1, deflt = 0;
       +            break;
       +#endif /* USE_SOCK */
       +          case 'D':
       +            daemon = 1, deflt = 0;
       +            break;
       +          case 'G':
       +            keygen = 2, deflt = 0;
       +            break;
       +          case 'K':
       +            keygen = 1, deflt = 0;
       +            break;
       +          case 'L':                /* backwards compatibility */
       +            break;
       +          case 'v':
       +            verbose = 1;
       +            break;
       +          case 'h':
       +            help = 1, deflt = 0;
       +            break;
       +          case 'T':
       +            type_list = 1;
       +            break;
       +          case 'V':
       +            version = 1, deflt = 0;
       +            break;
       +          case 't':
       +            if (*(p + 1) == 'o')
       +              p++;
       +            header = 0;
       +            if (i < argc - 1)
       +              buf_appendf(msg, "To: %s\n", argv[++i]);
       +            else {
       +              fprintf(stderr, "%s: Missing argument for option -to\n", argv[0]);
       +              error = 1;
       +            }
       +            break;
       +          case 's':
       +            if (i < argc - 1)
       +              buf_appendf(msg, "Subject: %s\n", argv[++i]);
       +            else {
       +              noarg(argv[0], *p);
       +              error = 1;
       +            }
       +            break;
       +          case 'l':
       +            if (i < argc - 1)
       +              buf_appendf(msg, "Chain: %s\n", argv[++i]);
       +            else {
       +              noarg(argv[0], *p);
       +              error = 1;
       +            }
       +            break;
       +          case 'r':
       +            if (i < argc - 1)
       +              buf_appendf(msg, "Reply-Chain: %s\n", argv[++i]);
       +            else {
       +              noarg(argv[0], *p);
       +              error = 1;
       +            }
       +            break;
       +#ifdef USE_PGP
       +          case 'n':
       +            if (i < argc - 1)
       +              buf_appendf(msg, "Nym: %s\n", argv[++i]);
       +            else {
       +              noarg(argv[0], *p);
       +              error = 1;
       +            }
       +            break;
       +#endif /* USE_PGP */
       +          case 'c':
       +            if (i < argc - 1)
       +              sscanf(argv[++i], "%d", &numcopies);
       +            else {
       +              noarg(argv[0], *p);
       +              error = 1;
       +            }
       +            break;
       +          case 'p':
       +            send = MSG_POST;
       +            break;
       +          case 'g':
       +            if (i < argc - 1) {
       +              send = MSG_POST, header = 0;
       +              buf_appendf(msg, "Newsgroups: %s\n", argv[++i]);
       +            } else {
       +              noarg(argv[0], *p);
       +              error = 1;
       +            }
       +            break;
       +          case 'a':
       +            if (i < argc - 1)
       +              buf_appendf(attachments, "%s\n", argv[++i]);
       +            else {
       +              noarg(argv[0], *p);
       +              error = 1;
       +            }
       +            break;
       +          case 'm':
       +            send = MSG_MAIL;
       +            break;
       +          default:
       +            fprintf(stderr, "%s: Invalid option -%c\n", argv[0], *p);
       +            error = 1;
       +            break;
       +          }
       +        }
       +      }
       +    } else {
       +      if (strchr(argv[i], '@')) {
       +        header = 0;
       +        buf_appendf(msg, "To: %s\n", argv[i]);
       +      } else {
       +        if (filename == NULL)
       +          filename = argv[i];
       +        else {
       +          fprintf(stderr, "%s: Error in command line: %s\n", argv[0], argv[i]);
       +          error = 1;
       +        }
       +      }
       +    }
       +  }
       +
       +  if (error) {
       +    ret = 1;
       +    goto end;
       +  }
       +
       +  if (type_list) {
       +    BUFFER *type2list;
       +    type2list = buf_new();
       +    if (prepare_type2list(type2list) < 0) {
       +      fprintf(stderr, "Cannot print type2.list.\n");
       +      ret = 2;
       +    } else {
       +      printf("%s", type2list->data);
       +    };
       +    buf_free(type2list);
       +    goto end;
       +  }
       +
       +  if (version) {
       +    printf("Mixmaster %s\n", VERSION);
       +    ret = 0;
       +    goto end;
       +  }
       +
       +  if (update_pingerlist) {
       +    mixfile(pingpath, ALLPINGERSFILE);
       +    if (verbose) printf ("downloading %s...\n", ALLPINGERSURL);
       +    if (url_download(ALLPINGERSURL, pingpath) < 0) {
       +      printf("    Download failed... Try again later.\n");
       +      errlog(ERRORMSG, "All Pingers File Download failed.\n");
       +    } else {
       +      if (verbose) printf("    Done.\n");
       +      errlog(LOG, "All Pingers File Downloaded OK.\n");
       +    }
       +    ret = 0;
       +    goto end;
       +  }
       +  
       +  if (update_stats) {
       +    ret = download_stats(statssrc->data);
       +    if (ret == -3) {
       +      fprintf(stderr, "Stats source does not include all required files.\n");
       +    } else if (ret == -2) {
       +      fprintf(stderr, "Could not open stats source file for writing\n");
       +    } else if (ret == -1) {
       +      fprintf(stderr, "Stats source download failed.\n");
       +    }
       +    ret = 0;
       +    goto end;
       +  }
       +
       +#ifdef USE_NCURSES
       +/* If we get here then it's possible we still want to use the NCURSES interface */
       +    if (deflt && (send == -1) && isatty(fileno(stdin))) {
       +      menu_main();
       +      goto clientpool;
       +    }
       +#endif /* USE_NCURSES */
       +  
       +  if (help ||about ||(isatty(fileno(stdin)) && isatty(fileno(stdout))))
       +    fprintf(stderr, "Mixmaster %s\n", VERSION);
       +  if (help ||about)
       +    printf("\n\n");
       +  if (about) {
       +    printf("Many people have contributed to the source code for Mixmaster.\n");
       +    printf("These contributors include:\n\n");
       +    printf("Lance Cottrell\n");
       +    printf("Janis Jagars\n");
       +    printf("Ulf Moeller\n");
       +    printf("Peter Palfrader\n");
       +    printf("Len Sassaman\n");
       +    printf("\nand others. For full information on copyright and license issues,\n");
       +    printf("read the bundled file COPYRIGHT.\n\n");
       +    ret = 0;
       +    goto end;
       +  }
       +  
       +  if (help) {
       +    printf("Usage: %s [options] [user@host] [filename]\n\n", argv[0]);
       +    printf("Options:\n\
       +\n\
       +-h, --help                        summary of command line options\n\
       +-V, --version                     print version information\n\
       +    --about                       print authorship information\n\
       +-T, --type-list                   list available remailers\n\
       +-t, --to=user@host                the recipient's address(es)\n\
       +-g, --post-to=newsgroup           newsgroup(s) to post to\n\
       +-p, --post                        input is a Usenet article\n\
       +-m, --mail                        input is a mail message\n\
       +-s, --subject=subject             message subject\n\
       +    --header='header line'        arbitrary message headers\n\
       +-a, --attachment=file             attach a file\n"
       +#ifdef USE_PGP
       +#ifdef NYMSUPPORT
       +           "-n, --nym=yournym                 use pseudonym to send the message\n"
       +#endif /* NYMSUPPORT */
       +"    --encrypt                     encrypt the message using the PGP format\n\
       +    --sign                        sign the message using the PGP format\n"
       +#endif /* USE_PGP */
       +           "-l, --chain=mix1,mix2,mix3,...    specify a remailer chain\n\
       +-c, --copies=num                  send num copies to increase reliability\n\
       +-d, --dummy                       generate a dummy message\n\
       +-S, --send                        send the message(s) in the pool\n"
       +#ifdef USE_PGP
       +#ifdef NYMSUPPORT
       +           "    --nym-config=yournym          generate a new pseudonym\n\
       +    --latency=hours               reply chain latency\n\
       +    --reply-chain=rem1,rem2,...   reply chain for the pseudonym\n"
       +#endif /* NYMSUPPORT */
       +#endif /* USE_PGP */
       +           "-v, --verbose                     output informational messages\n\
       +-f [file]                         read a mail folder\n\
       +    --update-pinger-list          Download an updated all pingers list file\n\
       +    --update-stats[=source]       Download updated stats\n"
       +
       +#ifndef USE_NCURSES
       +           "\n-fr, -ff, -fg [file]              send reply/followup/group reply to a message\n"
       +#endif /* USE_NCURSES */
       +           "\nThe input file is expected to contain mail headers if no address is\n\
       +specified in the command line.\n\
       +\n\
       +Remailer:\n\
       +\n\
       +-R, --read-mail                   read remailer message from stdin\n\
       +-I, --store-mail                  read remailer msg from stdin, do not decrypt\n\
       +-M, --remailer                    process the remailer pool\n\
       +-D, --daemon                      remailer as background process\n\
       +    --no-detach                   do not detach from terminal as daemon\n"
       +#ifdef USE_SOCK
       +           "-S, --send                        force sending messages from the pool\n"
       +#endif /* USE_SOCK */
       +           "-P, --pop-mail                    force getting messages from POP3 servers\n\
       +-G, --generate-key                generate a new remailer key\n\
       +-K, --update-keys                 generate remailer keys if necessary\n\
       +    --config=file                 use alternate configuration file\n"
       +#ifdef WIN32SERVICE
       +           "\n\
       +WinNT service:\n\
       +\n\
       +    --install-svc                 install the service\n\
       +    --remove-svc                  remove the service\n\
       +    --run-svc                     run as a service\n"
       +#endif /* WIN32SERVICE */
       +    );
       +
       +    ret = 0;
       +    goto end;
       +  }
       +
       +  if (deflt && send == -1)
       +    send = MSG_MAIL;
       +  if (nym[0] != 0)
       +    send = -1;
       +  if ((send == MSG_MAIL || send == MSG_POST) && filename == NULL &&
       +      header == 1 && isatty(fileno(stdin))) {
       +    /* we don't get here if USE_NCURSES is set */
       +    printf("Run `%s -h' to view a summary of the command line options.\n\nEnter the message, complete with headers.\n",
       +           argv[0]);
       +#ifdef UNIX
       +    printf("When done, press ^D.\n\n");
       +#else
       +    printf("When done, press ^Z.\n\n");
       +#endif /* else not UNIX */
       +  }
       +  if (header == 0)
       +    buf_nl(msg);
       +
       +  /* timeskew check */
       +  if (REMAIL == 1)
       +    mix_check_timeskew();
       +
       +  if (readmail || redirect_mail || send == MSG_MAIL || send == MSG_POST) {
       +    if (filename == NULL || streq(filename, "-"))
       +      f = stdin;
       +    else {
       +      f = fopen(filename, "r");
       +      if (f == NULL)
       +        fprintf(stderr, "Can't open %s.\n", filename);
       +    }
       +
       +    if (f && buf_read(msg, f) != -1) {
       +      if (readmail == 1) {
       +        check_get_pass(1, never_ask_for_passphrase);
       +        mix_decrypt(msg);
       +      } else if (readmail == 2)
       +        pool_add(msg, "inf");
       +      if (send == MSG_MAIL || send == MSG_POST || redirect_mail) {
       +        BUFFER *sendmsg;
       +        int numdest = 0;
       +
       +        sendmsg = buf_new();
       +
       +        while (buf_getheader(msg, field, content) == 0) {
       +          if (bufieq(field, "nym")) {
       +            strncpy(nym, content->data, sizeof(nym));
       +          } else if (bufieq(field, "chain"))
       +            if (strchr(content->data, ';')) {
       +              i = strchr(content->data, ';') - (char *)content->data;
       +              strncpy(chain, content->data, i);
       +              if (strstr(content->data + i, "copies=") != NULL) {
       +                sscanf(strstr(content->data + i, "copies=") +
       +                       sizeof("copies=") - 1, "%d", &numcopies);
       +              }
       +            } else
       +              strncpy(chain, content->data, sizeof(chain));
       +          else {                /* line goes into message */
       +            if (((redirect_mail || send == MSG_MAIL) && bufieq(field, "to"))
       +                || (send == MSG_POST && bufieq(field, "newsgroups")))
       +              numdest++;
       +            if (bufieq(field, "from") && !redirect_mail)
       +              fprintf(stderr, "Warning: The message has a From: line.\n");
       +            buf_appendheader(sendmsg, field, content);
       +          }
       +        }
       +        buf_nl(sendmsg);
       +        buf_rest(sendmsg, msg);
       +
       +        while (buf_getline(attachments, field) != -1)
       +          if (attachfile(sendmsg, field) == -1) {
       +            errlog(ERRORMSG, "Can't attach %b!\n", field);
       +            ret = 2;
       +            goto end;
       +          }
       +
       +#ifdef USE_PGP
       +        if (nym[0] != 0 && strchr(nym, '@') == NULL)
       +          strcatn(nym, "@", sizeof(nym));
       +        if (sign || encrypt) {
       +          BUFFER *pass;
       +
       +          pass = buf_new();
       +          user_pass(pass);
       +          if (pgp_mailenc((encrypt ? PGP_ENCRYPT : 0) |
       +                          (nym[0] != 0 && sign ? PGP_SIGN : 0) |
       +                          PGP_TEXT | PGP_REMAIL, sendmsg, nym,
       +                          pass, NULL, NYMSECRING) != 0) {
       +            fprintf(stderr, "Encryption failed: missing key!");
       +            ret = 2;
       +            goto end;
       +          }
       +          buf_free(pass);
       +        }
       +        if (nym[0] != 0) {
       +#ifdef NYMSUPPORT
       +          if (nym_encrypt(sendmsg, nym, send) == 0)
       +            send = MSG_MAIL;
       +          else
       +#endif /* NYMSUPPORT */
       +            fprintf(stderr, "Nym error, sending message anonymously.\n");
       +        }
       +#endif /* USE_PGP */
       +        if (numdest == 0) {
       +          fprintf(stderr, "No destination address given!\n");
       +          ret = 2;
       +        } else if (numcopies < 0 || numcopies > 10) {
       +          fprintf(stderr, "Invalid number of copies!\n");
       +          ret = 2;
       +        } else {
       +          if ( ( redirect_mail ?
       +                redirect_message(sendmsg, chain, numcopies, chainlist) :
       +                mix_encrypt(send, sendmsg, chain, numcopies, chainlist)
       +                ) == -1) {
       +            ret = 2;
       +            if (chainlist->length)
       +              fprintf(stderr, "%s\n", chainlist->data);
       +            else
       +              fprintf(stderr, "Failed!\n");
       +          } else if (verbose) {
       +            fprintf(stderr, "Chain: ");
       +            buf_write(chainlist, stderr);
       +          }
       +        }
       +
       +        buf_free(sendmsg);
       +      }
       +      if (filename != NULL)
       +        fclose(f);
       +    } else
       +      ret = 2;
       +  }
       +  if (send == MSG_NULL) {
       +    if (msg->length) {
       +      while (buf_getheader(msg, field, content) == 0) {
       +        if (bufieq(field, "chain"))
       +          strncpy(chain, content->data, sizeof(chain));
       +      }
       +    }
       +    if (mix_encrypt(MSG_NULL, NULL, chain, numcopies, chainlist) == -1) {
       +      ret = 2;
       +      if (chainlist->length)
       +        printf("%s\n", chainlist->data);
       +      else
       +        fprintf(stderr, "Failed!\n");
       +    } else if (verbose) {
       +      printf("Chain: ");
       +      buf_write(chainlist, stdout);
       +    }
       +  }
       +#ifdef USE_PGP
       +#ifdef NYMSUPPORT
       +  if (nym[0] != 0) {
       +    char nymserver[LINELEN] = "*";
       +    BUFFER *chains;
       +
       +    chains = buf_new();
       +    if (numcopies < 1 || numcopies > 10)
       +      numcopies = 1;
       +    while (buf_getheader(msg, field, content) != -1) {
       +      if (bufieq(field, "chain"))
       +        strncpy(chain, content->data, sizeof(chain));
       +      else if (bufieq(field, "reply-chain"))
       +        buf_appendf(chains, "Chain: %b\n", content);
       +      else if (field->length)
       +        buf_appendheader(chains, field, content);
       +      else
       +        buf_nl(chains);
       +    }
       +    if (strrchr(nym, '@')) {
       +      strncpy(nymserver, strrchr(nym, '@'), sizeof(nymserver));
       +      *strrchr(nym, '@') = '\0';
       +    }
       +    if (nym_config(NYM_CREATE, nym, nymserver, pseudonym,
       +                   chain, numcopies, chains, nymopt) < 0) {
       +      ret = 2;
       +      fprintf(stderr, "Failed!\n");
       +    }
       +    user_delpass();
       +    buf_free(chains);
       +  }
       +#endif /* NYMSUPPORT */
       +#endif /* USE_PGP */
       +
       +  if (keygen) {
       +    check_get_pass(0, never_ask_for_passphrase);
       +    keymgt(keygen);
       +  }
       +  if (sendpool)
       +    mix_send();
       +#ifdef USE_SOCK
       +  if (pop3)
       +    pop3get();
       +#endif /* USE_SOCK */
       +  if (maint) {
       +    check_get_pass(1, never_ask_for_passphrase);
       +    mix_regular(0);
       +  }
       +
       +clientpool:
       +  if ((REMAIL == 0) && (CLIENTAUTOFLUSH == 1)) {
       +    SENDPOOLTIME = 0;
       +    RATE = 100;
       +    mix_send();
       +  };
       +
       +end:
       +  buf_free(field);
       +  buf_free(content);
       +  buf_free(chainlist);
       +  buf_free(msg);
       +  buf_free(nymopt);
       +  buf_free(pseudonym);
       +  buf_free(attachments);
       +  buf_free(statssrc);
       +
       +  if (daemon) {
       +    check_get_pass(1, never_ask_for_passphrase);
       +#ifdef UNIX
       +    if (! nodetach) {
       +      int pid;
       +
       +      fprintf(stderr, "Detaching.\n");
       +      /* Detach as suggested by the Unix Programming FAQ */
       +      pid = fork();
       +      if (pid > 0)
       +        exit(0);
       +      if (setsid() < 0) {
       +        /* This should never happen. */
       +        fprintf(stderr, "setsid() failed.\n");
       +        exit(1);
       +      };
       +      pid = fork();
       +      if (pid > 0)
       +        exit(0);
       +    };
       +    if (chdir(MIXDIR) < 0) {
       +      if (chdir("/") < 0) {
       +        fprintf(stderr, "Cannot chdir to mixdir or /.\n");
       +        exit(1);
       +      };
       +    };
       +    if (write_pidfile(PIDFILE)) {
       +      fprintf(stderr, "Aborting.\n");
       +      exit(1);
       +    }
       +    if (! nodetach) {
       +      freopen ("/dev/null", "r", stdin);
       +      freopen ("/dev/null", "w", stdout);
       +      freopen ("/dev/null", "w", stderr);
       +    }
       +#endif /* UNIX */
       +    mix_daemon();
       +#ifdef UNIX
       +/* ifdef this one too, so that we do not need to export it from windows dll */
       +    clear_pidfile(PIDFILE);
       +#endif /* UNIX */
       +  }
       +  mix_exit();
       +  return (ret);
       +}
       +
       +static char *largopt(char *p, char *opt, char *name, int *error)
       +{
       +  if (streq(p, opt)) {
       +    fprintf(stderr, "%s: Missing argument for option --%s\n", name, p);
       +    *error = 1;
       +  } else if (strleft(p, opt) && p[strlen(opt)] == '=') {
       +    return (p + strlen(opt) + 1);
       +  }
       +  return (NULL);
       +}
       +
       +static void noarg(char *name, char p)
       +{
       +  fprintf(stderr, "%s: Missing argument for option -%c\n", name, p);
       +}
       +
       +static int check_get_pass(int force, int never_ask_for_passphrase)
       +/* get a passphrase and check against keys
       + * if force != 0 passphrase must match with some key */
       +{
       +    BUFFER *pass, *pass2, *key;
       +    int n = 0;
       +
       +    if (PASSPHRASE[0] == '\0' && isatty(fileno(stdin)) && ! never_ask_for_passphrase) {
       +      pass = buf_new();
       +      pass2 = buf_new();
       +      key = buf_new();
       +      buf_sets(pass, PASSPHRASE);
       +      while (
       +#ifdef USE_PGP
       +             pgpdb_getkey(PK_DECRYPT, PGP_ES_RSA, NULL, NULL, NULL, NULL, NULL,
       +                           NULL, NULL, NULL, pass) < 0 &&
       +             pgpdb_getkey(PK_DECRYPT, PGP_E_ELG,  NULL, NULL, NULL, NULL, NULL,
       +                           NULL, NULL, NULL, pass) < 0 &&
       +#endif /* USE_PGP */
       +             getv2seckey(NULL, key) < 0)
       +      {
       +        user_delpass();
       +        if (n)
       +          fprintf(stderr, "re-");
       +        user_pass(pass);
       +        strncpy(PASSPHRASE, pass->data, LINELEN);
       +        PASSPHRASE[LINELEN-1] = 0;
       +        if (!force) {
       +          if (n && buf_eq(pass, pass2))
       +            break;
       +          buf_set(pass2, pass);
       +        }
       +        n=1;
       +      }
       +      user_delpass();
       +      buf_free(pass);
       +      buf_free(pass2);
       +      buf_free(key);
       +
       +      strncpy(ENTEREDPASSPHRASE, PASSPHRASE, LINELEN);
       +      ENTEREDPASSPHRASE[LINELEN-1] = 0;
       +    }
       +    return 1;
       +}
   DIR diff --git a/Src/menu.c b/Src/menu.c
       t@@ -0,0 +1,1003 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Menu-based user interface
       +   $Id: menu.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "menu.h"
       +#include "mix3.h"
       +#include <string.h>
       +#include <ctype.h>
       +#include <stdlib.h>
       +#include <fcntl.h>
       +#ifdef POSIX
       +#include <unistd.h>
       +#else /* end of POSIX */
       +#include <io.h>
       +#endif /* else if not POSIX */
       +#include <assert.h>
       +
       +void menu_folder(char command, char *foldername)
       +{
       +  mix_init(NULL);
       +  if (foldername)
       +    menu_init();
       +  read_folder(command, foldername, ANON);
       +  menu_exit();
       +}
       +
       +void read_folder(char command, char *foldername, char *nym)
       +{
       +#ifdef USE_NCURSES
       +  char path[PATHMAX] = "stdin", path_with_tilde[PATHMAX], l[LINELEN];
       +#else /* end of USE_NCURSES */
       +  char path[PATHMAX] = "stdin", l[LINELEN];
       +#endif /* else if not USE_NCURSES */
       +  char *h;
       +  FILE *f;
       +  BUFFER *folder;
       +  BUFFER *line, *field, *content, *name;
       +  BUFFER *index;
       +  BUFFER *mail, *log;
       +  int mailfolder = -1;        /* -1 = unknown, 0 = no mailfolder, 1 = mailfolder */
       +  int num = 0;
       +  long from = -1, subject = -1;
       +  int folder_has_changed;
       +#ifdef USE_NCURSES
       +  BUFFER *deleted_message;
       +  BUFFER *new_folder;
       +  BUFFER *new_index;
       +  long length;
       +  char sub[LINELEN], str[LINELEN], search[LINELEN] = "";
       +  long p;
       +  int display, range, selected, i, redraw, c, q;
       +
       +#endif /* USE_NCURSES */
       +  int ispgp = 0, eof = 0;
       +  folder_has_changed = 0;
       +
       +  line = buf_new();
       +  field = buf_new();
       +  content = buf_new();
       +  index = buf_new();
       +  mail = buf_new();
       +  name = buf_new();
       +  folder = buf_new();
       +  log = buf_new();
       +
       +  if (foldername == NULL)
       +    f = stdin;
       +  else {
       +    if (foldername[0] == '~' && (h = getenv("HOME")) != NULL) {
       +      strncpy(path, h, PATHMAX);
       +      strcatn(path, foldername + 1, PATHMAX);
       +    } else
       +      strncpy(path, foldername, PATHMAX);
       +    f = fopen(path, "r");
       +  }
       +  if (f == NULL) {
       +#ifdef USE_NCURSES
       +    if (foldername)
       +      beep();
       +#endif /* USE_NCURSES */
       +    mix_status("Can't read %s.\n", path);
       +    goto end;
       +  }
       +  for (;;) {
       +    if (fgets(l, sizeof(l), f) == NULL)
       +      eof = 1;
       +    else if (mailfolder == -1) {
       +      if (strleft(l, "From "))
       +        mailfolder = 1;
       +      else if (strileft(l, "from:") || strileft(l, "path:")
       +          || strileft(l, "xref:") || strileft(l, "return-path"))
       +        mailfolder = 0;
       +      else
       +        break;
       +    }
       +    if (eof || (mailfolder && strleft(l, "From ")) ||
       +        (mailfolder == 0 && from != -1 &&
       +         (strileft(l, "path:") ||
       +          strileft(l, "xref:") || strileft(l,"return-path")))) {
       +      if (num > 1)
       +        mix_status("Reading message %d", num);
       +#ifdef USE_PGP
       +      if (ispgp)
       +#ifdef NYMSUPPORT
       +        switch (nym_decrypt(mail, NULL, log)) {
       +        case 2:
       +          from = -1, subject = -1;
       +          while (buf_getline(mail, line) == 0) {
       +            if (bufileft(line, "from:"))
       +              from = folder->length + mail->ptr - line->length - 1;
       +            if (bufileft(line, "subject:"))
       +              subject = folder->length + mail->ptr - line->length - 1;
       +          }
       +          folder_has_changed = 1;
       +          break;
       +        case -1:
       +          buf_clear(mail);
       +          from = -1, subject = -1;
       +          continue;
       +        default:
       +          ;
       +        }
       +#else
       +        if (!eof) {
       +          buf_clear(mail);
       +          from = -1, subject = -1;
       +          continue;
       +        }
       +#endif /* NYMSUPPORT */
       +#endif /* USE_PGP */
       +      buf_cat(folder, mail);
       +      buf_clear(mail);
       +      ispgp = 0;
       +      if (num > 0) {
       +        buf_appendl(index, from);
       +        buf_appendl(index, subject);
       +      }
       +      if (eof)
       +        break;
       +
       +      buf_appendl(index, folder->length);
       +      from = subject = -1;
       +      num++;
       +    }
       +    if (from == -1 && strileft(l, "from:"))
       +      from = folder->length + mail->length;
       +
       +    if (subject == -1 && strileft(l, "subject:"))
       +      subject = folder->length + mail->length;
       +
       +    buf_appends(mail, l);
       +    if (strleft(l, begin_pgp))
       +      ispgp = 1;
       +  }
       +
       +  if (foldername)
       +    fclose(f);
       +  else {
       +    dup2(open("/dev/tty", O_RDWR), fileno(stdin));
       +    menu_init();
       +  }
       +
       +  mix_status("");
       +  if (folder->length == 0) {
       +#ifdef USE_NCURSES
       +    clear();
       +    beep();
       +#endif /* USE_NCURSES */
       +    mix_status("%s is empty.\n", path);
       +    goto end;
       +  }
       +  if (mailfolder == -1) {
       +#ifdef USE_NCURSES
       +    clear();
       +    beep();
       +#endif /* USE_NCURSES */
       +    mix_status("%s is not a mail folder.\n", path);
       +    goto end;
       +  }
       +#ifndef USE_NCURSES
       +  if (command == 0) {
       +    buf_write(folder, stdout);
       +    goto end;
       +  }
       +  if (num > 1) {
       +    mix_status("Folder contains several messages.");
       +    goto end;
       +  }
       +#endif /* not USE_NCURSES */
       +
       +  if (num < 2) {
       +    folder->ptr = 0;
       +    mimedecode(folder);
       +
       +    if (command != 0)
       +      send_message(command, nym, folder);
       +#ifdef USE_NCURSES
       +    else
       +      read_message(folder, nym);
       +
       +    clear();
       +#endif /* USE_NCURSES */
       +    goto end;
       +  }
       +#ifdef USE_NCURSES
       +  display = selected = 0;
       +  range = LINES - 3;
       +  redraw = 2;
       +
       +  for (;;) {
       +    if (selected < 0)
       +      selected = 0;
       +    if (selected >= num)
       +      selected = num - 1;
       +
       +    if (selected < display) {
       +      display = selected - range / 2;
       +      redraw = 2;
       +    }
       +    if (selected >= display + range) {
       +      display = selected - range / 2;
       +      redraw = 2;
       +    }
       +    if (display >= num - 5)
       +      display = num - 5;
       +    if (display < 0)
       +      display = 0;
       +
       +    if (redraw) {
       +      if (redraw == 2) {
       +        clear();
       +        standout();
       +        mvprintw(0, 0, "Mixmaster %s", VERSION);
       +        printw("   %.20s reading %.50s", nym, path);
       +        standend();
       +      }
       +      for (i = display; i < display + range; i++) {
       +        if (i < num) {
       +          index->ptr = 12 * i;
       +          p = buf_getl(index);
       +          buf_clear(name);
       +          folder->ptr = buf_getl(index);
       +          if (folder->ptr < 0)
       +            folder->ptr = 0;
       +          else {
       +            buf_getheader(folder, field, line);
       +            if (line->length) {
       +              decode_header(line);
       +              rfc822_name(line, name);
       +            }
       +          }
       +          if (i == selected)
       +            standout();
       +
       +          mvaddnstr(i - display + 2, 0, name->data, 18);
       +
       +          sub[0] = '\0';
       +          folder->ptr = buf_getl(index);
       +          if (folder->ptr < 0)
       +            folder->ptr = 0;
       +          else {
       +            buf_getheader(folder, field, content);
       +            if (content->length) {
       +              decode_header(content);
       +              strncpy(sub, content->data, sizeof(sub));
       +            }
       +          }
       +          if (sub[0] == '\0')
       +            strcpy(sub, "(no subject)");
       +          mvaddnstr(i - display + 2, 20, sub, COLS - 21);
       +
       +          if (i == selected)
       +            standend();
       +        }
       +      }
       +    }
       +    move(LINES - 1, COLS - 1);
       +    refresh();
       +    redraw = 0;
       +
       +    c = getch();
       +    switch (c) {
       +    case '\014':
       +      display = selected - range / 2;
       +      redraw = 2;
       +      break;
       +    case 'q':
       +      clear();
       +      goto end;
       +    case '/':
       +      echo();
       +      cl(LINES - 1, 0);
       +      printw("Search: ");
       +      refresh();
       +      wgetnstr(stdscr, str, LINELEN);
       +      if (str[0] != '\0')
       +        strncpy(search, str, LINELEN);
       +      noecho();
       +      for (i = (selected < num ? selected + 1 : 0); i < num; i++) {
       +        index->ptr = 12 * i + 4;
       +        folder->ptr = buf_getl(index);
       +        if (folder->ptr < 0)
       +          folder->ptr = 0;
       +        else {
       +          buf_getheader(folder, field, line);
       +          if (line->length) {
       +            decode_header(line);
       +            if (bufifind(line, search))
       +              break;
       +          }
       +        }
       +        folder->ptr = buf_getl(index);
       +        if (folder->ptr < 0)
       +          folder->ptr = 0;
       +        else {
       +          buf_getheader(folder, field, line);
       +          if (line->length) {
       +            decode_header(line);
       +            if (bufifind(line, search))
       +              break;
       +          }
       +        }
       +      }
       +      if (i < num)
       +        selected = i;
       +      else
       +        beep();
       +      redraw = 1;
       +      break;
       +    case '\r':                        /* read message */
       +    case '\n':
       +    case 'r':                        /* reply to message */
       +    case 'g':
       +    case 'f':
       +    case 'm':
       +    case 'p':
       +    case 's':
       +      index->ptr = 12 * selected;
       +      p = buf_getl(index);
       +      if (selected < num - 1) {
       +        index->ptr = 12 * (selected + 1);
       +        q = buf_getl(index) - p;
       +      } else
       +        q = folder->length - p;
       +      buf_clear(mail);
       +      buf_append(mail, folder->data + p, q);
       +      mimedecode(mail);
       +      if(c == 's')
       +        savemsg(mail);
       +      else{
       +        if (c == '\r' || c == '\n')
       +          read_message(mail, nym);
       +        else
       +          send_message(c, nym, mail);
       +      }
       +      redraw = 2;
       +      break;
       +    case 'd':                   /* delete message */
       +      /* Remove message from folder */
       +      if(num > 0){
       +        index->ptr = 12 * selected;
       +        p = buf_getl(index);
       +        if (selected < num - 1) {
       +          index->ptr = 12 * (selected + 1);
       +          q = buf_getl(index) - p;
       +        } else
       +          q = folder->length - p;
       +        deleted_message = buf_new();
       +        new_folder = buf_new();
       +        buf_cut_out(folder, deleted_message, new_folder, p, q);
       +        buf_free(deleted_message);
       +        buf_free(folder);
       +        folder = new_folder;
       +        /* Update index file */
       +        new_index = buf_new();
       +        index->ptr = 0;
       +        if(selected > 0)
       +          buf_get(index, new_index, 12 * selected);
       +        index->ptr = 12 * (selected + 1);
       +        while((from = buf_getl(index)) != -1){
       +          subject = buf_getl(index);
       +          length = buf_getl(index);
       +          buf_appendl(new_index, from - q);
       +          buf_appendl(new_index, subject - q);
       +          buf_appendl(new_index, length - q);
       +        }
       +        buf_free(index);
       +        index = new_index;
       +        /* Done */
       +        num--;
       +        folder_has_changed = 1;
       +      }
       +      redraw = 2;
       +      break;
       +    case KEY_UP:
       +      selected--;
       +      redraw = 1;
       +      break;
       +    case KEY_DOWN:
       +    case 'n':                        /* nym ???? */
       +      selected++;
       +      redraw = 1;
       +      break;
       +    case KEY_PPAGE:
       +      selected -= range;
       +      redraw = 1;
       +      break;
       +    case KEY_NPAGE:
       +      selected += range;
       +      redraw = 1;
       +      break;
       +    default:
       +      beep();
       +    }
       +  }
       +#endif /* USE_NCURSES */
       +
       +end:
       +#ifdef USE_NCURSES
       +  /* If folder has changed, ask user about saving new folder. */
       +  if (folder_has_changed && !streq(path, "stdin")) {
       +    mvprintw(LINES - 2, 0, "Buffer has changed. Save [y/n]? ");
       +    c = getch();
       +    cl(LINES - 2, 0);
       +    if ((c == 'y') || (c == 'Y')){
       +      strncpy(path_with_tilde, path, PATHMAX-1);
       +      strcat(path_with_tilde, "~");
       +      rename(path, path_with_tilde); /* Rename folder to folder~ */
       +      f = fopen(path, "w"); /* Write new folder */
       +      if (f == NULL)
       +        mix_status("Can't write to %s.", path);
       +      else{
       +        buf_write(folder, f);
       +        mix_status("Wrote %s.", path);
       +        fclose(f);
       +      }
       +    }
       +    else{
       +      mix_status("%s was not saved.", path);
       +    }
       +  }
       +#endif /* USE_NCURSES */
       +  buf_free(folder);
       +  buf_free(line);
       +  buf_free(field);
       +  buf_free(content);
       +  buf_free(index);
       +  buf_free(mail);
       +  buf_free(name);
       +  buf_free(log);
       +}
       +
       +#ifdef USE_NCURSES
       +static int sortrel(const void *a, const void *b)
       +{
       +  int na, ra, nb, rb;
       +
       +  na = *(int *) a;
       +  nb = *(int *) b;
       +
       +  ra = *((int *) a + 1);
       +  rb = *((int *) b + 1);
       +  return rb - ra;
       +}
       +
       +void menu_main(void)
       +{
       +  int y, x;
       +  int pool, n;
       +  int c;
       +  int space;
       +  BUFFER *chainlist, *line;
       +  char nym[LINELEN] = ANON;
       +
       +  chainlist = buf_new();
       +  line = buf_new();
       +
       +  mix_init(NULL);
       +  menu_init();
       +
       +menu_redraw:
       +  clear();
       +  for (;;) {
       +    standout();
       +    mvprintw(0, 0, "Mixmaster %s", VERSION);
       +#if 0
       +    mvprintw(0, COLS - sizeof(COPYRIGHT), COPYRIGHT);
       +#endif
       +    for (space = 0; space < (COLS - 10 - sizeof(VERSION)); space++) {
       +        printw(" ");
       +    };
       +    standend();
       +    mix_status(NULL);
       +
       +#ifdef NYMSUPPORT
       +    mvprintw(8, 4, "n)ym: %s", nym);
       +#endif /* NYMSUPPORT */
       +    y = 12, x = 25;
       +    mvprintw(y++, x, "m)ail");
       +    mvprintw(y++, x, "p)ost to Usenet");
       +    mvprintw(y++, x, "r)ead mail (or news article)");
       +    mvprintw(y++, x, "d)ummy message");
       +    mvprintw(y++, x, "s)end messages from pool");
       +    mvprintw(y++, x, "e)dit configuration file");
       +    mvprintw(y++, x, "u)pdate stats");
       +    mvprintw(y++, x, "q)uit");
       +
       +    pool = pool_read(NULL);
       +    if (pool == 1)
       +      mvprintw(4, 2, "%3d outgoing message in the pool. \n", pool);
       +    else
       +      mvprintw(4, 2, "%3d outgoing messages in the pool.\n", pool);
       +
       +    move(LINES - 1, COLS - 1);
       +    refresh();
       +    c = getch();
       +    if (c != ERR) {
       +      mix_status("");
       +      switch (c) {
       +      case '\014':
       +        mix_status("");
       +        goto menu_redraw;
       +#ifdef NYMSUPPORT
       +      case 'n':
       +        menu_nym(nym);
       +        goto menu_redraw;
       +#endif /* NYMSUPPORT */
       +      case 'm':
       +      case 'p':
       +        send_message(c, nym, NULL);
       +        break;
       +      case 'd':
       +        mix_status("Creating message...");
       +        if (mix_encrypt(MSG_NULL, NULL, NULL, 1, chainlist) != 0) {
       +          if (chainlist->length > 0)
       +            mix_status("%s", chainlist->data);
       +          else
       +            mix_genericerror();
       +          beep();
       +        } else {
       +          for (n = 0; buf_getline(chainlist, line) == 0; n++) ;
       +          if (n > 1)
       +            mix_status("Done (%d packets).", n);
       +          else
       +            mix_status("Chain: %s", chainlist->data);
       +        }
       +        break;
       +      case 's':
       +        mix_status("Mailing messages...");
       +        mix_send();
       +        mix_status("Done.");
       +        break;
       +      case 'r':
       +        {
       +          char name[LINELEN];
       +
       +          cl(LINES - 3, 0);
       +          if (getenv("MAIL"))
       +            printw("File name [%s]: ", getenv("MAIL"));
       +          else
       +            printw("File name: ");
       +          echo();
       +          wgetnstr(stdscr, name, LINELEN);
       +          noecho();
       +          cl(LINES - 3, 0);
       +          if (name[0] == '\0') {
       +            if (getenv("MAIL"))
       +              read_folder(0, getenv("MAIL"), nym);
       +          } else
       +            read_folder(0, name, nym);
       +        }
       +        break;
       +      case 'e':
       +        do {
       +          char path[PATHMAX];
       +          mixfile(path, MIXCONF);
       +          menu_spawn_editor(path, 0);
       +          mix_config();
       +        } while (0);
       +        break;
       +      case 'u':
       +        update_stats();
       +        break;
       +      case 'q':
       +      case 'Q':
       +        goto quit;
       +      default:
       +        beep();
       +      }
       +    }
       +  }
       +
       +quit:
       +  menu_exit();
       +  buf_free(chainlist);
       +  buf_free(line);
       +}
       +
       +void read_message(BUFFER *message, char *nym)
       +{
       +  int l = 0;
       +  int c;
       +  int inhdr = 1, txtbegin;
       +  BUFFER *field, *content, *line, *hdr;
       +  char sub[LINELEN] = "mail";
       +  char thisnym[LINELEN] = "";
       +
       +  field = buf_new();
       +  content = buf_new();
       +  line = buf_new();
       +  hdr = buf_new();
       +
       +  if (thisnym[0] == '\0')
       +    strncpy(thisnym, nym, LINELEN);
       +
       +  if (bufleft(message, "From nymserver ")) {
       +    /* select nym if Nym: pseudo header is in the first line */
       +    buf_getline(message, line);
       +    buf_getheader(message, field, content);
       +    if (bufieq(field, "Nym"))
       +      strncpy(thisnym, content->data, sizeof(thisnym));
       +    buf_rewind(message);
       +  }
       +  while (buf_getheader(message, field, content) == 0) {
       +    if (bufieq(field, "received") || bufleft(field, "From "))
       +      continue;
       +    if (bufieq(field, "subject"))
       +      strncpy(sub, content->data, sizeof(sub));
       +    buf_appendheader(hdr, field, content);
       +  }
       +  if (strlen(sub) > COLS - strlen(VERSION) - strlen(thisnym) - 23)
       +    sub[COLS - strlen(VERSION) - strlen(thisnym) - 24] = '\0';
       +  txtbegin = message->ptr;
       +
       +loop:
       +  clear();
       +  standout();
       +  mvprintw(0, 0, "Mixmaster %s", VERSION);
       +  printw("   %.20s reading %.50s\n", thisnym, sub);
       +  standend();
       +  mix_status(NULL);
       +
       +  while (l < LINES - 2) {
       +    if (inhdr) {
       +      if (buf_getline(hdr, line) == -1)
       +        buf_clear(line), inhdr = 0;
       +    } else {
       +      if (buf_getline(message, line) == -1) {
       +        standout();
       +        mvprintw(LINES - 1, 0, "Command");
       +        standend();
       +        refresh();
       +        for (;;) {
       +          c = getch();
       +          switch (c) {
       +          case 'm':
       +          case 'p':
       +          case 'r':
       +          case 'g':
       +          case 'f':
       +            send_message(c, thisnym, message);
       +            goto end;
       +          case 'u':
       +            inhdr = 0;
       +            message->ptr = txtbegin;
       +            l = 0;
       +            goto loop;
       +          case 'h':
       +            inhdr = 1;
       +            hdr->ptr = 0;
       +            message->ptr = txtbegin;
       +            l = 0;
       +            goto loop;
       +          case 's':
       +            savemsg(message);
       +            /* fallthru */
       +          case 'q':
       +          case 'i':
       +          case '\n':
       +          case '\r':
       +            goto end;
       +          case '\014':
       +            refresh();
       +            continue;
       +          default:
       +            beep();
       +            refresh();
       +          }
       +        }
       +      }
       +    }
       +    mvprintw(l + 1, 0, "%s\n", line->data);
       +    l += (line->length - 1) / COLS + 1;
       +  }
       +  standout();
       +  mvprintw(LINES - 1, 0, "MORE");
       +  standend();
       +  refresh();
       +  for (;;) {
       +    c = getch();
       +    switch (c) {
       +    case 'm':
       +    case 'p':
       +    case 'r':
       +    case 'g':
       +    case 'f':
       +      send_message(c, thisnym, message);
       +      goto end;
       +    case 'u':
       +      inhdr = 0;
       +      message->ptr = txtbegin;
       +      l = 0;
       +      goto loop;
       +    case 'h':
       +      inhdr = 1;                /* show full header */
       +      hdr->ptr = 0;
       +      message->ptr = txtbegin;
       +      l = 0;
       +      goto loop;
       +    case 's':
       +      savemsg(message);
       +      /* fallthru */
       +    case 'q':
       +    case 'i':
       +      goto end;
       +    case ' ':
       +    case '\n':
       +    case '\r':
       +      l = 0;
       +      goto loop;
       +    case '\014':
       +      refresh();
       +      continue;
       +    default:
       +      beep();
       +      refresh();
       +    }
       +  }
       +end:
       +  buf_free(field);
       +  buf_free(content);
       +  buf_free(line);
       +  buf_free(hdr);
       +}
       +
       +int menu_replychain(int *d, int *l, char *mdest, char *pdest, char *psub,
       +                    char *r)
       +{
       +  int c;
       +  char line[LINELEN];
       +  char reliability[9];
       +
       +redraw:
       +  clear();
       +  standout();
       +  printw("Create a nym reply block:");
       +  standend();
       +  mix_status(NULL);
       +
       +  mvprintw(3, 0, "Type of reply block:\n");
       +  if (*d == MSG_MAIL)
       +    standout();
       +  printw(" m)ail ");
       +  if (*d == MSG_MAIL)
       +    standend();
       +
       +  if (*d == MSG_POST)
       +    standout();
       +  printw(" Usenet message p)ool ");
       +  if (*d == MSG_POST)
       +    standend();
       +
       +  if (*d == MSG_NULL)
       +    standout();
       +  printw(" cover t)raffic ");
       +  if (*d == MSG_NULL)
       +    standend();
       +
       +  if (*d != MSG_NULL)
       +    mvprintw(6, 0, "d)estination: %s", *d == MSG_MAIL ? mdest : pdest);
       +  if (psub && *d == MSG_POST)
       +    mvprintw(7, 0, "s)ubject: %s", psub);
       +  chain_reliability(r, 1, reliability); /* chaintype 1=ek */
       +  mvprintw(8, 0, "c)hain: %-39s (reliability: %s)", r, reliability);
       +  mvprintw(10, 0, "l)atency: %d hours", *l);
       +  move(LINES - 1, COLS - 1);
       +
       +  for (;;) {
       +    refresh();
       +    c = getch();
       +    switch (c) {
       +    case 'm':
       +      *d = MSG_MAIL;
       +      goto redraw;
       +    case 'p':
       +      *d = MSG_POST;
       +      goto redraw;
       +    case 't':
       +      *d = MSG_NULL;
       +      goto redraw;
       +    case 'q':
       +      return (-1);
       +    case 'd':
       +      cl(6, 0);
       +      printw("d)estination: ");
       +      echo();
       +      wgetnstr(stdscr, *d == MSG_MAIL ? mdest : pdest, LINELEN);
       +      noecho();
       +      goto redraw;
       +    case 'l':
       +      cl(10, 0);
       +      printw("l)atency: ");
       +      echo();
       +      wgetnstr(stdscr, line, LINELEN);
       +      *l = strtol(line, NULL, 10);
       +      if (*l < 0)
       +        *l = 0;
       +      noecho();
       +      goto redraw;
       +    case 'c':
       +      menu_chain(r, 1, *d == MSG_POST);
       +      goto redraw;
       +    case '\014':
       +      goto redraw;
       +    case '\n':
       +    case '\r':
       +      return (0);
       +    case 's':
       +      if (*d == MSG_POST) {
       +        cl(7, 0);
       +        printw("s)ubject: ");
       +        echo();
       +        wgetnstr(stdscr, psub, LINELEN);
       +        noecho();
       +        goto redraw;
       +      }
       +    default:
       +      beep();
       +    }
       +  }
       +}
       +
       +void menu_chain(char *chainstr, int chaintype, int post)
       +     /* chaintype 0=mix 1=ek 2=newnym */
       +{
       +  REMAILER remailer[MAXREM];
       +  int badchains[MAXREM][MAXREM];
       +  int rlist[2 * MAXREM];
       +  char newchain[CHAINMAX];
       +  char info[LINELEN];
       +  int num = 0, i, middlemanlast=0, ok = 1;
       +  int c, x, y;
       +  int nymserv = 0;
       +  int chain[20], chainlen = 0;
       +  char reliability[9];
       +
       +  if (chaintype == 2)
       +    nymserv = 1, chaintype = 1;
       +  assert(chaintype == 0 || chaintype == 1);
       +
       +  clear();
       +  standout();
       +  if (nymserv)
       +    printw("Select nym server:\n\n");
       +  else
       +    printw("Select remailer chain:\n\n");
       +  standend();
       +
       +  if (chaintype == 1)
       +    num = t1_rlist(remailer, badchains);
       +  else
       +    num = mix2_rlist(remailer, badchains);
       +
       +  if (num < 1) {
       +    mix_status("Can't read remailer list.");
       +    beep();
       +    return;
       +  }
       +  for (i = 0; i < num; i++) {
       +    rlist[2 * i] = i + 1;
       +    rlist[2 * i + 1] = remailer[i + 1].info[chaintype].reliability -
       +      remailer[i + 1].info[chaintype].latency / 3600;
       +    if (remailer[i + 1].info[chaintype].history[0] == '\0')
       +      rlist[2 * i + 1] = -1;
       +    if ((nymserv && !remailer[i + 1].flags.newnym) ||
       +        ((chaintype == 0 && !remailer[i + 1].flags.mix) ||
       +         (chaintype == 1 && !nymserv && (!remailer[i + 1].flags.ek
       +                                         || !remailer[i + 1].flags.pgp))))
       +      rlist[2 * i] = 0, rlist[2 * i + 1] = -2;
       +  }
       +  qsort(rlist, num - 1, 2 * sizeof(int), sortrel);
       +
       +  for (i = 0; i < num; i++)
       +    if (rlist[2 * i + 1] == -2) {
       +      num = i;
       +      break;
       +    }
       +  if (num < 1) {
       +    mix_status("No remailers found!");
       +    return;
       +  }
       +  if (num > 2 * (LINES - 6))
       +    num = 2 * (LINES - 6);
       +  if (num > 2 * 26)
       +    num = 2 * 26;
       +
       +  for (i = 0; i < num && rlist[2 * i + 1] > -2; i++) {
       +    y = i, x = 0;
       +    if (y >= LINES - 6)
       +      y -= LINES - 6, x += 40;
       +    mvprintw(y + 2, x, "%c", i < 26 ? i + 'a' : i - 26 + 'A');
       +    mvprintw(y + 2, x + 2, "%s", remailer[rlist[2 * i]].name);
       +    mvprintw(y + 2, x + 16, "%s",
       +             remailer[rlist[2 * i]].info[chaintype].history);
       +    sprintf(info, "%3.2f",
       +            remailer[rlist[2 * i]].info[chaintype].reliability / 100.0);
       +    mvprintw(y + 2, x + 29 + 6 - strlen(info), "%s%%", info);
       +  }
       +  y = num + 3;
       +  if (y > LINES - 4)
       +    y = LINES - 4;
       +  mvprintw(y, 0, "*  select at random");
       +
       +  for (;;) {
       +    newchain[0] = '\0';
       +    for (i = 0; i < chainlen; i++) {
       +      if (i)
       +        strcatn(newchain, ",", CHAINMAX);
       +      if (chain[i])
       +        strcatn(newchain, remailer[chain[i]].name, CHAINMAX);
       +      else
       +        strcatn(newchain, "*", CHAINMAX);
       +    }
       +    if (chainlen > 0) {
       +      ok = 1;
       +      middlemanlast = remailer[chain[chainlen - 1]].flags.middle;
       +      if (post && !remailer[chain[chainlen - 1]].flags.post && !(chain[chainlen - 1] == 0 /*randhop*/))
       +        ok = 0;
       +    } else
       +      ok = 1;
       +
       +    mvprintw(LINES - 4, 40,
       +      middlemanlast ?
       +        "MIDDLEMAN   " :
       +        (ok ?
       +          "            " :
       +          "NO POSTING  "));
       +    cl(LINES - 3, 0);
       +    cl(LINES - 2, 0);
       +    cl(LINES - 1, 0);
       +    if(!nymserv){
       +      chain_reliability(newchain, chaintype, reliability);
       +      mvprintw(LINES - 4, 58, "(reliability: %s)", reliability);
       +    }
       +    mvprintw(LINES - 3, 0, nymserv ? "Nym server: %s" : "Chain: %s",
       +             newchain);
       +    refresh();
       +    c = getch();
       +    if (c == '\n' || c == '\r') {
       +    /* beep and sleep in case the user made a mistake */
       +      if (middlemanlast) {
       +        beep();
       +        sleep(2);
       +      }
       +      if (ok || middlemanlast)
       +        break;
       +      else
       +        beep();
       +    } else if (c == '*') {
       +      if (chainlen > 19 || (nymserv && chainlen > 0))
       +        beep();
       +      else
       +        chain[chainlen++] = 0;
       +    } else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
       +      if (c >= 'a')
       +        c -= 'a';
       +      else
       +        c = c - 'A' + 26;
       +
       +      if (chainlen > 19 || (nymserv && chainlen > 0) || c >= num)
       +        beep();
       +      else
       +        chain[chainlen++] = rlist[2 * c];
       +    } else if (c == killchar())
       +      chainlen = 0;
       +    else if ((c == KEY_BACKSPACE || c == KEY_LEFT || c == erasechar())
       +             && chainlen > 0)
       +      --chainlen;
       +    else
       +      beep();
       +  }
       +  if (chainlen)
       +    strncpy(chainstr, newchain, CHAINMAX);
       +}
       +
       +#endif /* USE_NCURSES */
   DIR diff --git a/Src/menu.h b/Src/menu.h
       t@@ -0,0 +1,48 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Menu-based user interface
       +   $Id: menu.h 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#ifndef _MENU_H
       +#define _MENU_H
       +#include "mix3.h"
       +#ifdef USE_NCURSES
       +#ifdef HAVE_NCURSES_H
       +#include <ncurses.h>
       +#else /* end of HAVE_NCURSES_H */
       +#include <curses.h>
       +#endif /* else if not HAVE_NCURSES_H */
       +#endif /* USE_NCURSES */
       +
       +#define NONANON "non-anonymous"
       +#define ANON "Anonymous"
       +
       +void send_message(int type, char *nym, BUFFER *txt);
       +void read_folder(char command, char *foldername, char *nym);
       +void menu_init(void);
       +void menu_exit(void);
       +
       +void menu_spawn_editor(char *path, int lineno);
       +
       +#ifdef USE_NCURSES
       +void read_message(BUFFER *message, char *nym);
       +void menu_nym(char *);
       +void menu_chain(char *chain, int type, int post);
       +void cl(int y, int x);
       +void askfilename(char *fn);
       +void savemsg(BUFFER *message);
       +int menu_replychain(int *d, int *l, char *mdest, char *pdest, char *psub,
       +                    char *r);
       +void update_stats(void);
       +
       +#endif /* USE_NCURSES */
       +
       +#define maxnym 30
       +
       +#endif /* not _MENU_H */
   DIR diff --git a/Src/menunym.c b/Src/menunym.c
       t@@ -0,0 +1,472 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Menu-based user interface - nym management
       +   $Id: menunym.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +#ifdef NYMSUPPORT
       +
       +#include "menu.h"
       +#include "mix3.h"
       +#include <string.h>
       +#include <stdlib.h>
       +#ifdef POSIX
       +#include <unistd.h>
       +#endif /* POSIX */
       +
       +#ifdef USE_NCURSES
       +void menu_nym(char *nnym)
       +{
       +  char nym[maxnym][LINELEN];
       +  char pending[maxnym][LINELEN];
       +  int c, i, num = 0, numpending = 0, select = -1;
       +  int edit = 0;
       +  BUFFER *nymlist;
       +  int s;
       +  int pass = 0;
       +  char reliability[9]; /* When printing information about a chain,
       +                          this variable stores the reliability. */
       +
       +  nymlist = buf_new();
       +
       +  strcpy(nym[0], NONANON);
       +  strcatn(nym[0], " (", sizeof(nym[0]));
       +  strcatn(nym[0], NAME, sizeof(nym[0]));
       +  strcatn(nym[0], ")", sizeof(nym[0]));
       +
       +  strcpy(nym[1], ANON);
       +  num = 2;
       +  if (nymlist_read(nymlist) == -1) {
       +    user_delpass();
       +    mix_status("");
       +  } else
       +    pass = 1;
       +  while (nymlist_get(nymlist, nym[num], NULL, NULL, NULL, NULL, NULL, &s) >= 0) {
       +    if (s == NYM_OK) {
       +      if (num < maxnym)
       +        num++;
       +    } else if (s == NYM_WAITING) {
       +      if (numpending < maxnym)
       +        strncpy(pending[numpending++], nym[num], LINELEN);
       +    }
       +  }
       +  buf_free(nymlist);
       +
       +nymselect:
       +  clear();
       +  standout();
       +  printw("Select nym:\n\n");
       +  standend();
       +#ifdef USE_PGP
       +  if (pass)
       +    printw("c)reate new nym\ne)dit nym\nd)elete nym\n\n");
       +  else
       +    printw("[nym passphrase is invalid]\n\n");
       +#endif /* USE_PGP */
       +  for (i = 0; i < num; i++)
       +    printw("%d) %s\n", i, nym[i]);
       +  if (numpending > 0) {
       +    printw("\n\nWaiting for confirmation: ");
       +    for (i = 0; i < numpending; i++)
       +      printw("%s ", pending[i]);
       +    printw("\n");
       +  }
       +select:
       +  if (select != -1)
       +    printw("\r%d", select);
       +  else
       +    printw("\r          \r");
       +  refresh();
       +  c = getch();
       +  if (c == erasechar())
       +    c = KEY_BACKSPACE;
       +  if (c >= '0' && c <= '9') {
       +    if (select == -1)
       +      select = c - '0';
       +    else
       +      select = 10 * select + c - '0';
       +    if (edit ? select == 0 || select >= num + numpending - 1 : select >= num) {
       +      beep();
       +      select = -1;
       +    }
       +    refresh();
       +    goto select;
       +  } else
       +    switch (c) {
       +    case KEY_BACKSPACE:
       +      select /= 10;
       +      if (select < 1)
       +        select = -1;
       +      goto select;
       +    case 'q':
       +      if (edit) {
       +        edit = 0;
       +        select = -1;
       +        goto nymselect;
       +      }
       +      break;
       +#ifdef USE_PGP
       +    case 'e':
       +      if (pass) {
       +        if (edit || num + numpending < 3) {
       +          edit = 0;
       +          select = -1;
       +          goto nymselect;
       +        } else {
       +          clear();
       +          standout();
       +          printw("Edit nym:\n\n");
       +          standend();
       +          for (i = 2; i < num + numpending; i++)
       +            printw("%d) %s\n", i - 1, i < num ? nym[i] : pending[i - num]);
       +          printw("\n");
       +          select = -1;
       +          edit = NYM_MODIFY;
       +          goto select;
       +        }
       +      }
       +      break;
       +    case 'd':
       +      if (pass) {
       +        if (edit || num + numpending < 3) {
       +          edit = 0;
       +          select = -1;
       +          goto nymselect;
       +        } else {
       +          clear();
       +          standout();
       +          printw("Delete nym:\n\n");
       +          standend();
       +          for (i = 2; i < num + numpending; i++)
       +            printw("%d) %s\n", i - 1, i < num ? nym[i] : pending[i - num]);
       +          printw("\n");
       +          select = -1;
       +          edit = NYM_DELETE;
       +          goto select;
       +        }
       +      }
       +      break;
       +    case '\r':
       +    case '\n':
       +      if (select == -1 || (edit && select == 0)) {
       +        beep();
       +        edit = 0;
       +        select = -1;
       +        goto nymselect;
       +      }
       +      if (!edit) {
       +        strncpy(nnym, nym[select], LINELEN);
       +        return;
       +      }
       +      /* fallthru */
       +    case 'c':
       +      if (pass) {
       +        char nymserv[LINELEN] = "*";
       +        char replyblock[5][CHAINMAX], dest[10][LINELEN];
       +        int latent[5], desttype[5];
       +        char mdest[LINELEN], pdest[LINELEN] = "alt.anonymous.messages",
       +        psub[LINELEN] = "";
       +        int deflatent = 0, defdesttype = MSG_MAIL;
       +        char alias[LINELEN] = "";
       +        BUFFER *name, *opt;
       +        char sendchain[CHAINMAX];
       +        int sendnumcopies = 1, rnum = 1;
       +        int i;
       +        char line[LINELEN];
       +        int acksend = 0, signsend = 0, fixedsize = 0, disable = 0,
       +            fingerkey = 1;
       +
       +        name = buf_new();
       +        opt = buf_new();
       +        strncpy(sendchain, CHAIN, CHAINMAX);
       +        strncpy(mdest, ADDRESS, LINELEN);
       +        if (edit)
       +          strncpy(alias, select + 1 < num ? nym[select + 1] :
       +                  pending[select + 1 - num], LINELEN);
       +        if (edit == NYM_MODIFY) {
       +          nymlist_getnym(alias, NULL, NULL, opt, name, NULL);
       +          acksend = bufifind(opt, "+acksend");
       +          signsend = bufifind(opt, "+signsend");
       +          fixedsize = bufifind(opt, "+fixedsize");
       +          disable = bufifind(opt, "+disable");
       +          fingerkey = bufifind(opt, "+fingerkey");
       +          rnum = -1;
       +        }
       +      newnym:
       +        if (!edit) {
       +          clear();
       +          standout();
       +          printw("Create a nym:");
       +          standend();
       +
       +          mvprintw(3, 0, "Alias address: ");
       +          echo();
       +          wgetnstr(stdscr, alias, LINELEN);
       +          noecho();
       +          if (alias[0] == '\0')
       +            goto end;
       +          for (i = 0; alias[i] > ' ' && alias[i] != '@'; i++) ;
       +          alias[i] = '\0';
       +          if (i == 0)
       +            goto newnym;
       +          mvprintw(4, 0, "Pseudonym: ");
       +          echo();
       +          wgetnstr(stdscr, line, LINELEN);
       +          noecho();
       +          buf_sets(name, line);
       +          menu_chain(nymserv, 2, 0);
       +        }
       +        if (edit != NYM_DELETE) {
       +          for (i = 0; i < 5; i++) {
       +            desttype[i] = defdesttype;
       +            latent[i] = deflatent;
       +            dest[i][0] = '\0';
       +            strcpy(replyblock[i], "*,*,*,*");
       +          }
       +          if (rnum != -1) {
       +            menu_replychain(&defdesttype, &deflatent, mdest, pdest, psub,
       +                            replyblock[0]);
       +            desttype[0] = defdesttype;
       +            latent[0] = deflatent;
       +            strncpy(dest[0], desttype[0] == MSG_POST ? pdest : mdest,
       +                    LINELEN);
       +          }
       +        }
       +      redraw:
       +        clear();
       +        standout();
       +        switch (edit) {
       +        case NYM_DELETE:
       +          printw("Delete nym:");
       +          break;
       +        case NYM_MODIFY:
       +          printw("Edit nym:");
       +          break;
       +        default:
       +          printw("Create a nym:");
       +          break;
       +        }
       +        standend();
       +      loop:
       +        {
       +          if (!edit) {
       +            cl(2, 0);
       +            printw("Nym: a)lias address: %s", alias);
       +            cl(3, 0);
       +            printw("     nym s)erver: %s", nymserv);
       +          }
       +          if (edit != NYM_DELETE) {
       +            cl(4, 0);
       +            printw("     p)seudonym: %s", name->data);
       +            if (edit)
       +              mvprintw(6, 0, "Nym modification:");
       +            else
       +              mvprintw(6, 0, "Nym creation:");
       +          }
       +          cl(7, 0);
       +          chain_reliability(sendchain, 0, reliability); /* chaintype 0=mix */
       +          printw("     c)hain to nym server: %-30s (reliability: %s)", sendchain, reliability);
       +          cl(8, 0);
       +          printw("     n)umber of redundant copies: %d", sendnumcopies);
       +          if (edit != NYM_DELETE) {
       +            mvprintw(10, 0, "Configuration:\n");
       +            printw("     A)cknowledge sending: %s\n", acksend ? "yes" : "no");
       +            printw("     S)erver signatures: %s\n", signsend ? "yes" : "no");
       +            printw("     F)ixed size replies: %s\n", fixedsize ? "yes" :
       +                   "no");
       +            printw("     D)isable: %s\n", disable ? "yes" : "no");
       +            printw("     Finger K)ey: %s\n", fingerkey ? "yes" : "no");
       +            mvprintw(17, 0, "Reply chains:");
       +            cl(18, 0);
       +            if (rnum == -1)
       +              printw("     create new r)eply block");
       +            else {
       +               printw("     number of r)eply chains: %2d                                     reliability", rnum);
       +              for (i = 0; i < rnum; i++) {
       +                cl(i + 19, 0);
       +                 chain_reliability(replyblock[i], 1, reliability); /* 1=ek */
       +                 printw("     %d) %30s %-31s [%s]", i + 1,
       +                         desttype[i] == MSG_NULL ?
       +                        "(cover traffic)" : dest[i], replyblock[i],
       +                        reliability);
       +              }
       +            }
       +          }
       +          move(LINES - 1, COLS - 1);
       +          refresh();
       +          c = getch();
       +          if (edit != NYM_DELETE && c >= '1' && c <= '9' && c - '1' < rnum) {
       +            menu_replychain(&defdesttype, &deflatent, mdest, pdest, psub,
       +                            replyblock[c - '1']);
       +            desttype[c - '1'] = defdesttype;
       +            latent[c - '1'] = deflatent;
       +            strncpy(dest[c - '1'],
       +                    desttype[c - '1'] == MSG_POST ? pdest : mdest, LINELEN);
       +            goto redraw;
       +          }
       +          switch (c) {
       +          case 'A':
       +            acksend = !acksend;
       +            goto redraw;
       +          case 'S':
       +            signsend = !signsend;
       +            goto redraw;
       +          case 'F':
       +            fixedsize = !fixedsize;
       +            goto redraw;
       +          case 'D':
       +            disable = !disable;
       +            goto redraw;
       +          case 'K':
       +            fingerkey = !fingerkey;
       +            goto redraw;
       +          case 'q':
       +            edit = 0;
       +            select = -1;
       +            goto nymselect;
       +          case '\014':
       +            goto redraw;
       +          case 'a':
       +            cl(2, 0);
       +            printw("Nym: a)lias address: ");
       +            echo();
       +            wgetnstr(stdscr, alias, LINELEN);
       +            noecho();
       +            for (i = 0; alias[i] > ' ' && alias[i] != '@'; i++) ;
       +            alias[i] = '\0';
       +            if (i == 0)
       +              goto nymselect;
       +            goto redraw;
       +          case 'p':
       +            cl(4, 0);
       +            printw("     p)seudonym: ");
       +            echo();
       +            wgetnstr(stdscr, line, LINELEN);
       +            noecho();
       +            if (line[0] != '\0')
       +              buf_sets(name, line);
       +            goto redraw;
       +          case 'c':
       +            menu_chain(sendchain, 0, 0);
       +            goto redraw;
       +          case 'n':
       +            cl(8, 0);
       +            printw("     n)umber of redundant copies: ");
       +            echo();
       +            wgetnstr(stdscr, line, LINELEN);
       +            noecho();
       +            sendnumcopies = strtol(line, NULL, 10);
       +            if (sendnumcopies < 1 || sendnumcopies > 10)
       +              sendnumcopies = 1;
       +            goto redraw;
       +          case 'r':
       +            cl(18, 0);
       +            printw("     number of r)eply chains: ");
       +            echo();
       +            wgetnstr(stdscr, line, LINELEN);
       +            noecho();
       +            i = rnum;
       +            rnum = strtol(line, NULL, 10);
       +            if (rnum < 1)
       +              rnum = 1;
       +            if (rnum > 5)
       +              rnum = 5;
       +            for (; i < rnum; i++)
       +              if (dest[i][0] == '\0') {
       +                desttype[i] = defdesttype;
       +                latent[i] = deflatent;
       +                strncpy(dest[i], defdesttype == MSG_POST ? pdest :
       +                        mdest, LINELEN);
       +              }
       +            goto redraw;
       +          case 's':
       +            menu_chain(nymserv, 2, 0);
       +            goto redraw;
       +          case '\n':
       +          case '\r':
       +            {
       +              BUFFER *chains;
       +              int err;
       +
       +              if (rnum == -1)
       +                chains = NULL;
       +              else {
       +                chains = buf_new();
       +                for (i = 0; i < rnum; i++)
       +                  if (replyblock[i][0] != '\0') {
       +                    if (desttype[i] == MSG_POST)
       +                      buf_appendf(chains, "Subject: %s\n", psub);
       +                    if (desttype[i] == MSG_MAIL)
       +                      buf_appends(chains, "To: ");
       +                    else if (desttype[i] == MSG_POST)
       +                      buf_appends(chains, "Newsgroups: ");
       +                    else
       +                      buf_appends(chains, "Null:");
       +                    buf_appendf(chains, "%s\n", dest[i]);
       +                    buf_appendf(chains, "Chain: %s\n", replyblock[i]);
       +                    buf_appendf(chains, "Latency: %d\n\n", latent[i]);
       +                  }
       +              }
       +            create:
       +              clear();
       +              buf_setf(opt,
       +                       " %cacksend %csignsend +cryptrecv %cfixedsize %cdisable %cfingerkey",
       +                       acksend ? '+' : '-',
       +                       signsend ? '+' : '-',
       +                       fixedsize ? '+' : '-',
       +                       disable ? '+' : '-',
       +                       fingerkey ? '+' : '-');
       +              if (edit) {
       +                mix_status("Preparing nymserver configuration message...");
       +                err = nym_config(edit, alias, NULL,
       +                                 name, sendchain, sendnumcopies,
       +                                 chains, opt);
       +              } else {
       +                mix_status("Preparing nym creation request...");
       +                err = nym_config(edit, alias, nymserv, name,
       +                                 sendchain, sendnumcopies, chains,
       +                                 opt);
       +              }
       +              if (err == -3) {
       +                beep();
       +                mix_status("Bad passphrase!");
       +                getch();
       +                goto create;
       +              }
       +              if (err != 0) {
       +                mix_genericerror();
       +                beep();
       +                refresh();
       +              } else {
       +                if (edit)
       +                  mix_status("Nymserver configuration message completed.");
       +                else
       +                  mix_status("Nym creation request completed.");
       +              }
       +              if (chains)
       +                buf_free(chains);
       +              goto end;
       +            }
       +          default:
       +            beep();
       +            goto loop;
       +          }
       +        }
       +      end:
       +        buf_free(name);
       +        buf_free(opt);
       +        return;
       +      }
       +#endif /* USE_PGP */
       +    default:
       +      beep();
       +      goto select;
       +    }
       +}
       +
       +#endif /* USE_NCURSES */
       +#endif /* NYMSUPPORT */
   DIR diff --git a/Src/menusend.c b/Src/menusend.c
       t@@ -0,0 +1,556 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Menu-based user interface -- send message
       +   $Id: menusend.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "menu.h"
       +#include "mix3.h"
       +#include <string.h>
       +#include <ctype.h>
       +#include <stdlib.h>
       +#ifdef POSIX
       +#include <unistd.h>
       +#else /* end of POSIX */
       +#include <io.h>
       +#endif /* else if not POSIX */
       +
       +void send_message(int type, char *nym, BUFFER *in)
       +{
       +  char dest[LINELEN] = "", subject[LINELEN] = "";
       +  char chain[CHAINMAX], thisnym[LINELEN], path[PATHMAX];
       +  BUFFER *chainlist, *msg, *txt, *tmp, *field, *content, *cc, *cite;
       +  int numcopies;
       +  int hdr = 0;                        /* txt buffer contains header lines */
       +  FILE *f;
       +  int n, err;
       +
       +#ifdef USE_PGP
       +  int sign = 0, encrypt = 0, key = 0;
       +
       +#endif /* USE_PGP */
       +#ifdef USE_NCURSES
       +  char reliability[9];
       +  int c;
       +  char line[LINELEN];
       +
       +#endif /* USE_NCURSES */
       +  msg = buf_new();
       +  tmp = buf_new();
       +  txt = buf_new();
       +  field = buf_new();
       +  content = buf_new();
       +  chainlist = buf_new();
       +  cc = buf_new();
       +  cite = buf_new();
       +  strncpy(chain, CHAIN, CHAINMAX);
       +  numcopies = NUMCOPIES;
       +
       +  mix_status("");
       +  strncpy(thisnym, nym, sizeof(thisnym));
       +
       +  if (in != NULL)
       +    buf_set(txt, in);
       +
       +  if (bufileft(txt, "From "))
       +    buf_getline(txt, field);        /* ignore envelope From */
       +
       +  if (type == 'p' || type == 'm') {
       +#ifndef USE_NCURSES
       +    mix_status("Invalid option to -f");
       +    mix_exit();
       +    exit(1);
       +#else /* end of not USE_NCURSES */
       +    clear();
       +    echo();
       +    if (in != NULL)
       +      mvprintw(1, 0, "%s forwarding message...", thisnym);
       +    if (type == 'p')
       +      mvprintw(3, 0, "Newsgroups: ");
       +    else
       +      mvprintw(3, 0, "Send message to: ");
       +    refresh();
       +    wgetnstr(stdscr, dest, LINELEN);
       +    if (dest[0] == '\0') {
       +      noecho();
       +      cl(3, 0);
       +      goto quit;
       +    }
       +    if (txt->length == 0) {
       +      mvprintw(4, 0, "Subject: ");
       +      refresh();
       +      wgetnstr(stdscr, subject, LINELEN);
       +    } else {
       +      strcpy(subject, "Forwarded message");
       +      while (buf_getheader(txt, field, content) == 0) {
       +        if (bufieq(field, "subject")) {
       +          strncpy(subject, content->data, sizeof(subject));
       +          strcatn(subject, " (fwd)", sizeof(subject));
       +        }
       +        if (bufieq(field, "from") || bufieq(field, "subject") ||
       +            bufieq(field, "date"))
       +          buf_appendheader(tmp, field, content);
       +      }
       +      buf_nl(tmp);
       +      buf_rest(tmp, txt);
       +      buf_move(txt, tmp);
       +    }
       +    noecho();
       +#endif /* else if USE_NCURSES */
       +  } else {
       +    strcpy(subject, "Re: your mail");
       +    while (buf_getheader(txt, field, content) == 0) {
       +      if (bufieq(field, "subject")) {
       +        if (bufileft(content, "Re:"))
       +          subject[0] = '\0';
       +        else
       +          strcpy(subject, "Re: ");
       +        strcatn(subject, content->data, sizeof(subject));
       +      }
       +      if (bufieq(field, "from"))
       +        buf_set(cite, content);
       +      if (type == 'p' || type == 'f') {
       +        if (dest[0] == '\0' && bufieq(field, "newsgroups"))
       +          strncpy(dest, content->data, sizeof(dest));
       +        if (bufieq(field, "followup-to") && !bufieq(content, "poster"))
       +          strncpy(dest, content->data, sizeof(dest));
       +        if (bufieq(field, "message-id"))
       +          buf_appendf(tmp, "References: %b\n", content);
       +      } else {
       +        if (dest[0] == '\0' && bufieq(field, "from"))
       +          strncpy(dest, content->data, sizeof(dest));
       +        if (bufieq(field, "reply-to"))
       +          strncpy(dest, content->data, sizeof(dest));
       +        if (type == 'g' && (bufieq(field, "to") || bufieq(field, "cc"))) {
       +          if (cc->length)
       +            buf_appends(cc, ", ");
       +          buf_cat(cc, content);
       +        }
       +        if (bufieq(field, "message-id"))
       +          buf_appendf(tmp, "In-Reply-To: %b\n", content);
       +      }
       +    }
       +    if (cc->length)
       +      buf_appendf(tmp, "Cc: %b\n", cc);
       +    if (tmp->length > 0)
       +      hdr = 1;
       +    if (hdr)
       +      buf_nl(tmp);
       +
       +    if ((type == 'f' || type == 'g') && cite->length) {
       +      buf_appendf(tmp, "%b wrote:\n\n", cite);
       +    }
       +    if (type == 'r')
       +      buf_appends(tmp, "You wrote:\n\n");
       +
       +    while (buf_getline(txt, content) != -1)
       +      buf_appendf(tmp, "> %b\n", content);
       +    buf_set(txt, tmp);
       +    if (dest[0] == '\0') {
       +#ifdef USE_NCURSES
       +      beep();
       +      mix_status("No recipient address found.");
       +#endif /* USE_NCURSES */
       +      goto quit;
       +    }
       +    goto edit;
       +  }
       +
       +#ifdef USE_NCURSES
       +redraw:
       +  clear();
       +
       +  for (;;) {
       +    standout();
       +    mvprintw(0, 0, "Mixmaster %s - ", VERSION);
       +    printw(type == 'p' || type == 'f' ? "posting to Usenet" : "sending mail");
       +    standend();
       +    mix_status(NULL);
       +    cl(2, 0);
       +#ifdef NYMSUPPORT
       +    printw("n)ym: %s", thisnym);
       +#endif /* NYMSUPPORT */
       +    if (!strleft(thisnym, NONANON)) {
       +      chain_reliability(chain, 0, reliability);   /* chaintype 0=mix */
       +      cl(4, 0);
       +      printw("c)hain: %-35s (reliability: %s)", chain, reliability);
       +      cl(5, 0);
       +      printw("r)edundancy: %3d copies ", numcopies);
       +    }
       +    cl(7, 0);
       +    printw("d)estination: %s", dest);
       +    cl(8, 0);
       +    printw("s)ubject: %s", subject);
       +#ifdef USE_PGP
       +    if (type != 'p' && type != 'f') {
       +      cl(10, 0);
       +      printw("pgp encry)ption: ");
       +      if (encrypt)
       +        printw("yes");
       +      else
       +        printw("no");
       +    }
       +    if (!streq(thisnym, ANON)) {
       +      cl(11, 0);
       +      printw("p)gp signature: ");
       +      if (sign)
       +        printw("yes");
       +      else
       +        printw("no");
       +      cl(12, 0);
       +      if (key == 0)
       +        printw("attach pgp k)ey: no");
       +    }
       +#endif /* USE_PGP */
       +
       +    if (txt->length == 0)
       +      mvprintw(LINES - 3, 18,
       +               "e)dit message           f)ile      q)uit w/o sending");
       +    else
       +      mvprintw(LINES - 3, 0,
       +               "m)ail message      e)dit message         f)ile          q)uit w/o sending");
       +    move(LINES - 1, COLS - 1);
       +    refresh();
       +    c = getch();
       +    if (c != ERR) {
       +      mix_status("");
       +      if (c == '\r' || c == '\n') {        /* default action is edit or mail */
       +        if (txt->length == 0)
       +          c = 'e';
       +        else
       +          c = 'm';
       +      }
       +      switch (c) {
       +#ifdef NYMSUPPORT
       +      case 'n':
       +        menu_nym(thisnym);
       +        goto redraw;
       +#endif /* NYMSUPPORT */
       +      case '\014':
       +        goto redraw;
       +      case 'd':
       +        echo();
       +        cl(LINES - 3, 20);
       +        cl(7, 14);
       +        wgetnstr(stdscr, dest, LINELEN);
       +        noecho();
       +        break;
       +      case 's':
       +        echo();
       +        cl(LINES - 3, 20);
       +        cl(8, 10);
       +        wgetnstr(stdscr, subject, LINELEN);
       +        noecho();
       +        break;
       +      case 'c':
       +        menu_chain(chain, 0, (type == 'p' || type == 'f')
       +                   && streq(thisnym, ANON));
       +        goto redraw;
       +      case 'r':
       +        echo();
       +        cl(LINES - 5, 20);
       +        cl(5, 13);
       +        wgetnstr(stdscr, line, LINELEN);
       +        numcopies = strtol(line, NULL, 10);
       +        if (numcopies < 1 || numcopies > 10)
       +          numcopies = 1;
       +        noecho();
       +        break;
       +      case 'f':
       +        cl(LINES - 3, 0);
       +        askfilename(path);
       +        cl(LINES - 3, 0);
       +        if (txt->length) {
       +          buf_sets(tmp, path);
       +          buf_clear(msg);
       +          if (!hdr)
       +            buf_nl(msg);
       +          buf_cat(msg, txt);
       +          if (attachfile(msg, tmp) == -1)
       +            beep();
       +          else {
       +            buf_move(txt, msg);
       +            hdr = 1;
       +          }
       +        } else {
       +          if ((f = fopen(path, "r")) != NULL) {
       +            buf_clear(txt);
       +            buf_read(txt, f);
       +            fclose(f);
       +          } else
       +            beep();
       +        }
       +        break;
       +      case 'e':
       +#endif /* USE_NCURSES */
       +        {
       +          int linecount;
       +
       +        edit:
       +          linecount = 1;
       +          sprintf(path, "%s%cx%02x%02x%02x%02x.txt", POOLDIR, DIRSEP,
       +                  rnd_byte(), rnd_byte(), rnd_byte(), rnd_byte());
       +          f = fopen(path, "w");
       +          if (f == NULL) {
       +#ifdef USE_NCURSES
       +            beep();
       +#endif /* USE_NCURSES */
       +          } else {
       +            if (type == 'f' || type == 'p')
       +              fprintf(f, "Newsgroups: %s\n", dest);
       +            if (type == 'r' || type == 'g' || type == 'm')
       +              fprintf(f, "To: %s\n", dest);
       +            fprintf(f, "Subject: %s\n", subject);
       +            linecount += 2;
       +            if (hdr)
       +              while (buf_getline(txt, NULL) == 0) linecount++;
       +            else
       +              fprintf(f, "\n");
       +            linecount++;
       +            if (txt->length == 0)
       +              fprintf(f, "\n");
       +
       +            buf_write(txt, f);
       +            fclose(f);
       +          }
       +
       +          menu_spawn_editor(path, linecount);
       +
       +          f = fopen(path, "r");
       +          if (f == NULL) {
       +#ifdef USE_NCURSES
       +            clear();
       +            beep();
       +            continue;
       +#else /* end of USE_NCURSES */
       +            goto quit;
       +#endif /* else if not USE_NCURSES */
       +          }
       +          buf_reset(txt);
       +          hdr = 0;
       +
       +          buf_reset(tmp);
       +          buf_read(tmp, f);
       +          while (buf_getheader(tmp, field, content) == 0) {
       +            if (bufieq(field, "subject"))
       +              strncpy(subject, content->data,
       +                      sizeof(subject));
       +            else if ((type == 'p' || type == 'f') &&
       +                     bufieq(field, "newsgroups"))
       +              strncpy(dest, content->data, sizeof(dest));
       +            else if (bufieq(field, "to"))
       +              strncpy(dest, content->data, sizeof(dest));
       +            else {
       +              buf_appendheader(txt, field, content);
       +              hdr = 1;
       +            }
       +          }
       +          if (hdr)
       +            buf_nl(txt);
       +          buf_rest(txt, tmp);
       +
       +          fclose(f);
       +          unlink(path);
       +          strcatn(path, "~", PATHMAX);
       +          unlink(path);
       +#ifndef USE_NCURSES
       +          {
       +            char line[4];
       +
       +            fprintf(stderr, "Send message [y/n]? ");
       +            scanf("%3s", line);
       +            if (!strleft(line, "y"))
       +              goto quit;
       +          }
       +#else /* end of not USE_NCURSES */
       +          goto redraw;
       +        }
       +        break;
       +      case 'm':
       +        if (txt->length == 0)
       +          beep();
       +        else if (dest[0] == '\0') {
       +          mix_status("No destination given.");
       +          goto redraw;
       +        } else {
       +          mix_status("Creating message...");
       +#endif /* else if USE_NCURSES */
       +          buf_reset(msg);
       +
       +          if (type == 'p' || type == 'f')
       +            buf_appends(msg, "Newsgroups: ");
       +          else
       +            buf_appends(msg, "To: ");
       +          buf_appends(msg, dest);
       +          buf_nl(msg);
       +          buf_appends(msg, "Subject: ");
       +          if (subject[0] == '\0')
       +            buf_appends(msg, "(no subject)");
       +          else
       +            buf_appends(msg, subject);
       +          buf_nl(msg);
       +          if (!hdr)
       +            buf_nl(msg);
       +          buf_cat(msg, txt);
       +#ifdef USE_PGP
       +          {
       +            BUFFER *p;
       +
       +            p = buf_new();
       +            if (streq(thisnym, ANON))
       +              sign = 0;
       +            if (sign || (key && !strileft(thisnym, NONANON)))
       +              user_pass(p);
       +
       +            if (encrypt || sign) {
       +              if (pgp_mailenc((encrypt ? PGP_ENCRYPT : 0)
       +                              | (sign ? PGP_SIGN : 0) | PGP_TEXT
       +                              | (strleft(thisnym, NONANON) ? 0 : PGP_REMAIL),
       +                              msg, strleft(thisnym, NONANON) ?
       +                              ADDRESS : thisnym, p, PGPPUBRING,
       +                              strleft(thisnym, NONANON) ?
       +                              PGPSECRING : NYMSECRING) == -1) {
       +                mix_genericerror();
       +#ifdef USE_NCURSES
       +                beep();
       +                goto redraw;
       +#endif /* USE_NCURSES */
       +              }
       +            }
       +            buf_free(p);
       +          }
       +#endif /* USE_PGP */
       +
       +          if (strleft(thisnym, NONANON)) {
       +            FILE *f = NULL;
       +
       +            if (type == 'p' || type == 'f') {
       +              if (strchr(NEWS, '@')) {
       +                /*  NOT_IMPLEMENTED; */
       +              } else
       +                f = openpipe(NEWS);
       +            } else {
       +              if (NAME[0]) {
       +                buf_sets(tmp, NAME);
       +                buf_appends(tmp, " <");
       +                buf_appends(tmp, ADDRESS);
       +                buf_appends(tmp, ">");
       +              } else
       +                buf_sets(tmp, ADDRESS);
       +              mail_encode(msg, 0);
       +              if (sendmail(msg, tmp->data, NULL) != 0) {
       +#ifdef USE_NCURSES
       +                clear();
       +#endif /* USE_NCURSES */
       +                mix_status("Error sending message.");
       +#ifdef USE_NCURSES
       +                goto redraw;
       +#else /* end of USE_NCURSES */
       +                goto quit;
       +#endif /* else if not USE_NCURSES */
       +              }
       +            }
       +#ifdef USE_NCURSES
       +            clear();
       +#endif /* USE_NCURSES */
       +            mix_status("Message sent non-anonymously.");
       +            goto quit;
       +          } else {
       +#ifdef USE_PGP
       +#ifdef NYMSUPPORT
       +            if (!streq(thisnym, ANON)) {
       +              if (nym_encrypt(msg, thisnym, (type == 'p' || type == 'f') ?
       +                              MSG_POST : MSG_MAIL) == 0)
       +                type = 'm';
       +            }
       +#endif /* NYMSUPPORT */
       +#endif /* USE_PGP */
       +            err = mix_encrypt((type == 'p' || type == 'f') ?
       +                              MSG_POST : MSG_MAIL,
       +                              msg, chain, numcopies, chainlist);
       +            if (err == 0) {
       +#ifdef USE_NCURSES
       +              clear();
       +#endif /* USE_NCURSES */
       +              for (n = 0; buf_getline(chainlist, tmp) == 0; n++) ;
       +              if (n > 1)
       +                mix_status("Done. (%d packets)", n);
       +              else
       +                mix_status("Chain: %s", chainlist->data);
       +              goto quit;
       +            } else {
       +#ifdef USE_NCURSES
       +              beep();
       +#endif /* USE_NCURSES */
       +              if (chainlist->length)
       +                mix_status("%s", chainlist->data);
       +              else
       +                mix_genericerror();
       +            }
       +          }
       +        }
       +#ifdef USE_NCURSES
       +        break;
       +      case 'q':
       +      case 'Q':
       +        clear();
       +        goto quit;
       +#ifdef USE_PGP
       +      case 'p':
       +        if (!streq(thisnym, ANON))
       +          sign = !sign;
       +        break;
       +      case 'y':
       +        encrypt = !encrypt;
       +        break;
       +      case 'k':
       +        if (!streq(thisnym, ANON)) {
       +          BUFFER *p, *keytxt, *uid;
       +
       +          key = 1;
       +          p = buf_new();
       +          keytxt = buf_new();
       +          uid = buf_new();
       +
       +          buf_appendf(uid, "<%s>", strleft(thisnym, NONANON) ? ADDRESS :
       +                      thisnym);
       +          user_pass(p);
       +          pgp_pubkeycert(uid, strleft(thisnym, NONANON) ?
       +                         PGPSECRING : NYMSECRING, p, keytxt, PGP_ARMOR_NYMKEY);
       +
       +          buf_clear(msg);
       +          if (!hdr)
       +            buf_nl(msg);
       +          buf_cat(msg, txt);
       +          buf_sets(p, "application/pgp-keys");
       +          mime_attach(msg, keytxt, p);
       +          hdr = 1;
       +          buf_move(txt, msg);
       +
       +          buf_free(p);
       +          buf_free(keytxt);
       +          buf_free(uid);
       +        }
       +        break;
       +#endif /* USE_PGP */
       +      default:
       +        beep();
       +      }
       +    }
       +  }
       +#endif /* USE_NCURSES */
       +quit:
       +  buf_free(cc);
       +  buf_free(cite);
       +  buf_free(msg);
       +  buf_free(txt);
       +  buf_free(field);
       +  buf_free(content);
       +  buf_free(chainlist);
       +  buf_free(tmp);
       +}
   DIR diff --git a/Src/menustats.c b/Src/menustats.c
       t@@ -0,0 +1,445 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Menu-based user interface
       +   $Id: menustats.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#if 0
       +void errlog(int type, char *format, ...) { };
       +char MIXDIR[512];
       +#include "util.c"
       +#include "buffers.c"
       +int menu_getuserpass(BUFFER *p, int mode) { return 0; };
       +#endif
       +
       +#include <string.h>
       +#include <assert.h>
       +#include <stdlib.h>
       +
       +#include "menu.h"
       +#ifdef WIN32
       +#include <urlmon.h>
       +#pragma comment(lib,"urlmon.lib")
       +#else
       +#include <sys/wait.h>
       +#endif /* WIN32 */
       +
       +
       +int url_download(char *url, char *dest) {
       +  int err;
       +#ifdef WIN32
       +  err = URLDownloadToFile(NULL, url, dest, BINDF_GETNEWESTVERSION, NULL);
       +
       +  if (err != S_OK)
       +    return -1;
       +  else
       +    return 0;
       +#else
       +  char s[PATHMAX];
       +  snprintf(s, PATHMAX, "%s -q %s -O %s", WGET, url, dest);
       +  err = system(s);
       +
       +  if (err != -1) {
       +    if (WIFEXITED(err) == 0)
       +      return -1; /* abnormal child exit */
       +    else
       +      return 0;
       +  }
       +  else
       +    return -1;
       +#endif /* WIN32 */
       +}
       +
       +/** read the allpingers file into the buffer */
       +void read_allpingers(BUFFER *allpingers) {
       +  FILE *f;
       +
       +  f = mix_openfile(ALLPINGERSFILE, "r");
       +  if (f != NULL) {
       +    buf_clear(allpingers);
       +    buf_read(allpingers, f);
       +    fclose(f);
       +  }
       +}
       +
       +/* Get all sections from inifile.
       + *
       + * They are put into the sections buffer, separated by newlines
       + */
       +void get_sections(BUFFER *inifile, BUFFER  *sections) {
       +  BUFFER *line;
       +  int err;
       +
       +  line = buf_new();
       +
       +  buf_rewind(inifile);
       +  buf_reset(sections);
       +
       +  while ((err = buf_getline(inifile, line)) != -1) {
       +    if (bufileft (line, "[") &&
       +        bufiright(line, "]")) {
       +      line->data[line->length-1] = '\0';
       +      buf_appends(sections, line->data+1);
       +      buf_nl(sections);
       +    };
       +  }
       +  buf_free (line);
       +}
       +
       +/* Get value of an attribute
       + *
       + * returns -1 if it isn't found.
       + */
       +int get_attribute(BUFFER *inifile, char *section, char *attribute, BUFFER *value) {
       +  BUFFER *line;
       +  int err = -1;
       +  int insection = 0;
       +
       +  line = buf_new();
       +
       +  buf_rewind(inifile);
       +  buf_reset(value);
       +
       +  while (buf_getline(inifile, line) != -1) {
       +    if (bufileft (line, "[") &&
       +        bufiright(line, "]")) {
       +      if (insection)
       +        break;
       +
       +      line->data[line->length-1] = '\0';
       +      if (strcasecmp(section, line->data+1) == 0) {
       +        insection = 1;
       +      }
       +    } else if (insection && bufileft(line, attribute)) {
       +      /* we are in the right section and this attribute name
       +       * at least starts with what we want */
       +      char *ptr = line->data + strlen(attribute);
       +      /* eat up whitespace */
       +      while ((*ptr == ' ') || (*ptr == '\t'))
       +        ptr++;
       +      if (*ptr != '=')
       +        continue;
       +      ptr++;
       +      while ((*ptr == ' ') || (*ptr == '\t'))
       +        ptr++;
       +      buf_appends(value, ptr);
       +      err = 0;
       +      break;
       +    }
       +  }
       +  buf_free (line);
       +  return (err);
       +}
       +
       +
       +
       +
       +
       +static char *files[] = { "mlist", "rlist", "mixring", "pgpring"};
       +#define NUMFILES sizeof(files)/sizeof(*files)
       +
       +/* Download all the needed files from the specified source */
       +/* returns -1 on error */
       +int stats_download(BUFFER *allpingers, char *sourcename, int curses) {
       +  char *localfiles[] = { TYPE2REL, TYPE1LIST, PUBRING, PGPREMPUBASC };
       +  char path[PATHMAX];
       +  char path_t[PATHMAX];
       +  BUFFER *value;
       +  int ret = 0;
       +  int err;
       +  int i;
       +
       +  value = buf_new();
       +
       +  if (curses) {
       +    clear();
       +  }
       +
       +  err = get_attribute(allpingers, sourcename, "base", value);
       +  if (err == 0) {
       +    if (curses) {
       +      standout();
       +      printw("%s", value->data);
       +      standend();
       +    }
       +    else
       +      printf("%s\n\r", value->data);
       +  }
       +
       +/* Loop to get each file in turn to a temp file */
       +
       +  for (i=0; i<NUMFILES; i++) {
       +    err = get_attribute(allpingers, sourcename, files[i], value);
       +    if (err < 0) {
       +      /* the attribute vanished under us */
       +      ret = -1;
       +      break;
       +    }
       +    mixfile(path, localfiles[i]);
       +    if (curses) {
       +      mvprintw(i+3, 0, "downloading %s from %s...", localfiles[i], value->data);
       +      refresh();
       +    }
       +    else
       +      printf("downloading %s from %s...", localfiles[i], value->data);
       +    err = url_download(value->data, strcat(path, ".t"));
       +    if (err < 0) {
       +      if (curses)
       +        printw("failed to download.\n\rTry using another stats source.");
       +      else
       +        printf("failed to download.\n\rTry using another stats source.\n\r");
       +      ret = -1;
       +      break;
       +    }
       +    if (curses)
       +      printw("done");
       +    else
       +      printf("done\n\r");
       +  }
       +
       +/* We got them all ok - so rename them to their correct names */
       +
       +  for (i=0; i<NUMFILES; i++) {
       +    mixfile(path, localfiles[i]);
       +    mixfile(path_t, localfiles[i]);
       +    strcat(path_t, ".t");
       +    rename(path_t, path);
       +  }
       +  
       +  if (curses) {  
       +    printw("\n\n\n\n\rPress any key to continue");
       +    getch();
       +    clear();
       +  }
       +  buf_free(value);
       +  return ret;
       +}
       +/* Checks whether the stats source has all the required files.
       + *
       + * 1 if it has,
       + * 0 otherwise
       + */
       +int good_stats_source (BUFFER *allpingers, char *sourcename) {
       +  BUFFER *value;
       +  int i;
       +  int res = 1;
       +  int err;
       +
       +  value = buf_new();
       +
       +  for (i = 0; i < NUMFILES; i++) {
       +    err = get_attribute(allpingers, sourcename, files[i], value);
       +    if (err < 0) {
       +      res = 0;
       +      break;
       +    }
       +  }
       +
       +  buf_free (value);
       +  return (res);
       +}
       +
       +/* Do a stats download update and report status */
       +/* 0  on success              */
       +/* -1 File download failed    */
       +/* -2 Error writing file      */
       +/* -3 Stats source incomplete */
       +
       +int download_stats(char *sourcename) {
       +  BUFFER *inifile;
       +  FILE *f;
       +  int ret;
       +  inifile = buf_new();
       +  read_allpingers(inifile);
       +  if (good_stats_source(inifile, sourcename) == 1) {
       +    if (stats_download(inifile, sourcename, 0) == 0) {
       +      f = mix_openfile(STATSSRC, "w+");
       +      if (f != NULL) {
       +        fprintf(f, "%s", sourcename);
       +        fclose(f);
       +        ret = 0;
       +      } else {
       +        ret = -2;
       +        errlog(ERRORMSG, "Could not open stats source file for writing.\n");
       +      }
       +    } else {
       +        ret = -1;
       +        errlog(ERRORMSG, "Stats source download failed.\n");
       +    }
       +  } else {
       +      ret = -3;
       +      errlog(ERRORMSG, "Stats source does not include all required files.\n");
       +  }
       +
       +  buf_free(inifile);
       +  return (ret);
       +}
       +
       +
       +/* Download allpingers.txt */
       +/* -1 on error */
       +static int download_list() {
       +  char path[PATHMAX];
       +
       +  mixfile(path, ALLPINGERSFILE);
       +
       +  clear();
       +  standout();
       +  printw(ALLPINGERSURL);
       +  standend();
       +
       +  mvprintw(3,0,"downloading %s...", ALLPINGERSURL);
       +  refresh();
       +  if (url_download(ALLPINGERSURL, path) < 0) {
       +    printw("failed to download.\n\rTry again later.");
       +    printw("\n\n\rPress any key to continue");
       +    getch();
       +    return -1;
       +  }
       +  return 0;
       +}
       +
       +/* Displays the choice of stats sources */
       +#define MAXPING (26 * 2)
       +void update_stats() {
       +  char c;
       +  BUFFER *inifile;
       +  BUFFER *pingernames;
       +  BUFFER *goodpingers;
       +  BUFFER *line;
       +  BUFFER *statssrc;
       +  FILE *f;
       +  int num;
       +  int err;
       +  int x, y;
       +  int i;
       +
       +  inifile = buf_new();
       +  pingernames = buf_new();
       +  goodpingers = buf_new();
       +  line = buf_new();
       +  statssrc = buf_new();
       +
       +  while (1) {
       +    clear();
       +    standout();
       +    buf_clear(statssrc);
       +    f = mix_openfile(STATSSRC, "r");
       +    if (f != NULL) {
       +      buf_read(statssrc, f);
       +      fclose(f);
       +    }
       +    printw("Select stats source:");
       +    standend();
       +    if (statssrc->length > 0)
       +      printw("       Current: %s (Enter to download)", statssrc->data);
       +    printw("\n\n");
       +
       +    read_allpingers(inifile);
       +    get_sections (inifile, pingernames);
       +
       +    num = 0;
       +    buf_reset(goodpingers);
       +    buf_rewind(pingernames);
       +    while ((buf_getline(pingernames, line) != -1) && num < MAXPING) {
       +      if (good_stats_source (inifile, line->data)) {
       +        buf_cat(goodpingers, line);
       +        buf_nl(goodpingers);
       +        num++;
       +      }
       +    }
       +
       +    x = 0;
       +    buf_rewind(goodpingers);
       +    for (i=0; i<num; i++) {
       +      err = buf_getline(goodpingers, line);
       +      assert (err != -1);
       +      y = i;
       +      if (y >= LINES - 6)
       +        y -= LINES - 6, x = 40;
       +      mvprintw(y + 2, x, "%c", i < 26 ? i + 'a' : i - 26 + 'A');
       +      mvprintw(y + 2, x + 2, "%s", line->data);
       +    }
       +    y = i + 3;
       +    if (y > LINES - 4)
       +      y = LINES - 4;
       +    mvprintw(y, 0, "*  update list of pingers from web     =  edit list       <space> to exit");
       +    c = getch();
       +    if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
       +      if (c >= 'a')
       +        c -= 'a';
       +      else
       +        c = c - 'A' + 26;
       +      if (c < num) {
       +        buf_rewind(goodpingers);
       +        while (c >= 0) {
       +          err = buf_getline(goodpingers, line);
       +          assert (err != -1);
       +          c--;
       +        }
       +        if (stats_download(inifile, line->data, 1) == 0) {
       +          f = mix_openfile(STATSSRC, "w+");
       +          if (f != NULL) {
       +            fprintf(f, "%s", line->data);
       +            fclose(f);
       +          } else
       +            fprintf(stderr, "Could not open stats source file for writing\n");
       +          break;
       +        }
       +      }
       +    }
       +    else if (c == '*') {
       +      download_list();
       +    }
       +    else if (c == '=') {
       +      char path[PATHMAX];
       +      mixfile(path, ALLPINGERSFILE);
       +      menu_spawn_editor(path, 0);
       +    }
       +    else if ((c == '\r') && statssrc->length) {
       +      stats_download(inifile, statssrc->data, 1);
       +      break;
       +    }
       +    else if (c == ' ') {
       +      break;
       +    }
       +  }
       +  clear();
       +
       +  buf_free(statssrc);
       +  buf_free(inifile);
       +  buf_free(line);
       +  buf_free(pingernames);
       +  buf_free(goodpingers);
       +}
       +
       +#if 0
       +int main() {
       +  strcpy(MIXDIR,"./");
       +
       +  BUFFER *allpingers;
       +  BUFFER *pingernames;
       +  BUFFER *value;
       +
       +  allpingers = buf_new();
       +  pingernames = buf_new();
       +  value = buf_new();
       +
       +  read_allpingers (allpingers);
       +  get_sections (allpingers, pingernames);
       +
       +  printf("%s", pingernames->data);
       +
       +  get_attribute (allpingers, "noreply", "rlist", value);
       +  printf("%s\n", value->data);
       +
       +
       +  exit(0);
       +}
       +
       +#endif
   DIR diff --git a/Src/menuutil.c b/Src/menuutil.c
       t@@ -0,0 +1,154 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Menu-based user interface - utility functions
       +   $Id: menuutil.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "menu.h"
       +#include <stdarg.h>
       +#include <stdlib.h>
       +#include <ctype.h>
       +#include <string.h>
       +
       +int menu_initialized = 0;
       +
       +#ifdef USE_NCURSES
       +void cl(int y, int x)
       +{
       +  move(y, x);
       +  hline(' ', COLS - x);
       +}
       +#endif /* USE_NCURSES */
       +
       +void menu_init(void)
       +{
       +#ifdef USE_NCURSES
       +  initscr();
       +  cbreak();
       +  noecho();
       +  nonl();
       +  intrflush(stdscr, FALSE);
       +  keypad(stdscr, TRUE);
       +  menu_initialized = 1;
       +#endif /* USE_NCURSES */
       +}
       +
       +void menu_exit(void)
       +{
       +  user_delpass();
       +#ifdef USE_NCURSES
       +  endwin();
       +#endif /* USE_NCURSES */
       +}
       +
       +#ifdef USE_NCURSES
       +void askfilename(char *path)
       +{
       +  char line[PATHMAX];
       +
       +  printw("\rFile name: ");
       +  echo();
       +  wgetnstr(stdscr, path, PATHMAX);
       +  noecho();
       +  printw("\r");
       +  if (path[0] == '~') {
       +    char *h;
       +
       +    if ((h = getenv("HOME")) != NULL) {
       +      strncpy(line, h, PATHMAX);
       +      strcatn(line, "/", PATHMAX);
       +      strcatn(line, path + 1, PATHMAX);
       +      strncpy(path, line, PATHMAX);
       +    }
       +  }
       +}
       +
       +void savemsg(BUFFER *message)
       +{
       +  char savename[PATHMAX];
       +  FILE *f;
       +
       +  askfilename(savename);
       +  f = fopen(savename, "a");
       +  if (f != NULL) {
       +    buf_write(message, f);
       +    fclose(f);
       +  }
       +}
       +
       +#endif /* USE_NCURSES */
       +
       +void menu_spawn_editor(char *path, int lineno) {
       +#ifdef WIN32
       +  SHELLEXECUTEINFO sei;
       +  ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));
       +  sei.cbSize = sizeof(SHELLEXECUTEINFO);
       +  sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
       +  sei.hwnd = NULL;
       +  sei.lpVerb = "open";
       +  sei.lpFile = path;
       +  sei.lpParameters = NULL;
       +  sei.nShow = SW_SHOWNORMAL;
       +
       +  if (ShellExecuteEx(&sei) == TRUE) {
       +    WaitForSingleObject(sei.hProcess, INFINITE);
       +    CloseHandle(sei.hProcess);
       +  }
       +#else /* WIN32 */
       +  char *editor;
       +  char s[PATHMAX];
       +
       +/* Command line option +nn to position the cursor? */
       +#define cursorpos (strfind(editor, "emacs") || streq(editor, "vi") || \
       +                   streq(editor, "joe"))
       +
       +  editor = getenv("EDITOR");
       +  if (editor == NULL)
       +    editor = "vi";
       +
       +  if (lineno > 1 && cursorpos)
       +    snprintf(s, PATHMAX, "%s +%d %s", editor, lineno, path);
       +  else
       +    snprintf(s, PATHMAX, "%s %s", editor, path);
       +
       +#ifdef USE_NCURSES
       +  clear();
       +  refresh();
       +  endwin();
       +#endif /* USE_NCURSES */
       +  system(s);
       +#ifdef USE_NCURSES
       +  refresh();
       +#endif /* USE_NCURSES */
       +
       +#endif /* WIN32 */
       +}
       +
       +int menu_getuserpass(BUFFER *b, int mode)
       +{
       +#ifdef USE_NCURSES
       +  char p[LINELEN];
       +
       +  if (menu_initialized) {
       +    cl(LINES - 1, 10);
       +    if (mode == 0)
       +      printw("enter passphrase: ");
       +    else
       +      printw("re-enter passphrase: ");
       +    wgetnstr(stdscr, p, LINELEN);
       +    cl(LINES - 1, 10);
       +    refresh();
       +    if (mode == 0)
       +      buf_appends(b, p);
       +    else
       +      return (bufeq(b, p));
       +    return (0);
       +  }
       +#endif /* USE_NCURSES */
       +  return (-1);
       +}
   DIR diff --git a/Src/mime.c b/Src/mime.c
       t@@ -0,0 +1,814 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   MIME functions
       +   $Id: mime.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include <ctype.h>
       +#include <string.h>
       +
       +#define hex(i) (isdigit(i) ? (i) - '0' : tolower(i) - 'a' + 10)
       +
       +#define hexdigit(i) ((byte)(i < 10 ? i + '0' : i - 10 + 'A'))
       +
       +static void encode_word(BUFFER *in)
       +{
       +  BUFFER *out;
       +  int i;
       +
       +  out = buf_new();
       +  for (i = 0; i < in->length; i++)
       +    if (in->data[i] < 32 || in->data[i] >= 127 || in->data[i] == '='
       +        || in->data[i] == '?' || in->data[i] == '_') {
       +      buf_appendc(out, '=');
       +      buf_appendc(out, hexdigit(in->data[i] / 16));
       +      buf_appendc(out, hexdigit(in->data[i] % 16));
       +    } else if (in->data[i] == ' ')
       +      buf_appendc(out, '_');
       +    else
       +      buf_appendc(out, in->data[i]);
       +  buf_move(in, out);
       +  buf_free(out);
       +}
       +
       +void body_encode(BUFFER *in, int transport, BUFFER *hdr)
       +{
       +  BUFFER *out;
       +  int c, l=0, encoding = 0;
       +  out = buf_new();
       +
       +  buf_clear(hdr);
       +
       +  l = in->ptr;
       +  while ((c = buf_getc(in)) != -1 && encoding != 2) {
       +    if (c >= 160)
       +      encoding = 1;
       +    else if (c == ' ') {
       +      if (buf_getc(in) == '\n')
       +        encoding = 1;
       +      buf_ungetc(in);
       +    } else if ((c < 32 && c != ' ' && c != '\n' && c != '\t') ||
       +               (c >= 127 && c < 160)) {
       +      encoding = 2;
       +    }
       +  }
       +  in->ptr = l;
       +
       +  if (encoding == 2) {
       +    buf_sets(hdr, "Content-Transfer-Encoding: base64\n");
       +    encode(in, 76);
       +  } else {
       +
       +#if 0
       +    if (encoding == 0)
       +      buf_sets(hdr, "Content-Transfer-Encoding: 7bit\n");
       +#endif
       +    if (encoding != 0 && transport == MIME_8BIT)
       +      buf_sets(hdr, "Content-Transfer-Encoding: 8bit\n");
       +    if (encoding == 0 || transport == MIME_8BIT) {
       +      buf_rest(out, in); /* transparent */
       +      buf_move(in, out);
       +    } else {
       +      buf_sets(hdr, "Content-Transfer-Encoding: quoted-printable\n");
       +      l = 0;
       +      while ((c = buf_getc(in)) != -1) {
       +        if (c == '\n') {
       +          buf_nl(out);
       +          l = 0;
       +        }
       +        else if (c < 32 || c >= 127 || c == '=') {
       +          if (l > 73) {
       +            buf_appends(out, "=\n");
       +            l = 0;
       +          }
       +          buf_appendc(out, '=');
       +          buf_appendc(out, hexdigit(c / 16));
       +          buf_appendc(out, hexdigit(c % 16));
       +          l += 3;
       +        } else if (c == ' ') {
       +          if (buf_getc(in) == '\n') {
       +            buf_appendc(out, '=');
       +            buf_appendc(out, hexdigit(c / 16));
       +            buf_appendc(out, hexdigit(c % 16));
       +            buf_nl(out);
       +            l = 0;
       +          } else {
       +            buf_appendc(out, c);
       +            buf_ungetc(in);
       +            l++;
       +          }
       +        } else {
       +          buf_appendc(out, c);
       +          l++;
       +        }
       +      }
       +      buf_move(in, out);
       +    }
       +  }
       +  buf_free(out);
       +}
       +
       +int mail_encode(BUFFER *in, int encoding)
       +{
       +  BUFFER *out, *line, *tmp;
       +
       +  out = buf_new();
       +  line = buf_new();
       +  tmp = buf_new();
       +
       +  while (buf_getline(in, line) == 0) {
       +    hdr_encode(line, 255);
       +    buf_cat(out, line);
       +    buf_nl(out);
       +  }
       +  if (in->ptr < in->length) {
       +    /* no newline if only encoding header lines */
       +    if (encoding == 0) {
       +      buf_nl(out);
       +      buf_rest(out, in);
       +    }
       +    else {
       +      body_encode(in, encoding, line);
       +      buf_cat(out, line);
       +      buf_nl(out);
       +      buf_cat(out, in);
       +    }
       +  }
       +  buf_move(in, out);
       +  buf_free(line);
       +  buf_free(tmp);
       +  buf_free(out);
       +  return (0);
       +}
       +
       +int hdr_encode(BUFFER *in, int n)
       +{
       +  int i;
       +  int encodeword = 0, encode = 0;
       +  BUFFER *out, *word, *space;
       +
       +  out = buf_new();
       +  word = buf_new();
       +  space = buf_new();
       +  for (i = 0; i <= in->length; i++) {
       +    if (isspace(in->data[i]) || in->data[i] == '\0') {
       +      if (word->length) {
       +        if (encodeword) {
       +          if (encode == 0) {
       +            buf_cat(out, space);
       +            buf_clear(space);
       +            buf_appends(out, "=?");
       +            buf_appends(out, MIMECHARSET);
       +            buf_appends(out, "?Q?");
       +            encode = 1;
       +          } else {
       +            buf_cat(space, word);
       +            buf_move(word, space);
       +          }
       +          encode_word(word);
       +        }
       +        if (encode && !encodeword) {
       +          encode = 0;
       +          buf_appends(out, "?=");
       +        }
       +        buf_cat(out, space);
       +        buf_cat(out, word);
       +        encodeword = 0;
       +        buf_clear(space);
       +        buf_clear(word);
       +      }
       +      buf_appendc(space, in->data[i]);
       +    } else {
       +      if (in->data[i] < 32 || in->data[i] >= 127)
       +        encodeword = 1;
       +      buf_appendc(word, in->data[i]);
       +    }
       +  }
       +  if (encode)
       +    buf_appends(out, "?=");
       +
       +  buf_move(in, out);
       +  while (n > 0 && in->length - in->ptr > n) {
       +    for (i = 1; i < in->length - in->ptr; i++)
       +      if (isspace(in->data[in->length - i]))
       +        break;
       +    buf_get(in, out, in->length - i);
       +    buf_appends(out, "\n\t");
       +  }
       +  buf_rest(out, in);
       +  buf_move(in, out);
       +  buf_free(out);
       +  buf_free(space);
       +  buf_free(word);
       +  return (0);
       +}
       +
       +void addprintable(BUFFER *out, int c)
       +{
       +  if (c == '\n')
       +    buf_appendc(out, (char) c);
       +  else if (c == '\t')
       +    buf_appends(out, "        ");
       +  else if (c == '\014')
       +    buf_appends(out, "^L");
       +  else if (c == '\r') ;
       +  else if (c <= 31 || (c >= 128 && c <= 128 + 31))
       +    buf_appendc(out, '?');
       +  else
       +    buf_appendc(out, (char) c);
       +}
       +
       +void addprintablebuf(BUFFER *out, BUFFER *in)
       +{
       +  int c;
       +
       +  while ((c = buf_getc(in)) != -1)
       +    addprintable(out, c);
       +}
       +
       +int decode_line(BUFFER *line)
       +{
       +  BUFFER *out;
       +  unsigned int i;
       +  int c, softbreak = 0;
       +
       +  out = buf_new();
       +  for (i = 0; line->data[i] != '\0'; i++) {
       +    if (line->data[i] == '=') {
       +      if (isxdigit(line->data[i + 1]) && isxdigit(line->data[i + 2])) {
       +        c = hex(line->data[i + 1]) * 16 + hex(line->data[i + 2]);
       +        i += 2;
       +        addprintable(out, c);
       +      } else if (line->data[i + 1] == '\0') {
       +        softbreak = 1;
       +        break;
       +      }
       +    } else
       +      addprintable(out, line->data[i]);
       +  }
       +
       +  buf_move(line, out);
       +  buf_free(out);
       +  return (softbreak);
       +}
       +
       +int decode_header(BUFFER *in)
       +{
       +  int encoded = 0;
       +  int c;
       +  int err = 0;
       +  int last = 0;
       +  BUFFER *out;
       +
       +  out = buf_new();
       +  for (in->ptr = 0; in->data[in->ptr] != '\0'; in->ptr++) {
       +    if (encoded == 'q' && in->data[in->ptr] == '=' &&
       +        isxdigit(in->data[in->ptr + 1])
       +        && isxdigit(in->data[in->ptr + 2])) {
       +      c = hex(in->data[in->ptr + 1]) * 16 + hex(in->data[in->ptr + 2]);
       +      in->ptr += 2;
       +      addprintable(out, c);
       +    } else if (encoded == 'q' && in->data[in->ptr] == '_')
       +      buf_appendc(out, ' ');
       +    else if (in->data[in->ptr] == '=' && in->data[in->ptr + 1] == '?' &&
       +             in->data[in->ptr + 2] != '\0') {
       +      if (last > 0 && out->length > last) {
       +        out->data[last] = '\0';
       +        out->length = last;
       +      }
       +      in->ptr++;
       +      while (in->data[++in->ptr] != '?')
       +        if (in->data[in->ptr] == 0) {
       +          err = -1;
       +          goto end;
       +        }
       +      if (in->data[in->ptr + 1] != '\0' && in->data[in->ptr + 2] == '?') {
       +        encoded = tolower(in->data[in->ptr + 1]);
       +        in->ptr += 2;
       +        if (encoded == 'b') {
       +          BUFFER *tmp;
       +
       +          tmp = buf_new();
       +          decode(in, tmp);
       +          addprintablebuf(out, tmp);
       +          last = out->length;
       +          buf_free(tmp);
       +        } else if (encoded != 'q')
       +          err = 1;
       +      } else {
       +        err = -1;
       +        goto end;
       +      }
       +    } else if (encoded && in->data[in->ptr] == '?' &&
       +               in->data[in->ptr + 1] == '=') {
       +      in->ptr++;
       +      last = out->length;
       +      encoded = 0;
       +    } else {
       +      addprintable(out, in->data[in->ptr]);
       +      if (!encoded || !isspace(in->data[in->ptr]))
       +        last = out->length;
       +    }
       +  }
       +end:
       +  if (err == -1)
       +    buf_set(out, in);
       +
       +  buf_move(in, out);
       +  buf_free(out);
       +  return (err);
       +}
       +
       +#define delimclose 2
       +
       +int boundary(BUFFER *line, BUFFER *boundary)
       +{
       +  int c;
       +
       +  if (boundary->length == 0 || !bufleft(line, "--") ||
       +      !strleft(line->data + 2, boundary->data))
       +    return (0);
       +  line->ptr = boundary->length + 2;
       +  for (;;) {
       +    c = buf_getc(line);
       +    if (c == -1)
       +      return (1);
       +    if (c == '-' && buf_getc(line) == '-')
       +      return (delimclose);
       +    if (!isspace(c))
       +      return (0);
       +  }
       +}
       +
       +#define pgpenc 1
       +#define pgpsig 2
       +
       +/*
       + * decodes non-multipart quoted printable message
       + */
       +int qp_decode_message(BUFFER *msg)
       +{
       +  BUFFER *out, *line, *field, *content;
       +  out     = buf_new();
       +  line    = buf_new();
       +  field   = buf_new();
       +  content = buf_new();
       +
       +  buf_rewind(msg);
       +
       +  /* copy over headers without decoding */
       +  while (buf_getheader(msg, field, content) == 0) {
       +    if (bufieq(field, "content-transfer-encoding")
       +        && bufieq(content, "quoted-printable")) {
       +      continue;                 /* no longer quoted-printable */
       +    } else {
       +      buf_appendheader(out, field, content);
       +    }
       +  }
       +
       +  buf_nl(out);
       +
       +  /* copy over body, quoted-printable decoding as we go */
       +  while (buf_getline(msg, line) != -1) {
       +    int softbreak;
       +    softbreak = decode_line(line);
       +    buf_cat(out, line);
       +    if (!softbreak)
       +      buf_nl(out);
       +  }
       +  buf_move(msg, out);
       +  buf_free(out);
       +  buf_free(line);
       +  buf_free(field);
       +  buf_free(content);
       +  return 0;
       +}
       +
       +
       +int entity_decode(BUFFER *msg, int message, int mptype, BUFFER *data)
       +{
       +  BUFFER *out, *line, *field, *content, *type, *subtype, *disposition,
       +      *mboundary, *part, *sigdata;
       +  int ret = 0, ptype = 0, partno = 0;
       +  int p, encoded = 0;
       +
       +  out = buf_new();
       +  line = buf_new();
       +  field = buf_new();
       +  content = buf_new();
       +  type = buf_new();
       +  subtype = buf_new();
       +  disposition = buf_new();
       +  mboundary = buf_new();
       +  part = buf_new();
       +  sigdata = buf_new();
       +
       +  if (message && bufileft(msg, "From ")) {
       +    buf_getline(msg, out); /* envelope from */
       +    buf_nl(out);
       +  }
       +
       +  while (buf_getheader(msg, field, content) == 0) {
       +    if (bufieq(field, "content-transfer-encoding") &&
       +        bufieq(content, "quoted-printable"))
       +      encoded = 'q';
       +    if (bufieq(field, "content-type")) {
       +      get_type(content, type, subtype);
       +      if (bufieq(type, "multipart"))
       +        get_parameter(content, "boundary", mboundary);
       +      if (bufieq(type, "multipart") && bufieq(subtype, "encrypted")) {
       +        get_parameter(content, "protocol", line);
       +        if (bufieq(line, "application/pgp-encrypted"))
       +          ptype = pgpenc;
       +      }
       +      if (bufieq(type, "multipart") && bufieq(subtype, "signed")) {
       +        get_parameter(content, "protocol", line);
       +        if (bufieq(line, "application/pgp-signature"))
       +          ptype = pgpsig;
       +      }
       +    }
       +    if (bufieq(field, "content-disposition"))
       +      buf_set(disposition, content);
       +    if (message) {
       +      decode_header(content);
       +      buf_appendheader(out, field, content);
       +    }
       +  }
       +
       +  if (message)
       +    buf_nl(out);
       +
       +  if (bufifind(disposition, "attachment")) {
       +    buf_appendf(out, "[-- %b attachment", type);
       +    get_parameter(disposition, "filename", line);
       +    if (line->length)
       +       buf_appendf(out, " (%b)", line);
       +    buf_appends(out, " --]\n");
       +  }
       +
       +  if (mboundary->length) {
       +  /* multipart */
       +    while (buf_getline(msg, line) > -1 && !boundary(line, mboundary))
       +      ; /* ignore preamble */
       +    while (buf_getline(msg, line) != -1) {
       +      p = boundary(line, mboundary);
       +      if (p) {
       +        if (part->data[part->length - 1] == '\n')
       +          part->data[--(part->length)] = '\0';
       +        partno++;
       +        if (ptype == pgpsig && partno == 1)
       +          buf_set(sigdata, part);
       +        ret += entity_decode(part, 0, ptype, sigdata);
       +        buf_cat(out, part);
       +        buf_clear(part);
       +        if (p == delimclose)
       +          break;
       +        if (bufieq(subtype, "alternative") && ret > 0)
       +          break;
       +        if (bufieq(subtype, "mixed"))
       +          buf_appends(out,
       +                      "[-------------------------------------------------------------------------]\n");
       +      } else {
       +        buf_cat(part, line);
       +        buf_nl(part);
       +      }
       +    }
       +  } else if (mptype == pgpenc && bufieq(type, "application") &&
       +             bufieq(subtype, "pgp-encrypted")) {
       +    /* application/pgp-encrypted part of multipart/encrypted */
       +    ; /* skip */
       +  } else if (mptype == pgpenc && bufieq(type, "application") &&
       +             bufieq(subtype, "octet-stream")) {
       +    /* application/octet-stream part of multipart/encrypted */
       +    int ok = 0;
       +    buf_getline(msg, line);
       +    if (bufleft(line, info_beginpgp)) {
       +      if (buffind(line, "(SIGNED)")) {
       +          buf_getline(msg, line);
       +          buf_appends(out, "[-- OpenPGP message with signature --]\n");
       +          if (bufleft(line, info_pgpsig))
       +            buf_appendf(out, "[%s]\n",
       +                        line->data + sizeof(info_pgpsig) - 1);
       +          else
       +            buf_appends(out, "[Signature invalid]\n");
       +      } else
       +        buf_appends(out, "[-- OpenPGP message --]\n");
       +      while (buf_getline(msg, line) != -1) {
       +        if (bufleft(line, info_endpgp)) {
       +          ret += entity_decode(part, 0, 0, NULL);
       +          buf_cat(out, part);
       +          buf_appends(out, "[-- End OpenPGP message --]\n");
       +          ok = 1, ret++;
       +          break;
       +        }
       +        buf_cat(part, line);
       +        buf_nl(part);
       +      }
       +    }
       +    if (!ok) {
       +      buf_appends(out, "[-- Bad OpenPGP message --]\n");
       +      buf_cat(out, msg);
       +    }
       +  } else if (mptype == pgpsig && bufeq(type, "application") &&
       +             bufieq(subtype, "pgp-signature")) {
       +    buf_rest(part, msg);
       +#ifdef USE_PGP
       +    if (pgp_decrypt(part, NULL, data, PGPPUBRING, NULL) == PGP_SIGOK)
       +      buf_appendf(out, "[-- OpenPGP signature from:\n    %b --]\n", data);
       +    else
       +      buf_appends(out, "[-- Invalid OpenPGP signature --]\n");
       +#else /* USE_PGP */
       +    buf_appends(out, "[-- No OpenPGP support --]\n");
       +#endif /* !USE_PGP */
       +  } else if (type->length == 0 || bufieq(type, "text")) {
       +    while (buf_getline(msg, line) != -1) {
       +      int softbreak;
       +      softbreak = encoded ? decode_line(line) : 0;
       +      buf_cat(out, line);
       +      if (!softbreak)
       +        buf_nl(out);
       +    }
       +    ret++;
       +  } else {
       +    buf_appendf(out, "[-- %b/%b message part --]\n", type, subtype);
       +    buf_cat(out, msg);
       +  }
       +
       +  buf_move(msg, out);
       +  buf_free(line);
       +  buf_free(out);
       +  buf_free(field);
       +  buf_free(content);
       +  buf_free(type);
       +  buf_free(subtype);
       +  buf_free(disposition);
       +  buf_free(mboundary);
       +  buf_free(part);
       +  buf_free(sigdata);
       +  return (0);
       +}
       +
       +void mimedecode(BUFFER *msg)
       +{
       +  entity_decode(msg, 1, 0, NULL);
       +}
       +
       +int attachfile(BUFFER *message, BUFFER *filename)
       +{
       +  BUFFER *type, *attachment;
       +  FILE *f;
       +  int ret = -1;
       +
       +  type = buf_new();
       +  attachment = buf_new();
       +
       +  if ((bufiright(filename, ".txt") || !bufifind(filename, ".")) &&(strlen(DEFLTENTITY) != 0))
       +    buf_sets(type, DEFLTENTITY);
       +  else if (bufiright(filename, ".htm") || bufiright(filename, ".html"))
       +    buf_sets(type, "text/html");
       +  else if (bufiright(filename, ".jpeg"))
       +    buf_sets(type, "image/jpeg");
       +  else if (bufiright(filename, ".gif"))
       +    buf_sets(type, "image/gif");
       +  else if (bufiright(filename, ".pcm"))
       +    buf_sets(type, "audio/basic");
       +  else if (bufiright(filename, ".mpg") || bufiright(filename, ".mpeg"))
       +    buf_sets(type, "video/mpeg");
       +  else if (bufiright(filename, ".ps"))
       +    buf_sets(type, "application/postscript");
       +  else
       +    buf_sets(type, "application/octet-stream");
       +
       +  f = fopen(filename->data, "r");
       +  if (f) {
       +    buf_read(attachment, f);
       +    fclose(f);
       +    ret = mime_attach(message, attachment, type);
       +  }
       +
       +  buf_free(attachment);
       +  buf_free(type);
       +  return(ret);
       +}
       +
       +int mime_attach(BUFFER *message, BUFFER *attachment, BUFFER *attachtype)
       +{
       +  BUFFER *out, *part, *line, *type, *subtype, *mboundary, *field, *content;
       +  int mimeheader = 0, multipart = 0, versionheader = 0;
       +
       +  out = buf_new();
       +  line = buf_new();
       +  part = buf_new();
       +  type = buf_new();
       +  subtype = buf_new();
       +  mboundary = buf_new();
       +  field = buf_new();
       +  content = buf_new();
       +
       +  buf_rewind(message);
       +  while (buf_getheader(message, field, content) == 0) {
       +    if (bufieq(field, "mime-version"))
       +      versionheader = 1;
       +    if (bufieq(field, "content-type")) {
       +      get_type(content, type, subtype);
       +      if (bufieq(type, "multipart") && bufieq(subtype, "mixed")) {
       +        multipart = 1;
       +        get_parameter(content, "boundary", mboundary);
       +      }
       +    }
       +    if (bufileft(field, "content-"))
       +      mimeheader = 1;
       +  }
       +
       +  if (mimeheader && !multipart) {
       +    buf_rewind(message);
       +    while (buf_getheader(message, field, content) == 0) {
       +      if (bufileft(field, "content-"))
       +        buf_appendheader(part, field, content);
       +      else
       +        buf_appendheader(out, field, content);
       +    }
       +  } else {
       +    buf_ungetc(message);
       +    buf_append(out, message->data, message->ptr);
       +    buf_getc(message);
       +  }
       +
       +  if (!versionheader)
       +    buf_appends(out, "MIME-Version: 1.0\n");
       +
       +  if (!multipart) {
       +    buf_setrnd(mboundary, 18);
       +    encode(mboundary, 0);
       +    buf_appendf(out, "Content-Type: multipart/mixed; boundary=\"%b\"\n",
       +                mboundary);
       +  }
       +  buf_nl(out);
       +
       +  if (multipart) {
       +    while (buf_getline(message, line) != -1) {
       +      if (boundary(line, mboundary) == delimclose)
       +        break;
       +      buf_cat(out, line);
       +      buf_nl(out);
       +    }
       +  } else {
       +    buf_appendf(out, "--%b\n", mboundary);
       +    if (part->length) {
       +      buf_cat(out, part); /* body part header */
       +    }
       +    else {
       +      if (strlen(DEFLTENTITY))
       +        buf_appendf(out, "Content-Type: %s\n", DEFLTENTITY);
       +    }
       +
       +    buf_nl(out);
       +    buf_cat(out, message);
       +    buf_nl(out);
       +  }
       +
       +  buf_appendf(out, "--%b\n", mboundary);
       +  buf_appendf(out, "Content-Type: %b\n", attachtype);
       +
       +  body_encode(attachment, MIME_8BIT, line);
       +  buf_cat(out, line);
       +  buf_nl(out);
       +  buf_cat(out, attachment);
       +  buf_appendf(out, "\n--%b--\n", mboundary);
       +
       +  buf_move(message, out);
       +
       +  buf_free(out);
       +  buf_free(line);
       +  buf_free(part);
       +  buf_free(type);
       +  buf_free(subtype);
       +  buf_free(mboundary);
       +  buf_free(field);
       +  buf_free(content);
       +  return (1);
       +}
       +
       +static int entity_encode(BUFFER *message, BUFFER *out, BUFFER *messagehdr,
       +                         int encoding)
       +{
       +  BUFFER *field, *content, *mboundary, *part, *line, *line2, *tmp;
       +
       +  field = buf_new();
       +  content = buf_new();
       +  mboundary = buf_new();
       +  part = buf_new();
       +  line = buf_new();
       +  line2 = buf_new();
       +  tmp = buf_new();
       +
       +  buf_rewind(message);
       +  buf_clear(out);
       +  buf_clear(messagehdr);
       +
       +  while (buf_getheader(message, field, content) == 0) {
       +    if (bufileft(field, "content-"))
       +      buf_appendheader(out, field, content);
       +    else if (messagehdr)
       +      buf_appendheader(messagehdr, field, content);
       +
       +    if (bufieq(field, "content-type")) {
       +      get_type(content, line, tmp);
       +      if (bufieq(line, "multipart"))
       +        get_parameter(content, "boundary", mboundary);
       +    }
       +  }
       +
       +  buf_nl(out);
       +  if (mboundary->length) {
       +      while (buf_getline(message, line) != -1) {
       +        buf_cat(out, line);
       +        buf_nl(out);
       +        if (boundary(line, mboundary))
       +          break;
       +      }
       +      while (buf_getline(message, line) != -1) {
       +          if (boundary(line, mboundary)) {
       +            entity_encode(part, tmp, line2, encoding);
       +            buf_cat(out, line2);
       +            buf_cat(out, tmp);
       +            buf_cat(out, line);
       +            buf_nl(out);
       +            buf_clear(part);
       +            if (boundary(line, mboundary) == delimclose)
       +              break;
       +          } else {
       +            buf_cat(part, line);
       +            buf_nl(part);
       +          }
       +      }
       +  } else
       +    buf_rest(out, message);
       +  buf_rewind(out);
       +  mail_encode(out, encoding);
       +
       +  buf_free(field);
       +  buf_free(content);
       +  buf_free(mboundary);
       +  buf_free(part);
       +  buf_free(line);
       +  buf_free(line2);
       +  buf_free(tmp);
       +  return (1);
       +}
       +
       +int pgpmime_sign(BUFFER *message, BUFFER *uid, BUFFER *pass, char *secring)
       +{
       +#ifndef USE_PGP
       +  return (-1)
       +#else /* end of not USE_PGP */
       +  BUFFER *out, *body, *mboundary, *algo;
       +  int err;
       +
       +  out = buf_new();
       +  body = buf_new();
       +  mboundary = buf_new();
       +  algo = buf_new();
       +
       +  pgp_signhashalgo(algo, uid, secring, pass);
       +
       +  entity_encode(message, body, out, MIME_7BIT);
       +
       +  buf_setrnd(mboundary, 18);
       +  encode(mboundary, 0);
       +  buf_appendf(out, "Content-Type: multipart/signed; boundary=\"%b\";\n",
       +              mboundary);
       +  buf_appendf(out,
       +              "\tmicalg=pgp-%b; protocol=\"application/pgp-signature\"\n",
       +              algo);
       +  buf_nl(out);
       +
       +  buf_appendf(out, "--%b\n", mboundary);
       +  buf_cat(out, body);
       +  buf_nl(out);
       +  buf_appendf(out, "--%b\n", mboundary);
       +
       +  err = pgp_encrypt(PGP_SIGN | PGP_TEXT | PGP_DETACHEDSIG, body, NULL,
       +                    uid, pass, NULL, secring);
       +
       +  buf_appends(out, "Content-Type: application/pgp-signature\n");
       +  buf_nl(out);
       +  buf_cat(out, body);
       +  buf_nl(out);
       +  buf_appendf(out, "--%b--\n", mboundary);
       +  if (err == 0)
       +    buf_move(message, out);
       +
       +  buf_free(out);
       +  buf_free(body);
       +  buf_free(mboundary);
       +  buf_free(algo);
       +  return (err);
       +#endif /* else if USE_PGP */
       +}
   DIR diff --git a/Src/mix.c b/Src/mix.c
       t@@ -0,0 +1,1262 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Mixmaster initialization, configuration
       +   $Id: mix.c 962 2007-11-19 13:42:41Z zax $ */
       +
       +
       +#include "mix3.h"
       +#include <stdlib.h>
       +#include <stdio.h>
       +#include <string.h>
       +#include <stdarg.h>
       +#include <ctype.h>
       +#include <time.h>
       +#include <sys/types.h>
       +#include <sys/stat.h>
       +#ifdef POSIX
       +#include <signal.h>
       +#include <unistd.h>
       +#include <pwd.h>
       +#include <sys/utsname.h>
       +#else /* end of POSIX */
       +#include <io.h>
       +#include <direct.h>
       +#endif /* else if not POSIX */
       +#ifdef WIN32
       +#include <windows.h>
       +#include <shlobj.h>
       +#include <shlobj.h>
       +#endif /* WIN32 */
       +#include <assert.h>
       +#include "menu.h"
       +
       +int buf_vappendf(BUFFER *b, char *fmt, va_list args);
       +
       +/** filenames ************************************************************/
       +char MIXCONF[PATHMAX] = DEFAULT_MIXCONF;
       +char DISCLAIMFILE[PATHMAX];
       +char FROMDSCLFILE[PATHMAX];
       +char MSGFOOTERFILE[PATHMAX];
       +char POP3CONF[PATHMAX];
       +char HELPFILE[PATHMAX];
       +char REQUESTDIR[PATHMAX];
       +char ABUSEFILE[PATHMAX];
       +char REPLYFILE[PATHMAX];
       +char USAGEFILE[PATHMAX];
       +char USAGELOG[PATHMAX];
       +char BLOCKFILE[PATHMAX];
       +char ADMKEYFILE[PATHMAX];
       +char KEYFILE[PATHMAX];
       +char PGPKEY[PATHMAX];
       +char DSAPARAMS[PATHMAX];
       +char DHPARAMS[PATHMAX];
       +char MIXRAND[PATHMAX];
       +char SECRING[PATHMAX];
       +char PUBRING[PATHMAX];
       +char IDLOG[PATHMAX];
       +char STATS[PATHMAX];
       +char PGPMAXCOUNT[PATHMAX];
       +char DESTBLOCK[PATHMAX];
       +char DESTALLOW[PATHMAX];
       +char DESTALLOW2[PATHMAX];
       +char SOURCEBLOCK[PATHMAX];
       +char HDRFILTER[PATHMAX];
       +char REGULAR[PATHMAX];
       +char POOL[PATHMAX];
       +char TYPE1LIST[PATHMAX];
       +char TYPE2REL[PATHMAX];
       +char PIDFILE[PATHMAX];
       +
       +char PGPREMPUBRING[PATHMAX];
       +char PGPREMPUBASC[PATHMAX];
       +char PGPREMSECRING[PATHMAX];
       +char NYMSECRING[PATHMAX];
       +char NYMDB[PATHMAX];
       +char STAREX[PATHMAX];
       +
       +/** config ***************************************************************/
       +
       +char MIXDIR[PATHMAX];
       +char POOLDIR[PATHMAX];
       +
       +/* programs */
       +char SENDMAIL[LINELEN];
       +char SENDANONMAIL[LINELEN];
       +char NEWS[LINELEN];
       +char TYPE1[LINELEN];
       +
       +/* addresses */
       +char MAILtoNEWS[LINELEN];
       +char REMAILERNAME[LINELEN];
       +char ANONNAME[LINELEN];
       +char REMAILERADDR[LINELEN];
       +char ANONADDR[LINELEN];
       +char COMPLAINTS[LINELEN];
       +int AUTOREPLY;
       +char SMTPRELAY[LINELEN];
       +char SMTPUSERNAME[LINELEN];
       +char SMTPPASSWORD[LINELEN];
       +
       +#ifdef USE_SOCK
       +char HELONAME[LINELEN];
       +char ENVFROM[LINELEN];
       +int POP3DEL;
       +int POP3SIZELIMIT;
       +long POP3TIME;
       +
       +#endif /* USE_SOCK */
       +
       +char SHORTNAME[LINELEN];
       +char ALLPINGERSURL[BUFSIZE];
       +char ALLPINGERSFILE[PATHMAX];
       +char WGET[PATHMAX];
       +char STATSSRC[PATHMAX];
       +int  STATSAUTOUPDATE;
       +long STATSINTERVAL;
       +
       +
       +/* remailer configuration */
       +int REMAIL;
       +int MIX;
       +int PGP;
       +int UNENCRYPTED;
       +int REMIX;
       +int REPGP;
       +char EXTFLAGS[LINELEN];        /* user-defined capstring flags */
       +
       +char PRECEDENCE[LINELEN];        /* default Precedence: header for outgoing mail */
       +int POOLSIZE;
       +int RATE;
       +int INDUMMYP;
       +int OUTDUMMYP;
       +int INDUMMYMAXP;
       +int OUTDUMMYMAXP;
       +int MIDDLEMAN;
       +int AUTOBLOCK;
       +int STATSDETAILS;
       +char FORWARDTO[LINELEN];
       +int SIZELIMIT;                /* maximal size of remailed messages */
       +int INFLATEMAX;                /* maximal size of Inflate: padding */
       +int MAXRANDHOPS;
       +int BINFILTER;                /* filter binary attachments? */
       +int LISTSUPPORTED;        /* list supported remailers in remailer-conf reply? */
       +long PACKETEXP;                /* Expiration time for old packets */
       +long IDEXP;                /* 0 = no ID log !! */
       +long SENDPOOLTIME;        /* frequency for sending pool messages */
       +long MAILINTIME;        /* frequency for processing MAILIN mail */
       +
       +long KEYLIFETIME;
       +long KEYOVERLAPPERIOD;
       +long KEYGRACEPERIOD;
       +
       +char ERRLOG[LINELEN];
       +char ADDRESS[LINELEN];
       +char NAME[LINELEN];
       +
       +char ORGANIZATION[LINELEN];
       +char MID[LINELEN];
       +
       +/* client config */
       +int NUMCOPIES;
       +char CHAIN[LINELEN];
       +int VERBOSE;
       +int DISTANCE;
       +int MINREL;
       +int RELFINAL;
       +long MAXLAT;
       +long MINLAT;
       +char PGPPUBRING[PATHMAX];
       +char PGPSECRING[PATHMAX];
       +char PASSPHRASE[LINELEN];
       +char MAILIN[PATHMAX];
       +char MAILBOX[PATHMAX];
       +char MAILABUSE[PATHMAX];
       +char MAILBLOCK[PATHMAX];
       +char MAILUSAGE[PATHMAX];
       +char MAILANON[PATHMAX];
       +char MAILERROR[PATHMAX];
       +char MAILBOUNCE[PATHMAX];
       +
       +int CLIENTAUTOFLUSH;
       +int MAXRECIPIENTS;
       +
       +long TIMESKEW_FORWARD;
       +long TIMESKEW_BACK;
       +int TEMP_FAIL;
       +
       +char ENTEREDPASSPHRASE[LINELEN] = "";
       +
       +static int rereadconfig = 0;
       +static int terminatedaemon = 0;
       +
       +#if defined(S_IFDIR) && !defined(S_ISDIR)
       +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
       +#endif /* defined(S_IFDIR) && !defined(S_ISDIR) */
       +
       +static int mixdir(char *d, int create)
       +{
       +  int err;
       +  struct stat buf;
       +
       +  if (d != MIXDIR)
       +    strncpy(MIXDIR, d, PATHMAX);
       +  if (MIXDIR[strlen(MIXDIR) - 1] == DIRSEP)
       +    MIXDIR[strlen(MIXDIR) - 1] = '\0';
       +  err = stat(MIXDIR, &buf);
       +  if (err == -1) {
       +    if (create) {
       +#ifndef POSIX
       +      err = mkdir(MIXDIR);
       +#else /* end of not POSIX */
       +      err = mkdir(MIXDIR, S_IRWXU);
       +#endif /* else if POSIX */
       +      if (err == 0)
       +        errlog(NOTICE, "Creating directory %s.\n", MIXDIR);
       +    } else
       +      err = 1;
       +  } else if (!S_ISDIR(buf.st_mode))
       +    err = -1;
       +  if (err == 0)
       +    strcatn(MIXDIR, DIRSEPSTR, PATHMAX);
       +  return (err);
       +}
       +
       +void whoami(char *addr, char *defaultname)
       +{
       +  char *p = NULL;
       +
       +#if defined(HAVE_GETDOMAINNAME) || (defined(HAVE_GETHOSTNAME) && ! defined(HAVE_UNAME))
       +  char line[LINELEN];
       +
       +#endif /* defined(HAVE_GETDOMAINNAME) || [...] */
       +#ifdef HAVE_UNAME
       +  struct utsname uts;
       +
       +#endif /* HAVE_UNAME */
       +#ifdef POSIX
       +  p = getlogin();
       +#endif /* POSIX */
       +  if (p == NULL)
       +    strcpy(addr, defaultname);
       +  else
       +    strncpy(addr, p, LINELEN);
       +
       +  strcatn(addr, "@", LINELEN);
       +#ifdef HAVE_UNAME
       +  if (uname(&uts) != -1)
       +    strcatn(addr, uts.nodename, LINELEN);
       +#elif defined(HAVE_GETHOSTNAME) /* end of HAVE_UNAME */
       +  if (gethostname(line, LINELEN) == 0)
       +    strcatn(addr, line, LINELEN);
       +#endif /* defined(HAVE_GETHOSTNAME) */
       +  if (addr[strlen(addr) - 1] == '@')
       +    strcatn(addr, SHORTNAME, LINELEN);
       +
       +  if (strchr(strchr(addr, '@'), '.') == NULL) {
       +#ifdef HAVE_GETDOMAINNAME
       +    if (getdomainname(line, LINELEN) == 0 && !streq(line, "(none)")) {
       +      strcatn(addr, ".", LINELEN);
       +      strcatn(addr, line, LINELEN);
       +    }
       +#endif /* HAVE_GETDOMAINNAME */
       +  }
       +}
       +
       +#define read_conf(t) readconfline(line, #t, sizeof(#t)-1, t)
       +
       +static int readconfline(char *line, char *name, int namelen, char *var)
       +{
       +  if (strncmp(line, name, namelen) == 0 &&
       +      (isspace(line[namelen]) || line[namelen] == '=')) {
       +    line += namelen;
       +    if (*line == '=')
       +      line++;
       +    while (isspace(*line))
       +      line++;
       +    if (line[0] == '\n' || line[0] == '\0')        /* leave default */
       +      return (1);
       +    strncpy(var, line, LINELEN);
       +    if (var[strlen(var) - 1] == '\n')
       +      var[strlen(var) - 1] = '\0';
       +    return (1);
       +  } else
       +    return (0);
       +}
       +
       +#define read_conf_i(t) readiconfline(line, #t, sizeof(#t)-1, &t)
       +
       +static int readiconfline(char *line, char *name, int namelen, int *var)
       +{
       +  if (strncmp(line, name, namelen) == 0 &&
       +      (isspace(line[namelen]) || line[namelen] == '=')) {
       +    line += namelen;
       +    if (*line == '=')
       +      line++;
       +    while (isspace(*line))
       +      line++;
       +    if (line[0] == '\n' || line[0] == '\0')        /* leave default */
       +      return (1);
       +    switch (tolower(line[0])) {
       +    case 'n':
       +      *var = 0;
       +      break;
       +    case 'y':
       +      *var = 1;
       +      break;
       +    case 'x':
       +      *var = 2;
       +      break;
       +    default:
       +      sscanf(line, "%d", var);
       +    }
       +    return (1);
       +  } else
       +    return (0);
       +}
       +
       +#define read_conf_t(t) readtconfline(line, #t, sizeof(#t)-1, &t)
       +
       +static int readtconfline(char *line, char *name, int namelen, long *var)
       +{
       +  char *linenext;
       +  int mod = 0;
       +  long l = 0;
       +  long n;
       +
       +  if (strncmp(line, name, namelen) == 0 &&
       +      (isspace(line[namelen]) || line[namelen] == '=')) {
       +    line += namelen;
       +    if (*line == '=')
       +      line++;
       +    for (;; line++) {
       +      n = strtol(line, &linenext, 10);
       +      if (linenext == line)
       +        break;
       +      line = linenext;
       +      mod = 1;
       +      assert(line != NULL);
       +      while (isspace(*line))
       +        line++;
       +      switch (tolower(*line)) {
       +      case 'y': /* years */
       +        l += 365 * 24 * 60 * 60 * n;
       +        break;
       +      case 'b': /* months */
       +        l += 30 * 24 * 60 * 60 * n;
       +        break;
       +      case 'w': /* weeks */
       +        l += 7 * 24 * 60 * 60 * n;
       +        break;
       +      case 'd': /* days */
       +        l += 24 * 60 * 60 * n;
       +        break;
       +      case 's': /* seconds */
       +        l += n;
       +        break;
       +      case 'm': /* minutes */
       +        l += 60 * n;
       +        break;
       +      case 'h': /* hours - default */
       +      default:
       +        l += 60 * 60 * n;
       +        break;
       +      }
       +    }
       +    if (mod)
       +      *var = l;
       +    return (1);
       +  } else
       +    return (0);
       +}
       +
       +static void mix_setdefaults()
       +{
       +#define strnncpy(a,b) strncpy(a, b, sizeof(a)); a[sizeof(a)-1] = '\0'
       +
       +        strnncpy(DISCLAIMFILE , DEFAULT_DISCLAIMFILE);
       +        strnncpy(FROMDSCLFILE , DEFAULT_FROMDSCLFILE);
       +        strnncpy(MSGFOOTERFILE, DEFAULT_MSGFOOTERFILE);
       +        strnncpy(POP3CONF     , DEFAULT_POP3CONF);
       +        strnncpy(HELPFILE     , DEFAULT_HELPFILE);
       +        strnncpy(REQUESTDIR   , DEFAULT_REQUESTDIR);
       +        strnncpy(ABUSEFILE    , DEFAULT_ABUSEFILE);
       +        strnncpy(REPLYFILE    , DEFAULT_REPLYFILE);
       +        strnncpy(USAGEFILE    , DEFAULT_USAGEFILE);
       +        strnncpy(USAGELOG     , DEFAULT_USAGELOG);
       +        strnncpy(BLOCKFILE    , DEFAULT_BLOCKFILE);
       +        strnncpy(ADMKEYFILE   , DEFAULT_ADMKEYFILE);
       +        strnncpy(KEYFILE      , DEFAULT_KEYFILE);
       +        strnncpy(PGPKEY       , DEFAULT_PGPKEY);
       +        strnncpy(DSAPARAMS    , DEFAULT_DSAPARAMS);
       +        strnncpy(DHPARAMS     , DEFAULT_DHPARAMS);
       +        strnncpy(MIXRAND      , DEFAULT_MIXRAND);
       +        strnncpy(SECRING      , DEFAULT_SECRING);
       +        strnncpy(PUBRING      , DEFAULT_PUBRING);
       +        strnncpy(IDLOG        , DEFAULT_IDLOG);
       +        strnncpy(STATS        , DEFAULT_STATS);
       +        strnncpy(PGPMAXCOUNT  , DEFAULT_PGPMAXCOUNT);
       +        strnncpy(DESTBLOCK    , DEFAULT_DESTBLOCK);
       +        strnncpy(DESTALLOW    , DEFAULT_DESTALLOW);
       +        strnncpy(DESTALLOW2   , DEFAULT_DESTALLOW2);
       +        strnncpy(SOURCEBLOCK  , DEFAULT_SOURCEBLOCK);
       +        strnncpy(HDRFILTER    , DEFAULT_HDRFILTER);
       +        strnncpy(REGULAR      , DEFAULT_REGULAR);
       +        strnncpy(POOL         , DEFAULT_POOL);
       +        strnncpy(TYPE1LIST    , DEFAULT_TYPE1LIST);
       +        strnncpy(TYPE2REL     , DEFAULT_TYPE2REL);
       +        strnncpy(PIDFILE      , DEFAULT_PIDFILE);
       +
       +        strnncpy(PGPREMPUBRING, DEFAULT_PGPREMPUBRING);
       +        strnncpy(PGPREMPUBASC , DEFAULT_PGPREMPUBASC);
       +        strnncpy(PGPREMSECRING, DEFAULT_PGPREMSECRING);
       +        strnncpy(NYMSECRING   , DEFAULT_NYMSECRING);
       +        strnncpy(NYMDB        , DEFAULT_NYMDB);
       +        strnncpy(STAREX       , DEFAULT_STAREX);
       +        strnncpy(ALLPINGERSURL, DEFAULT_ALLPINGERSURL);
       +        strnncpy(ALLPINGERSFILE, DEFAULT_ALLPINGERSFILE);
       +        strnncpy(WGET         , DEFAULT_WGET);
       +        strnncpy(STATSSRC     , DEFAULT_STATSSRC);
       +
       +        strnncpy(MIXDIR       , "");
       +        strnncpy(POOLDIR      , "");
       +
       +/* programs */
       +#ifdef WIN32
       +        strnncpy(SENDMAIL     , "outfile");
       +#else /* end of WIN32 */
       +        strnncpy(SENDMAIL     , "/usr/lib/sendmail -t");
       +#endif /* else if not WIN32 */
       +        strnncpy(SENDANONMAIL , "");
       +        strnncpy(NEWS         , "");
       +        strnncpy(TYPE1        , "");
       +
       +/* addresses */
       +        strnncpy(MAILtoNEWS   , "mail2news@dizum.com,mail2news@m2n.mixmin.net");
       +        strnncpy(REMAILERNAME , "Anonymous Remailer");
       +        strnncpy(ANONNAME     , "Anonymous");
       +        strnncpy(REMAILERADDR , "");
       +        strnncpy(ANONADDR     , "");
       +        strnncpy(COMPLAINTS   , "");
       +        strnncpy(SMTPRELAY    , "");
       +        AUTOREPLY             = 0;
       +
       +#ifdef USE_SOCK
       +          strnncpy(HELONAME     , "");
       +        strnncpy(ENVFROM      , "");
       +        POP3DEL               = 0;
       +        POP3SIZELIMIT         = 0;
       +        POP3TIME              = 60 * 60;
       +
       +#endif /* USE_SOCK */
       +
       +        strnncpy(SHORTNAME    , "");
       +
       +/*         configuration */
       +        REMAIL        = 0;
       +        MIX           = 1;
       +        PGP           = 1;
       +        UNENCRYPTED   = 0;
       +        REMIX         = 1;
       +        REPGP         = 1;
       +        STATSAUTOUPDATE = 0;
       +        STATSINTERVAL = 8 * 60 * 60;
       +        strnncpy(EXTFLAGS, "");
       +
       +    strnncpy(PRECEDENCE, "");
       +        POOLSIZE      = 0;
       +        RATE          = 100;
       +        INDUMMYP      = 3;        /* add dummy messages with probability p for each message added to the pool */
       +        OUTDUMMYP     = 10;        /* add dummy messages with probability p each time we send from the pool */
       +        INDUMMYMAXP   = 84;        /* for both of the above:  while (rnd < p) { senddummy(); }  */
       +        OUTDUMMYMAXP  = 96;     /* set max INDUMMYP and OUTDUMMYP such that 24 and 5.25 dummy messages will */
       +        MIDDLEMAN     = 0;      /* be generated on average. More than this is insane. */
       +        AUTOBLOCK     = 1;
       +        STATSDETAILS  = 1;
       +        strnncpy(FORWARDTO, "*");
       +        SIZELIMIT     = 0;                /* maximal size of remailed messages */
       +        INFLATEMAX    = 50;                /* maximal size of Inflate: padding */
       +        MAXRANDHOPS   = 5;
       +        BINFILTER     = 0;                /* filter binary attachments? */
       +        LISTSUPPORTED = 1;                /* list supported remailers in remailer-conf reply? */
       +        PACKETEXP     = 7 * SECONDSPERDAY;        /* Expiration time for old packets */
       +        IDEXP         = 7 * SECONDSPERDAY;        /* 0 = no ID log !! */
       +        SENDPOOLTIME  = 0;              /* frequency for sending pool messages */
       +        MAILINTIME    = 5 * 60;                /* frequency for processing MAILIN mail */
       +
       +        KEYLIFETIME      = 13 * 30 * 24 * 60 * 60;        /* validity period for keys. */
       +        KEYOVERLAPPERIOD =  1 * 30 * 24 * 60 * 60;        /* when keys have this amount of time */
       +                                                        /* left before expiration, create  */
       +                                                        /* new ones when ./mix -K is run.*/
       +        KEYGRACEPERIOD   =       7 * 24 * 60 * 60;        /* accept mail to the old key for this */
       +                                                        /* amount of time after it has expired. */
       +
       +
       +        strnncpy(ERRLOG      , "");
       +        strnncpy(ADDRESS     , "");
       +        strnncpy(NAME        , "");
       +
       +        strnncpy(ORGANIZATION, "Anonymous Posting Service");
       +        strnncpy(MID         , "y");
       +
       +/* client config */
       +        NUMCOPIES = 1;
       +        strnncpy(CHAIN, "*,*,*,*");
       +        VERBOSE = 2;
       +        DISTANCE = 2;
       +        MINREL = 98;
       +        RELFINAL = 99;
       +        MAXLAT = 36 * 60 * 60;
       +        MINLAT = 5 * 60;
       +        strnncpy(PGPPUBRING, "");
       +        strnncpy(PGPSECRING, "");
       +#ifdef COMPILEDPASS
       +        strnncpy(PASSPHRASE, COMPILEDPASS);
       +#else /* end of COMPILEDPASS */
       +        strnncpy(PASSPHRASE, "");
       +#endif /* else if not COMPILEDPASS */
       +        strnncpy(MAILIN    , "");
       +        strnncpy(MAILBOX   , "mbox");
       +        strnncpy(MAILABUSE , "");
       +        strnncpy(MAILBLOCK , "");
       +#ifdef WIN32
       +        strnncpy(MAILUSAGE , "nul:");
       +        strnncpy(MAILANON  , "nul:");
       +        strnncpy(MAILERROR , "nul:");
       +#else /* end of WIN32 */
       +        strnncpy(MAILUSAGE , "/dev/null");
       +        strnncpy(MAILANON  , "/dev/null");
       +        strnncpy(MAILERROR , "/dev/null");
       +#endif /* else if not WIN32 */
       +        strnncpy(MAILBOUNCE, "");
       +
       +        CLIENTAUTOFLUSH = 1;
       +        MAXRECIPIENTS   = 5;
       +
       +        TIMESKEW_FORWARD = 2*7*24*60*60;
       +        TIMESKEW_BACK = 12*60*60;
       +        TEMP_FAIL = 75;
       +}
       +
       +int mix_configline(char *line)
       +{
       +  return (read_conf(ADDRESS) || read_conf(NAME) ||
       +          read_conf(SHORTNAME) || read_conf(REMAILERADDR) ||
       +          read_conf(ANONADDR) || read_conf(REMAILERNAME) ||
       +          read_conf(ANONNAME) || read_conf(COMPLAINTS) ||
       +          read_conf_i(AUTOREPLY) || read_conf(SMTPRELAY) ||
       +          read_conf(SMTPUSERNAME) || read_conf(SMTPPASSWORD) ||
       +#ifdef USE_SOCK
       +          read_conf(HELONAME) || read_conf(ENVFROM) ||
       +#endif /* USE_SOCK */
       +          read_conf(SENDMAIL) || read_conf(SENDANONMAIL) ||
       +          read_conf(PRECEDENCE) ||
       +          read_conf_i(REMAIL) || read_conf_i(MIX) ||
       +          read_conf_i(PGP) || read_conf_i(UNENCRYPTED) ||
       +          read_conf_i(REMIX) || read_conf(NEWS) ||
       +          read_conf_i(REPGP) || read_conf(EXTFLAGS) ||
       +          read_conf(MAILtoNEWS) || read_conf(ERRLOG) ||
       +          read_conf(ORGANIZATION) || read_conf(MID) ||
       +          read_conf(TYPE1) || read_conf_i(POOLSIZE) ||
       +          read_conf_i(RATE) || read_conf_i(MIDDLEMAN) ||
       +          read_conf_i(INDUMMYP) ||
       +          read_conf_i(OUTDUMMYP) ||
       +          read_conf_i(AUTOBLOCK) || read_conf(FORWARDTO) ||
       +          read_conf_i(STATSDETAILS) ||
       +          read_conf_i(SIZELIMIT) || read_conf_i(INFLATEMAX) ||
       +          read_conf_i(MAXRANDHOPS) || read_conf_i(BINFILTER) ||
       +          read_conf_i(LISTSUPPORTED) ||
       +          read_conf_t(PACKETEXP) || read_conf_t(IDEXP) ||
       +          read_conf_t(SENDPOOLTIME) || read_conf_i(NUMCOPIES) ||
       +          read_conf_t(MAILINTIME) ||
       +          read_conf(CHAIN) || read_conf_i(VERBOSE) ||
       +          read_conf_i(DISTANCE) || read_conf_i(MINREL) ||
       +          read_conf_i(RELFINAL) || read_conf_t(MAXLAT) ||
       +          read_conf_t(MINLAT) ||
       +          read_conf(PGPPUBRING) || read_conf(PGPSECRING) ||
       +          read_conf(PASSPHRASE) || read_conf_t(KEYLIFETIME) ||
       +          read_conf_t(KEYGRACEPERIOD) || read_conf_t(KEYOVERLAPPERIOD) ||
       +#ifdef USE_SOCK
       +          read_conf_i(POP3DEL) || read_conf_i(POP3SIZELIMIT) ||
       +          read_conf_t(POP3TIME) ||
       +#endif /* USE_SOCK */
       +          read_conf(MAILBOX) || read_conf(MAILABUSE) ||
       +          read_conf(MAILBLOCK) || read_conf(MAILUSAGE) ||
       +          read_conf(MAILANON) || read_conf(MAILERROR) ||
       +          read_conf(MAILBOUNCE) || read_conf(MAILIN) ||
       +
       +          read_conf(DISCLAIMFILE) || read_conf(FROMDSCLFILE) ||
       +          read_conf(MSGFOOTERFILE) ||
       +          read_conf(POP3CONF) || read_conf(HELPFILE) ||
       +          read_conf(REQUESTDIR)  ||
       +          read_conf(ABUSEFILE) || read_conf(REPLYFILE) ||
       +          read_conf(USAGEFILE) || read_conf(USAGELOG) ||
       +          read_conf(BLOCKFILE) || read_conf(ADMKEYFILE) ||
       +          read_conf(KEYFILE) || read_conf(PGPKEY) ||
       +          read_conf(DSAPARAMS) || read_conf(DHPARAMS) ||
       +          read_conf(MIXRAND) || read_conf(SECRING) ||
       +          read_conf(PUBRING) || read_conf(IDLOG) ||
       +          read_conf(STATS) || read_conf(DESTBLOCK) ||
       +          read_conf(PGPMAXCOUNT) ||
       +          read_conf(DESTALLOW) || read_conf(DESTALLOW2) ||
       +          read_conf(SOURCEBLOCK) ||
       +          read_conf(STAREX) || read_conf(ALLPINGERSURL) ||
       +          read_conf(ALLPINGERSFILE) ||
       +          read_conf(HDRFILTER) || read_conf(REGULAR) ||
       +          read_conf(POOL) || read_conf(TYPE1LIST) ||
       +          read_conf(TYPE2REL) ||
       +          read_conf(PGPREMPUBRING) || read_conf(PGPREMPUBASC) ||
       +          read_conf(PGPREMSECRING) || read_conf(NYMSECRING) ||
       +          read_conf(NYMDB) || read_conf(PIDFILE) ||
       +          read_conf(WGET) || read_conf(STATSSRC) ||
       +          read_conf_i(STATSAUTOUPDATE) || read_conf_t(STATSINTERVAL) ||
       +
       +          read_conf_i(CLIENTAUTOFLUSH) ||
       +          read_conf_i(MAXRECIPIENTS) ||
       +          
       +          read_conf_t(TIMESKEW_FORWARD) ||
       +          read_conf_t(TIMESKEW_BACK) ||
       +          read_conf_i(TEMP_FAIL) );
       +}
       +
       +int mix_config(void)
       +{
       +  char *d;
       +  FILE *f;
       +  char line[PATHMAX];
       +  int err = -1;
       +#ifdef POSIX
       +  struct passwd *pw;
       +#endif /* POSIX */
       +  struct stat buf;
       +#ifdef HAVE_UNAME
       +  struct utsname uts;
       +#endif /* HAVE_UNAME */
       +#ifdef WIN32
       +  HKEY regsw, reg, regpgp;
       +  DWORD type, len;
       +  int rkey = 0;
       +#endif /* WIN32 */
       +
       +  mix_setdefaults();
       +
       +#ifdef POSIX
       +  pw = getpwuid(getuid());
       +#endif /* POSIX */
       +
       + /* find our base directory
       +  *
       +  * first match wins.
       +  *
       +  *  - what the MIXPATH environment variable points to, if it is set.
       +  *  - On WIN32, HKEY_CURRENT_USER\Software\Mixmaster\MixDir, if it exists
       +  *  - whatever is compiled in with -DSPOOL
       +  *  - On Win32 %APPDATA%\Mixmaster
       +  *  - on POSIX, ~/Mix  (or ~/<HOMEMIXDIR>)
       +  *  - the current working directory
       +  */
       +
       +  if (err == -1 && (d = getenv("MIXPATH")) != NULL)
       +    err = mixdir(d, 1);
       +
       +#ifdef WIN32
       +  RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &regsw);
       +  len=sizeof(line);
       +  if (err == -1 &&
       +      RegOpenKeyEx(regsw, "Mixmaster", 0, KEY_QUERY_VALUE, &reg) == 0) {
       +    if (RegQueryValueEx(reg, "MixDir", 0, &type, line, &len) == 0)
       +      err = mixdir(line, 1);
       +    RegCloseKey(reg);
       +  }
       +#endif /* WIN32 */
       +
       +#ifdef SPOOL
       +  if (err == -1 && strlen(SPOOL) > 0)
       +    err = mixdir(SPOOL, 0);
       +#endif /* SPOOL */
       +
       +#ifdef WIN32
       +    if (err == -1) {
       +      LPMALLOC lpmalloc;
       +      ITEMIDLIST *itemidlist;
       +      if (SUCCEEDED(SHGetMalloc(&lpmalloc)))
       +      {
       +        SHGetSpecialFolderLocation(0,CSIDL_APPDATA,&itemidlist);
       +        SHGetPathFromIDList(itemidlist,line);
       +        lpmalloc->lpVtbl->Free(lpmalloc,&itemidlist);
       +        lpmalloc->lpVtbl->Release(lpmalloc);
       +
       +        strcatn(line, "\\Mixmaster", PATHMAX);
       +        err = mixdir(line, 1);
       +
       +      }
       +    }
       +#endif /* WIN32 */
       +
       +#ifdef POSIX
       +  if (err == -1 && pw != NULL) {
       +    strncpy(line, pw->pw_dir, PATHMAX);
       +    line[PATHMAX-1] = '\0';
       +    if (line[strlen(line) - 1] != DIRSEP)
       +      strcatn(line, DIRSEPSTR, PATHMAX);
       +    strcatn(line, HOMEMIXDIR, PATHMAX);
       +    err = mixdir(line, 1);
       +  }
       +#endif /* POSIX */
       +
       +  if (err == -1) {
       +    getcwd(MIXDIR, PATHMAX);
       +    mixdir(MIXDIR, 0);
       +  }
       +
       +#ifdef GLOBALMIXCONF
       +  f = mix_openfile(GLOBALMIXCONF, "r");
       +  if (f != NULL) {
       +    while (fgets(line, LINELEN, f) != NULL)
       +      if (line[0] > ' ' && line[0] != '#')
       +        mix_configline(line);
       +    fclose(f);
       +  }
       +#endif /* GLOBALMIXCONF */
       +  f = mix_openfile(MIXCONF, "r");
       +  if (f != NULL) {
       +    while (fgets(line, LINELEN, f) != NULL)
       +      if (line[0] > ' ' && line[0] != '#')
       +        mix_configline(line);
       +    fclose(f);
       +  }
       +
       +  mixfile(POOLDIR, POOL); /* set POOLDIR after reading POOL from cfg file */
       +  if (POOLDIR[strlen(POOLDIR) - 1] == DIRSEP)
       +    POOLDIR[strlen(POOLDIR) - 1] = '\0';
       +  if (stat(POOLDIR, &buf) != 0)
       +    if
       +#ifndef POSIX
       +      (mkdir(POOLDIR) != 0)
       +#else /* end of not POSIX */
       +      (mkdir(POOLDIR, S_IRWXU) == -1)
       +#endif /* else if POSIX */
       +      strncpy(POOLDIR, MIXDIR, PATHMAX);
       +
       +  if (IDEXP > 0 && IDEXP < 5 * SECONDSPERDAY)
       +    IDEXP = 5 * SECONDSPERDAY;
       +  if (MAXRANDHOPS > 20)
       +    MAXRANDHOPS = 20;
       +  if (INDUMMYP > INDUMMYMAXP)
       +    INDUMMYP = INDUMMYMAXP;
       +  if (OUTDUMMYP > OUTDUMMYMAXP)
       +    OUTDUMMYP = OUTDUMMYMAXP;
       +
       +  if (strchr(SHORTNAME, '.'))
       +    *strchr(SHORTNAME, '.') = '\0';
       +  if (strchr(SHORTNAME, ' '))
       +    *strchr(SHORTNAME, ' ') = '\0';
       +#ifdef HAVE_UNAME
       +  if (SHORTNAME[0] == '\0' && uname(&uts) != -1)
       +    strncpy(SHORTNAME, uts.nodename, LINELEN);
       +#elif defined(HAVE_GETHOSTNAME) /* end of HAVE_UNAME */
       +  if (SHORTNAME[0] == '\0')
       +    gethostname(SHORTNAME, LINELEN);
       +#endif /* defined(HAVE_GETHOSTNAME) */
       +  if (SHORTNAME[0] == '\0')
       +    strcpy(SHORTNAME, "unknown");
       +
       +  if (ADDRESS[0] == '\0')
       +    whoami(ADDRESS, "user");
       +
       +#ifdef HAVE_GECOS
       +  if (NAME[0] == '\0' && pw != NULL)
       +    strcatn(NAME, pw->pw_gecos, sizeof(NAME));
       +#endif /* HAVE_GECOS */
       +
       +  if (REMAILERADDR[0] == '\0')
       +    strncpy(REMAILERADDR, ADDRESS, LINELEN);
       +
       +  if (COMPLAINTS[0] == '\0')
       +    strncpy(COMPLAINTS, REMAILERADDR, LINELEN);
       +
       +  if (strchr(REMAILERNAME, '@') == NULL) {
       +    strcatn(REMAILERNAME, " <", LINELEN);
       +    strcatn(REMAILERNAME, REMAILERADDR, LINELEN);
       +    strcatn(REMAILERNAME, ">", LINELEN);
       +  }
       +  if (strchr(ANONNAME, '@') == NULL && ANONADDR[0] != '\0') {
       +    strcatn(ANONNAME, " <", LINELEN);
       +    strcatn(ANONNAME, ANONADDR, LINELEN);
       +    strcatn(ANONNAME, ">", LINELEN);
       +  }
       +  if (strchr(ANONNAME, '@') == NULL) {
       +    strcatn(ANONNAME, " <", LINELEN);
       +    strcatn(ANONNAME, REMAILERADDR, LINELEN);
       +    strcatn(ANONNAME, ">", LINELEN);
       +  }
       +#ifndef USE_PGP
       +  if (TYPE1[0] == '\0')
       +    PGP = 0;
       +#endif /* not USE_PGP */
       +
       +#ifdef WIN32
       +  if (RegOpenKeyEx(regsw, "PGP", 0, KEY_ALL_ACCESS, &regpgp) == 0)
       +    rkey++;
       +  if (rkey && RegOpenKeyEx(regpgp, "PGPlib", 0, KEY_QUERY_VALUE, &reg) == 0)
       +    rkey++;
       +  if (PGPPUBRING[0] == '\0' && rkey == 2) {
       +    len = PATHMAX;
       +    RegQueryValueEx(reg, "PubRing", 0, &type, PGPPUBRING, &len);
       +  }
       +  if (PGPSECRING[0] == '\0' && rkey == 2) {
       +    len = PATHMAX;
       +    RegQueryValueEx(reg, "SecRing", 0, &type, PGPSECRING, &len);
       +  }
       +  if (rkey == 2)
       +    RegCloseKey(reg);
       +  if (rkey)
       +    RegCloseKey(regpgp);
       +  RegCloseKey(regsw);
       +#endif /* WIN32 */
       +
       +  if (PGPPUBRING[0] == '\0') {
       +    char *d;
       +
       +    if ((d = getenv("HOME")) != NULL) {
       +      strcpy(PGPPUBRING, d);
       +      strcatn(PGPPUBRING, "/.pgp/", PATHMAX);
       +    }
       +    strcatn(PGPPUBRING, "pubring.pkr", PATHMAX);
       +    if (stat(PGPPUBRING, &buf) == -1)
       +      strcpy(strrchr(PGPPUBRING, '.'), ".pgp");
       +  }
       +  if (PGPSECRING[0] == '\0') {
       +    char *d;
       +
       +    if ((d = getenv("HOME")) != NULL) {
       +      strcpy(PGPSECRING, d);
       +      strcatn(PGPSECRING, "/.pgp/", PATHMAX);
       +    }
       +    strcatn(PGPSECRING, "secring.skr", PATHMAX);
       +    if (stat(PGPSECRING, &buf) == -1)
       +      strcpy(strrchr(PGPSECRING, '.'), ".pgp");
       +  }
       +  if (streq(NEWS, "mail-to-news"))
       +    strncpy(NEWS, MAILtoNEWS, sizeof(NEWS));
       +
       +  if (f == NULL) {
       +#ifndef GLOBALMIXCONF
       +    /* Only write the config file in non systemwide installation */
       +    f = mix_openfile(MIXCONF, "w");
       +    if (f == NULL)
       +      errlog(WARNING, "Can't open %s%s!\n", MIXDIR, MIXCONF);
       +    else {
       +      fprintf(f, "# mix.cfg - mixmaster configuration file\n");
       +      fprintf(f, "NAME                %s\n", NAME);
       +      fprintf(f, "ADDRESS                %s\n", ADDRESS);
       +      fprintf(f, "\n# edit to set up a remailer:\n");
       +      fprintf(f, "REMAIL          n\n");
       +      fprintf(f, "SHORTNAME        %s\n", SHORTNAME);
       +      fprintf(f, "REMAILERADDR        %s\n", REMAILERADDR);
       +      fprintf(f, "COMPLAINTS        %s\n", COMPLAINTS);
       +      fclose(f);
       +    }
       +#endif /* not GLOBALMIXCONF */
       +    REMAIL = 0;
       +  }
       +
       +  if (ENTEREDPASSPHRASE[0] != '\0') {
       +    strncpy(PASSPHRASE, ENTEREDPASSPHRASE, LINELEN);
       +    PASSPHRASE[LINELEN-1] = 0;
       +  };
       +
       +  return (0);
       +}
       +
       +/** Library initialization: ******************************************/
       +
       +static int initialized = 0;
       +
       +void mix_check_timeskew() {
       +  FILE *f;
       +  long now, tpool = 0, tpop3 = 0, tdaily = 0, tmailin = 0, latest = 0;
       +
       +  f = mix_openfile(REGULAR, "r+");
       +  if (f != NULL) {
       +    lock(f);
       +    fscanf(f, "%ld %ld %ld %ld", &tpool, &tpop3, &tdaily, &tmailin);
       +    latest = tpool;
       +    latest = latest > tpop3 ? latest : tpop3;
       +    latest = latest > tdaily ? latest : tdaily;
       +    latest = latest > tmailin ? latest : tmailin;
       +    now = time(NULL);
       +
       +
       +    if (( (TIMESKEW_BACK    != 0) && (now < latest - TIMESKEW_BACK   )) ||
       +        ( (TIMESKEW_FORWARD != 0) && (now > latest + TIMESKEW_FORWARD)) ) {
       +      /* Possible timeskew */
       +      errlog(ERRORMSG, "Possible timeskew detected.  Check clock and rm %s\n", REGULAR);
       +      exit(TEMP_FAIL);
       +    }
       +    fclose(f);
       +  } else {
       +    /* shrug */
       +  }
       +}
       +
       +int mix_init(char *mixdir)
       +{
       +  if (!initialized) {
       +    if (mixdir)
       +      strncpy(MIXDIR, mixdir, LINELEN);
       +    mix_config();
       +#if defined(USE_SOCK) && defined(WIN32)
       +    sock_init();
       +#endif /* defined(USE_SOCK) && defined(WIN32) */
       +    /* atexit (mix_exit); */
       +    initialized = 1;
       +  }
       +
       +  if (rnd_init() == -1)
       +    rnd_seed();
       +  return(0);
       +}
       +
       +void mix_exit(void)
       +{
       +  if (!initialized)
       +    return;
       +  rnd_final();
       +#if defined(USE_SOCK) && defined(WIN32)
       +  sock_exit();
       +#endif /* defined(USE_SOCK) && defined(WIN32) */
       +  initialized=0;
       +}
       +
       +void mix_upd_stats(void)
       +{
       +  FILE *f;
       +  BUFFER *statssrc;
       +  statssrc = buf_new();
       +  buf_clear(statssrc);
       +  f = mix_openfile(STATSSRC, "r");
       +  if (f != NULL) {
       +    buf_read(statssrc, f);
       +    fclose(f);
       +  }
       +  if (statssrc->length > 0)
       +    download_stats(statssrc->data);
       +  buf_free(statssrc);
       +}
       +
       +int mix_regular(int force)
       +{
       +  FILE *f;
       +  long now, tpool = 0, tpop3 = 0, tdaily = 0, tmailin = 0, tstats = 0;
       +  int ret = 0;
       +
       +  mix_init(NULL);
       +  now = time(NULL);
       +
       +  f = mix_openfile(REGULAR, "r+");
       +  if (f != NULL) {
       +    lock(f);
       +    fscanf(f, "%ld %ld %ld %ld %ld", &tpool, &tpop3, &tdaily, &tmailin, &tstats);
       +    if (now - tpool >= SENDPOOLTIME)
       +      force |= FORCE_POOL | FORCE_MAILIN;
       +#ifdef USE_SOCK
       +    if (now - tpop3 >= POP3TIME)
       +      force |= FORCE_POP3 | FORCE_MAILIN;
       +#endif /* USE_SOCK */
       +    if (now - tdaily >= SECONDSPERDAY)
       +      force |= FORCE_DAILY;
       +    if (now - tmailin >= MAILINTIME)
       +      force |= FORCE_MAILIN;
       +    if (now - tstats >= STATSINTERVAL)
       +      force |= FORCE_STATS;
       +    if (force & FORCE_POOL)
       +      tpool = now;
       +    if (force & FORCE_POP3)
       +      tpop3 = now;
       +    if (force & FORCE_DAILY)
       +      tdaily = now;
       +    if (force & FORCE_MAILIN)
       +      tmailin = now;
       +    if (force & FORCE_STATS)
       +      tstats = now;
       +    rewind(f);
       +    fprintf(f, "%ld %ld %ld %ld %ld\n", tpool, tpop3, tdaily, tmailin, tstats);
       +    unlock(f);
       +    fclose(f);
       +  } else {
       +    force = FORCE_POOL | FORCE_POP3 | FORCE_DAILY | FORCE_MAILIN | FORCE_STATS;
       +    f = mix_openfile(REGULAR, "w+");
       +    if (f != NULL) {
       +      lock(f);
       +      fprintf(f, "%ld %ld %ld %ld %ld\n", now, now, now, now, now);
       +      unlock(f);
       +      fclose(f);
       +    } else
       +      errlog(ERRORMSG, "Can't create %s!\n", REGULAR);
       +  }
       +
       +  if (force & FORCE_DAILY)
       +    mix_daily(), ret = 1;
       +#ifdef USE_SOCK
       +  if (force & FORCE_POP3)
       +    pop3get();
       +#endif /* USE_SOCK */
       +  if (force & FORCE_MAILIN)
       +    ret = process_mailin();
       +  if (force & FORCE_POOL)
       +    ret = pool_send();
       +  if ((force & FORCE_STATS) && (STATSAUTOUPDATE != 0))
       +    mix_upd_stats();
       +
       +  return (ret);
       +}
       +
       +int mix_daily(void)
       +{
       +  idexp();
       +  pgpmaxexp();
       +  pool_packetexp();
       +  stats(NULL);
       +  keymgt(0);
       +  return (0);
       +}
       +
       +/** Handle signals SIGHUP, SIGINT, and SIGTERM
       +    This signal handler gets called if the daemon
       +    process receives one of SIGHUP, SIGINT, or SIGTERM.
       +    It then sets either rereadconfig of terminatedaemon
       +    to true depending on the signal received.
       +
       +    @author        PP
       +    @return        nothing
       + */
       +#ifdef POSIX
       +void sighandler(int signal) {
       +  if (signal == SIGHUP)
       +    rereadconfig = 1;
       +  else if (signal == SIGINT || signal == SIGTERM)
       +    terminatedaemon = 1;
       +};
       +#endif /* POSIX */
       +
       +/** Set the signal handler for SIGHUP, SIGINT and SIGTERM
       +    This function registers signal handlers so that
       +    we can react on signals send by the user in daemon
       +    mode. SIGHUP will instruct mixmaster to reload its
       +    configuration while SIGINT and SIGTERM will instruct
       +    it to shut down. Mixmaster will finish the current
       +    pool run before it terminates.
       +
       +    @param restart  Whether or not system calls should be
       +                    restarted. Usually we want this, the
       +                    only excetion is the sleep() in the
       +                    daemon mail loop.
       +    @author         PP
       +    @return         -1 if calling sigaction failed, 0 on
       +                    no error
       +  */
       +int setsignalhandler(int restart)
       +{
       +#ifdef POSIX
       +  struct sigaction hdl;
       +  int err = 0;
       +
       +  memset(&hdl, 0, sizeof(hdl));
       +  hdl.sa_handler = sighandler;
       +  hdl.sa_flags = restart ? SA_RESTART : 0;
       +
       +  if (sigaction(SIGHUP, &hdl, NULL))
       +    err = -1;
       +  if (sigaction(SIGINT, &hdl, NULL))
       +    err = -1;
       +  if (sigaction(SIGTERM, &hdl, NULL))
       +    err = -1;
       +  return (err);
       +#else /* POSIX */
       +  return(0);
       +#endif /* POSIX */
       +}
       +
       +#ifdef WIN32
       +/* Try to detect if we are the service or not...
       +   seems there is no easy reliable way        */
       +int is_nt_service(void)
       +{
       +    static int issvc = -1;
       +#ifdef WIN32SERVICE
       +    STARTUPINFO StartupInfo;
       +    OSVERSIONINFO VersionInfo;
       +    DWORD dwsize;
       +
       +    if (issvc != -1)    /* do it only once */
       +        return issvc;
       +
       +    VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
       +    if (GetVersionEx(&VersionInfo))
       +        if (VersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
       +            return issvc = 0; /* not NT - not the service */
       +
       +    GetStartupInfo(&StartupInfo);
       +    if (StartupInfo.lpDesktop[0] == 0)
       +        return issvc = 1; /* have no desktop - we are the service probably */
       +#endif /* WIN32SERVICE */
       +
       +    return issvc = 0; /* assume not the service */
       +} /* is_nt_service */
       +
       +HANDLE hMustTerminate = NULL;
       +void set_nt_exit_event(HANDLE h_svc_exit_event)
       +{
       +    hMustTerminate = h_svc_exit_event;
       +} /* set_nt_exit_event */
       +
       +#endif /* WIN32 */
       +
       +int mix_daemon(void)
       +{
       +  long t, slept;
       +  t = SENDPOOLTIME;
       +  if (MAILINTIME < t && (MAILIN != NULL && MAILIN[0] != '\0'))
       +    t = MAILINTIME;
       +#ifdef USE_SOCK
       +  if (POP3TIME < t)
       +    t = POP3TIME;
       +#endif /* USE_SOCK */
       +  if (t < 5)
       +    t = 5; /* Some kind of safety for broken systems */
       +  slept = t;
       +
       +  setsignalhandler(1); /* set signal handlers and restart any interrupted system calls */
       +  for(;;) {
       +    if (terminatedaemon)
       +      break;
       +    if (rereadconfig) {
       +      rereadconfig = 0;
       +      mix_config();
       +      t = SENDPOOLTIME;
       +      if (MAILINTIME < t && (MAILIN != NULL && MAILIN[0] != '\0'))
       +        t = MAILINTIME;
       +#ifdef USE_SOCK
       +      if (POP3TIME < t)
       +        t = POP3TIME;
       +      if (t < 5)
       +        t = 5; /* Some kind of safety for broken systems */
       +#endif /* USE_SOCK */
       +    }
       +    if (slept >= t) {
       +      mix_regular(0);
       +      slept = 0;
       +    }
       +
       +#ifdef WIN32SERVICE
       +    if (hMustTerminate) {
       +      if (WaitForSingleObject(hMustTerminate, t * 1000) == WAIT_OBJECT_0) {
       +        CloseHandle(hMustTerminate);
       +        terminatedaemon = 1;
       +      }
       +    }
       +#endif /* WIN32SERVICE */
       +
       +    if (!terminatedaemon && !rereadconfig) {
       +      setsignalhandler(0); /* set signal handlers;  don't restart system calls */
       +#ifdef WIN32
       +      sleep(t); /* how to get the real number of seconds slept? */
       +      slept = t;
       +#else /* end of WIN32 */
       +      slept += (t - slept) - sleep(t - slept);
       +#endif /* else if not WIN32 */
       +      setsignalhandler(1); /* set signal handlers and restart any interrupted system calls */
       +    }
       +  }
       +  return (0);
       +}
       +
       +/** error ***************************************************************/
       +
       +void errlog(int type, char *fmt,...)
       +{
       +  va_list args;
       +  BUFFER *msg;
       +  FILE *e = NULL;
       +  time_t t;
       +  struct tm *tc;
       +  char line[LINELEN];
       +  int p;
       +  char err[6][8] =
       +  {"", "Error", "Warning", "Notice", "Info", "Info"};
       +
       +  if ((VERBOSE == 0 && type != ERRORMSG) || (type == LOG && VERBOSE < 2)
       +      || (type == DEBUGINFO && VERBOSE < 3))
       +    return;
       +
       +  t = time(NULL);
       +  tc = localtime(&t);
       +  strftime(line, LINELEN, "[%Y-%m-%d %H:%M:%S] ", tc);
       +
       +  msg = buf_new();
       +  buf_appends(msg, line);
       +  p = msg->length;
       +  buf_appendf(msg, "%s: ", err[type]);
       +  va_start(args, fmt);
       +  buf_vappendf(msg, fmt, args);
       +  va_end(args);
       +
       +  if (streq(ERRLOG, "stdout"))
       +    e = stdout;
       +  else if (streq(ERRLOG, "stderr"))
       +    e = stderr;
       +
       +  if (e == NULL && (ERRLOG[0] == '\0' ||
       +                    (e = mix_openfile(ERRLOG, "a")) == NULL))
       +    mix_status("%s", msg->data + p);
       +  else {
       +    buf_write(msg, e);
       +    if (e != stderr && e != stdout) {
       +      fclose(e);
       +      /* duplicate the error message on screen */
       +      mix_status("%s", msg->data + p);
       +    }
       +  }
       +  buf_free(msg);
       +}
       +
       +static char statusline[BUFSIZE] = "";
       +
       +void mix_status(char *fmt,...)
       +{
       +  va_list args;
       +
       +  if (fmt != NULL) {
       +    va_start(args, fmt);
       +#ifdef _MSC
       +    _vsnprintf(statusline, sizeof(statusline) - 1, fmt, args);
       +#else /* end of _MSC */
       +    vsnprintf(statusline, sizeof(statusline) - 1, fmt, args);
       +#endif /* else if not _MSC */
       +    va_end(args);
       +  }
       +#ifdef USE_NCURSES
       +  if (menu_initialized) {
       +    cl(LINES - 2, 10);
       +    printw("%s", statusline);
       +    refresh();
       +  } else
       +#endif /* USE_NCURSES */
       +  {
       +    fprintf(stderr, "%s", statusline);
       +  }
       +}
       +
       +void mix_genericerror(void)
       +{
       +  if (streq(statusline, "") || strfind(statusline, "...") ||
       +      strifind(statusline, "generating"))
       +    mix_status("Failed!");
       +  else
       +    mix_status(NULL);
       +}
   DIR diff --git a/Src/mix.h b/Src/mix.h
       t@@ -0,0 +1,917 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +
       +   Mixmaster Library API
       +   =====================
       +
       +The Mixmaster library consists of a set of high-level functions that
       +generate or process remailer messages, lower-level functions that
       +manipulate data in various ways, and a number of functions that
       +provide an interface to the underlying cryptographic library.
       +Generally, a return value of 0 indicates success, and -1 an error.
       +
       +
       +Initialization
       +==============
       +
       +int mix_init(char mixdir[]);
       +
       +  This function initializes internal data of the Mixmaster library,
       +  such as the random number generator. This should be the first call
       +  to the Mixmaster library. It returns 0 on success. If the random
       +  number generator cannot be initialized, mix_init() terminates.
       +
       +  The variable mixdir determines where the Mixmaster configuration
       +  files and the message pool are located. If mixdir is NULL, the
       +  library will use the directory specified in the environment variable
       +  $MIXPATH, the directory given at compile time if it exists, and the
       +  directory ~/Mix otherwise.
       +
       +
       +void mix_exit(void);
       +
       +  A program must call mix_exit before exiting. This function writes back
       +  the state of the random number generator.
       +
       +
       +Using the Mixmaster DLL
       +=======================
       +
       +In textmode applications, mix_init() can be used as described above.
       +In graphical applications, these functions are not needed. Instead,
       +the function rnd_mouse() should be called whenever the program gets
       +WM_MOUSEMOVE or other messages:
       +
       +int rnd_mouse(UINT i, WPARAM w, LPARAM l);
       +
       +  All events that a window gets may be passed to this function. It
       +  will extract the inherent randomness in user interaction, especially
       +  in mouse movements. It returns 100 if it has accumulated enough
       +  randomness to perform cryptographic operations, and a number between
       +  0 and 99 otherwise. This number can be used to provide graphical
       +  feedback on the progress of initializing the random number generator
       +  while asking the user to move the mouse. A runtime error will occur
       +  if any cryptographic functions are used before rnd_mouse() has
       +  signaled success.
       +
       +
       +Message I/O
       +===========
       +
       +The library uses dynamically allocated buffers for messages and other
       +data. Functions for buffer manipulation are described in section
       +"Buffers" below.
       +
       +
       +BUFFER *buf_new(void);
       +
       +  Buffers must be initialized before they can be used. buf_new() returns
       +  a pointer to a newly initialized buffer.
       +
       +
       +int buf_free(BUFFER *buf);
       +
       +  When a buffer is no longer needed, it should be freed. This function
       +  returns the memory used for the buffer to the operating system.
       +
       +
       +int buf_read(BUFFER *message, FILE *infile);
       +
       +  This function reads data from a stream and appends them to the buffer.
       +
       +  Return values:
       +   0 on success,
       +   1 if the file is too large to store it in a buffer,
       +  -1 if no data could be read.
       +
       +
       +int buf_write(BUFFER *message, FILE *outfile);
       +
       +  This function writes the entire buffer to the output stream.
       +
       +  Return values:
       +   0 if the buffer could be written completely,
       +  -1 otherwise.
       +
       +int buf_write_sync(BUFFER *message, FILE *outfile);
       +
       +  This function does the same as buf_write but also does
       +  checks for return values of fflush, fsync and ***fclose***.
       +
       +  Return values:
       +   0 if the buffer could be written, synced and closed completely,
       +  -1 otherwise.
       +
       +Remailer Messages
       +=================
       +
       +int mix_encrypt(int type, BUFFER *message, char *chain, int numcopies,
       +        BUFFER *feedback);
       +
       +  This function creates a Mixmaster message and stores it the Mixmaster
       +  message pool.
       +
       +  The type is one of the following:
       +
       +   MSG_MAIL  electronic mail message
       +   MSG_POST  Usenet news article
       +   MSG_NULL  dummy message, will be discarded
       +
       +  *chain is a string consisting of a comma-separated list of remailer
       +  names that the message will be sent through. '*' means that a remailer
       +  will be chosen at random. If *chain is NULL, mix_encrypt() will use the
       +  default chain.
       +
       +  numcopies is a number between 1 and 10 that indicates how many
       +  (redundant) copies of the message should be sent. If numcopies is 0,
       +  the default value will be used. The default values for *chain and
       +  numcopies are read from the configuration file.
       +
       +  If *feedback is not NULL, mix_encrypt() will write the chain(s) that
       +  have been selected as newline-separated strings, or a textual error
       +  message to *feedback. This text can be presented to the user as
       +  feedback.
       +
       +  Return values:
       +   0 on success,
       +  -1 if the message could not be created.
       +
       +
       +int mix_decrypt(BUFFER *message);
       +
       +  This is the remailer function, which reads Mixmaster and Cypherpunk
       +  remailer messages as well as help file and key requests. Remailer
       +  messages are decrypted and stored in the message pool. Replies to
       +  information requests are sent immediately.
       +
       +  Return values:
       +   0  if the message has been processed successfully,
       +   1  if the message is of an unknown type,
       +  -1  if the message could not be processed.
       +
       +
       +int mix_send(void);
       +
       +  This function causes the messages in the pool to be sent. Depending on
       +  the configuration, mix_send() may send only a certain fraction of the
       +  messages in the pool.
       +
       +  Return value: The size of the pool after the messages have been sent.
       +
       +
       +int mix_regular(int force);
       +
       +  This function is responsible for regular actions of the remailer such
       +  as sending messages from the pool, getting mail from POP3 servers and
       +  expiring log files.
       +
       +
       +Nymserver Client Functions
       +==========================
       +
       +The nymserver functions use user_pass() to get the passphrase for
       +opening the nym database.
       +
       +int nym_config(int mode, char *nym, char *nymserver, BUFFER *pseudonym,
       +               char *sendchain, int sendnumcopies, BUFFER *chains,
       +               BUFFER *options);
       +
       +  Create, modify or delete a nym. mode is one of NYM_CREATE, NYM_MODIFY and
       +  NYM_DELETE.
       +
       +  nym is the pseudonymous address or its local part. In the latter case,
       +  nymserver must contain a string that selects a nymserver.
       +
       +  pseudonym is a text string or NULL.
       +
       +  sendchain and sendnumcopies are the chain and number of copies of
       +  the Mixmaster message sent to the nymserver.
       +
       +  chains contains a list of reply blocks, consisting of "To:",
       +  "Newsgroups:", "Null:", "Latency:", "Chain:" and arbitrary header lines
       +  such as "Subject:". The "Chain:" line contains a remailer selection
       +  string for type 1 remailers. The reply blocks are separated by empty
       +  lines.
       +
       +  options contains nymserver options (any of "acksend", "signsend",
       +  "fixedsize", "disable", "fingerkey" with a "+" or "-" prefix) or is NULL.
       +
       +
       +int nym_encrypt(BUFFER *msg, char *nym, int type);
       +
       +  Prepare the message msg of type MSG_MAIL or MSG_POST to be sent using
       +  the nym. After successful encryption, msg contains a message of type
       +  MSG_MAIL addressed to the nymserver.
       +
       +
       +int nym_decrypt(BUFFER *msg, char *nym, BUFFER *log);
       +
       +  Decrypt nymserver replies and PGP messages. If msg contains a nymserver
       +  reply, the the recipient nym is stored in nym (unless nym is NULL), and
       +  msg is replaced with the plaintext message in the Unix mail folder
       +  format.
       +
       +  If log is not NULL, nym_decrypt will compute a unique ID for each
       +  message and append it to log. If the ID already is contained in log,
       +  it will return an empty msg buffer.
       +
       +
       +Lower-Level Remailer Functions
       +==============================
       +
       +t1_decrypt(BUFFER *in);
       +
       +  Decrypts and processes a Cypherpunk remailer message.
       +
       +
       +t2_decrypt(BUFFER *in);
       +
       +  Decrypts and processes a Mixmaster remailer message.
       +
       +
       +int mix_pool(BUFFER *msg, int type, long latent);
       +
       +  Adds the message msg of type MSG_MAIL or MSG_POST to the pool.
       +  latent is 0 or the message latency in seconds.
       +
       +
       +OpenPGP encryption
       +==================
       +
       +int pgp_encrypt(int mode, BUFFER *message, BUFFER *encr,
       +               BUFFER *sigid, BUFFER *pass, char *pubring,
       +               char *secring);
       +
       +  This function encrypts and signs a message according to OpenPGP (RFC 2440).
       +
       +  mode is the bitwise or of one of PGP_ENCRYPT, PGP_CONVENTIONAL and PGP_SIGN,
       +  and any of PGP_TEXT, PGP_REMAIL and PGP_NOARMOR.
       +
       +  PGP_CONVENTIONAL: the message is encrypted conventionally, using
       +            the passphrase encr. If PGP_NCONVENTIONAL is used instead,
       +            the new OpenPGP format is used.
       +  PGP_ENCRYPT: public key encryption is used. The message is encrypted to
       +            the first public key on the keyring a User ID of which contains
       +            the substring encr. encr may contain several lines with one
       +            address substring each.
       +  PGP_SIGN: the message is signed with the first key from the secret
       +            key ring whose user ID contains sigid as a substring, or the
       +            first key if sigid is NULL.
       +  PGP_TEXT: message is treated as text, without PGP_TEXT as binary.
       +  PGP_DETACHEDSIG: signature will not include the signed message.
       +  PGP_REMAIL: a random offset is subtracted from signature dates, and the
       +            ASCII armor is made to mimic PGP.
       +  PGP_NOARMOR: message armor is not applied.
       +
       +  If none of PGP_SIGN, PGP_CONVENTIONAL and PGP_ENCRYPT is set, the
       +  message is only compressed and armored.
       +
       +  pubring and secring can be NULL or specify the name of a key ring.
       +
       +  Return values:
       +   0       on success,
       +  -1       no matching key found,
       +  PGP_PASS bad signature passphrase.
       +
       +
       +int pgp_mailenc(int mode, BUFFER *message, char *sigid,
       +                BUFFER *pass, char *pubring, char *secring);
       +
       +  This function encrypts and signs an RFC 822 e-mail message according to
       +  RFC 2015 (OpenPGP/MIME). Signatures without encryption on non-MIME messages
       +  are "cleartext" signatures.
       +
       +
       +int pgp_decrypt(BUFFER *message, BUFFER *pass, BUFFER *sig, char *pubring,
       +               char *secring);
       +
       +  This function decrypts the OpenPGP message and verifies its signature.
       +  pass must contain the passphrase if message is conventionally encrypted
       +  or the secret key is protected by a passphrase. Otherwise it can be
       +  NULL.
       +
       +  If message is a detached signature, sig must contain the signed data.
       +  It sig is NULL, the message will be decrypted without signature
       +  verification.
       +
       +  pgp_getmsg() writes a string containing the signing time and
       +  signer's user ID or the key ID of the unknown signature key to sig.
       +
       +  pubring and secring can be NULL or specify the name of a key ring.
       +
       +  Return values:
       +  PGP_OK      on success,
       +  PGP_ERR     the message can't be read,
       +  PGP_PASS    bad passphrase,
       +  PGP_NOMSG   message is not an OpenPGP message,
       +  PGP_SIGOK   success, and signature has been verified,
       +  PGP_SIGNKEY can't verify signature,
       +  PGP_SIGBAD  bad signature,
       +  PGP_NODATA  OpenPGP message does not contain user data.
       +
       +
       +int pgp_keygen(int algo, int bits, BUFFER *userid, BUFFER *pass, char *pubring,
       +               char *secring, int remail);
       +
       +  Generate a new key pair with given userid, encrypt the secret key with
       +  pass if not NULL.  Use a fake date if remail is not zero. Assume an
       +  encrypted secring if remail == 2.  algo is PGP_ES_RSA or PGP_E_ELG.
       +
       +
       +Buffers
       +=======
       +
       +Buffers contain binary data of arbitrary length. You can append data
       +to buffers, clear buffers, and read data from buffers sequentially.
       +As data are appended to a buffer, memory is allocated dynamically.
       +
       +typedef unsigned char byte;
       +
       +typedef struct
       +{
       +    byte *data;
       +    long length;
       +    long ptr;
       +    long size;
       +    byte sensitive;
       +} BUFFER;
       +
       +For a buffer *b, b->data is a pointer to at least b->length+1 bytes of
       +memory. b->data[b->length] is guaranteed to contain a null byte, so that
       +string functions can be used directly on buffers that contain text.
       +
       +ptr is a counter for reading data from the buffer. b->data[b->ptr] is
       +the first data byte that has not been read (0 <= ptr <= length).
       +
       +If sensitive is 1, the buffer contents will be overwritten before the
       +memory is released.
       +
       +
       +int buf_reset(BUFFER *buf);
       +
       +  This function empties the buffer and returns the memory it has used to
       +  the operating system. It does not free the buffer itself.
       +
       +
       +int buf_clear(BUFFER *buf);
       +
       +  buf_clear() empties the buffer but does not free the memory it uses.
       +  This function should be used if data of a similar size will be stored
       +  to the buffer later.
       +
       +
       +int buf_eq(BUFFER *buf1, BUFFER *buf2);
       +
       +  Return values:
       +   1 if the buffers contain identical data,
       +   0 otherwise.
       +
       +
       +int buf_append(BUFFER *buf, byte *msg, int len);
       +
       +  This is the most basic function for appending data to a buffer. It is
       +  called by all other functions that write to buffers. buf_append()
       +  appends len bytes pointed to by msg to buf. New memory will be
       +  allocated for the buffer if necessary.
       +
       +  If msg is NULL, the buffer is increased by len bytes, but no
       +  guarantee is made about the contents of the appended bytes.
       +
       +  Return value:
       +   0 on success,
       +   does not return if allocation of memory fails.
       +
       +
       +int buf_appendc(BUFFER *buf, byte b);
       +  appends the byte b to buf.
       +
       +
       +int buf_appends(BUFFER *buf, char *s);
       +  appends the null-terminated string s to buf.
       +
       +
       +int buf_appendf(BUFFER *buf, char *fmt, ...);
       +  appends formatted output to buf.
       +
       +
       +int buf_sets(BUFFER *buf, char *s);
       +  sets buf to contain the null-terminated string s.
       +
       +
       +int buf_setf(BUFFER *buf, char *fmt, ...);
       +  sets buf to contain the formatted output.
       +
       +
       +int buf_nl(BUFFER *buf);
       +  appends a newline character to buf.
       +
       +
       +int buf_cat(BUFFER *buf, BUFFER *f);
       +  appends the entire contents of f to buf.
       +
       +
       +int buf_rest(BUFFER *buf, BUFFER *f);
       +  appends the unread data from f to buf.
       +
       +
       +int buf_set(BUFFER *buf, BUFFER *f);
       +  sets buf to a copy of the contents of f.
       +
       +
       +int buf_move(BUFFER *buf, BUFFER *f);
       +  sets buf to the contents of f, and resets f. This is equivalent to
       +  buf_set(buf, f); buf_reset(f); but more efficient.
       +
       +
       +int buf_appendrnd(BUFFER *buf, int n);
       +  appends n cryptographically strong pseudo-random bytes to buf.
       +
       +
       +int buf_setrnd(BUFFER *buf, int n);
       +  places n cryptographically strong pseudo-random bytes in buf.
       +
       +
       +int buf_appendzero(BUFFER *buf, int n);
       +  appends n null bytes to buf.
       +
       +
       +int buf_pad(BUFFER *buf, int size);
       +  pads the buffer with cryptographically strong pseudo-random data to
       +  length size. Aborts if size < buf->length.
       +
       +
       +int buf_appendi(BUFFER *b, int i);
       +  appends the two bytes representing i in big-endian byte order to buf.
       +
       +
       +int buf_appendi_lo(BUFFER *b, int i);
       +  appends the two bytes representing i in little-endian byte order to buf.
       +
       +
       +int buf_appendl(BUFFER *buf, long l);
       +  appends the four bytes representing l in big-endian byte order to buf.
       +
       +
       +int buf_appendl_lo(BUFFER *buf, long l);
       +  appends the four bytes representing l in little-endian byte order to buf.
       +
       +
       +int buf_prepare(BUFFER *buf, int size);
       +  sets buf to contain size bytes of arbitrary data.
       +
       +
       +int buf_get(BUFFER *buf, BUFFER *t, int n);
       +
       +  This function sets buffer t to contain n bytes read from buf.
       +
       +  Return values:
       +   0 on success,
       +  -1 if buf does not contain n unread bytes.
       +
       +
       +int buf_getc(BUFFER *buf);
       +  reads one byte from buf. Returns -1 if buf contains no unread data,
       +  the byte otherwise.
       +
       +
       +int buf_geti(BUFFER *buf);
       +  reads two bytes from buf. Returns -1 if buf buf does not contain two
       +  unread bytes, the integer represented by the bytes in big-endian
       +  byte order otherwise.
       +
       +
       +int buf_geti_lo(BUFFER *buf);
       +  reads two bytes from buf. Returns -1 if buf buf does not contain two
       +  unread bytes, the integer represented by the bytes in little-endian
       +  byte order otherwise.
       +
       +
       +long buf_getl(BUFFER *buf);
       +  reads four bytes from buf. Returns -1 if buf buf does not contain four
       +  unread bytes, the integer represented by the bytes in big-endian
       +  byte order otherwise.
       +
       +
       +long buf_getl_lo(BUFFER *buf);
       +  reads four bytes from buf. Returns -1 if buf buf does not contain four
       +  unread bytes, the integer represented by the bytes in little-endian
       +  byte order otherwise.
       +
       +
       +void buf_ungetc(BUFFER *buf);
       +  restores one character for reading.
       +
       +
       +int buf_appendb(BUFFER *buf, BUFFER *p);
       +  appends p (with length information) to buf.
       +
       +
       +int buf_getb(BUFFER *buf, BUFFER *p);
       +  gets length information, then p from buf.
       +
       +
       +int buf_getline(BUFFER *buf, BUFFER *line);
       +
       +  This function reads one line of text from buf, and stores it (without
       +  the trailing newline) in the buffer line.
       +
       +  Return values:
       +   0 if a line of text has been read,
       +   1 if the line read is empty,
       +  -1 if buf contains no unread data.
       +
       +
       +int buf_lookahead(BUFFER *buf, BUFFER *line);
       +
       +  This function reads one line of text from buf, and stores it (without
       +  the trailing newline) in the buffer line, without increasing the read
       +  counter.
       +
       +  Return values:
       +   0 if a line of text has been read,
       +   1 if the line read is empty,
       +  -1 if buf contains no unread data.
       +
       +
       +int buf_chop(BUFFER *buf);
       +
       +  buf is assumed to contain one line of text. A trailing newline and any
       +  other lines of text buf may contain are removed.
       +
       +
       +int buf_isheader(BUFFER *buf);
       +
       +  This function checks whether the first line of buf is a RFC 822 header line.
       +
       +  Returns:
       +   0 if it is not a header line.
       +   1 if it is a header line.
       +
       +int buf_getheader(BUFFER *buf, BUFFER *field, BUFFER *content);
       +
       +  This function reads a RFC 822 header line from buf. The field name of
       +  the header line without the colon is stored in field, the line's
       +  contents in content.
       +
       +  Returns:
       +   0 on success,
       +   1 at end of header,
       +  -1 if buf contains no unread data.
       +
       +
       +int buf_appendheader(BUFFER *buffer, BUFFER *field, BUFFER *content);
       +
       +  This function appends the RFC 822 header consisting of field and content
       +  to buffer.
       +
       +
       +int buf_rewind(BUFFER *buf);
       +
       +  This function sets the read counter of buf to the start of the buffer
       +  (equivalent to buf->ptr = 0).
       +
       +
       +Randomness
       +==========
       +
       +byte rnd_byte(void);
       +  returns a random byte.
       +
       +
       +int rnd_number(int n);
       +  returns a random number in 0 .. n-1.
       +
       +
       +int rnd_bytes(byte *b, int n);
       +  stores n random bytes at b.
       +
       +
       +Interface to the crypto library PRNG
       +====================================
       +
       +int rnd_init(void);
       +
       +  initializes the PRNG from the random seed file. Called from mix_init().
       +  Return values:
       +   0 on success,
       +  -1 on error.
       +
       +
       +int rnd_final(void);
       +
       +  writes the random seed file and ends the PRNG. Called from mix_exit().
       +  Return values:
       +   0 on success,
       +  -1 on error.
       +
       +
       +int rnd_seed(void);
       +  seeds the PRNG, using console input if necessary.
       +
       +
       +void rnd_update(byte *b, int n);
       +  adds n bytes from b to the PRNG, unless b == NULL, and adds randomness
       +  from the system environment.
       +
       +
       +extern int rnd_state;
       +  An application may set rnd_state = RND_WILLSEED before executing
       +  mix_init() to indicate that it will seed the PRNG later by making calls
       +  to rnd_update() and then to rnd_initialized(). In that case,
       +  rnd_seed() will not ask for user input. [This is what the DLL startup code
       +  does internally.]
       +
       +
       +String comparison
       +=================
       +
       +These functions operate on null-terminated strings. They return truth
       +values.
       +
       +
       +int streq(const char *s1, const char *s2);
       +
       +  Return values:
       +   1 if the strings s1 and s2 are equal,
       +   0 otherwise.
       +
       +
       +int strieq(const char *s1, const char *s2);
       +
       +  Return values:
       +   1 if the strings s1 and s2 are equal except for case,
       +   0 otherwise.
       +
       +
       +int strleft(const char *s, const char *keyword);
       +
       +  Return values:
       +   1 if keyword is the left part of s,
       +   0 otherwise.
       +
       +
       +int strileft(const char *s, const char *keyword);
       +
       +  Return values:
       +   1 if keyword is the left part of s, except for case,
       +   0 otherwise.
       +
       +
       +int strfind(const char *s, const char *keyword);
       +
       +  Return values:
       +   1 if keyword is contained in s,
       +   0 otherwise.
       +
       +
       +int strifind(const char *s, const char *keyword);
       +
       +  Return values:
       +   1 if keyword is contained in s, except for case,
       +   0 otherwise.
       +
       +
       +RFC 822 Addresses
       +=================
       +
       +void rfc822_addr(BUFFER *destination, BUFFER *list);
       +  stores a list of RFC 822 addresses from destination in list, separated
       +  by newlines.
       +
       +void rfc822_name(BUFFER *line, BUFFER *name);
       +  stores the name given in the RFC 822 address in line in name.
       +
       +
       +Files and Pipes
       +===============
       +
       +int mixfile(char path[PATHMAX], const char *name);
       +  stores the path to a given file in the Mixmaster directory in path[].
       +
       +
       +FILE *mix_openfile(const char *name, const char *a);
       +  opens a file in the Mixmaster directory.
       +
       +
       +LOCK *lockfile(char *filename);
       +  creates and locks a lockfile associated with filename.
       +
       +
       +int unlockfile(LOCK *lock);
       +  releases the lock and deletes the lockfile.
       +
       +
       +int lock(FILE *f);
       +  sets a lock on a file.
       +
       +
       +int unlock(FILE *f);
       +  releases a lock on a file.
       +
       +
       +FILE *openpipe(const char *prog);
       +  opens a pipe.
       +
       +
       +int closepipe(FILE *p);
       +  closes a pipe.
       +
       +
       +int sendmail(BUFFER *message, BUFFER *address, const char *from);
       +
       +  This function sends a mail message. The From: line and the destination
       +  address may be contained in the message; in that case address and from
       +  must be NULL. address is checked against the destination block list.
       +
       +int sendmail_loop(BUFFER *message, BUFFER *address, const char *from);
       +
       +  Identical to sendmail() but adds an X-Loop: header line.
       +
       +
       +Printable Encoding
       +==================
       +
       +int encode(BUFFER *buf, int linelen);
       +
       +  buf is encoded in base 64 encoding [RFC 1421]. If linelen > 0, the
       +  resulting text is broken into lines of linelen characters.
       +
       +  Return value: 0.
       +
       +
       +int decode(BUFFER *in, BUFFER *out);
       +
       +  This function reads the unread data from in, as long as it is valid
       +  base 64 encoded text, and stores the decoded data in out.
       +
       +  Return values:
       +   0 if the in could be decoded to the end,
       +  -1 otherwise.
       +
       +
       +int hdr_encode(BUFFER *in, int n);
       +
       +  Encodes a header line according to the MIME standard. The header is
       +  broken into lines of at most n characters.
       +
       +
       +int mail_encode(BUFFER *in, int encoding);
       +
       +  Encodes the mail headers of a message, and encodes the body according
       +  to encoding MIME_7BIT or MIME_8BIT.
       +
       +
       +void id_encode(byte id[16], byte *s);
       +  stores the hexadecimal representation of id in s.
       +
       +
       +void id_decode(byte *s, byte id[16]);
       +  sets id to the value of the hexadecimal string s.
       +
       +
       +Compression
       +===========
       +
       +int buf_zip(BUFFER *buf, BUFFER *f, int b);
       +
       +  compresses buffer f using GZIP with b bits (or a default value, if
       +  b == 0), and appends the result to buf.
       +
       +  Return values:
       +   0 on success,
       +  -1 on error.
       +
       +
       +int buf_unzip(BUFFER *buf, int type);
       +
       +  uncompresses a GZIP [RFC 1952] compressed buffer. If type == 1, uncompress
       +  a ZLIB [RFC 1950] compressed buffer.
       +
       +  Return values:
       +   0 on success,
       +  -1 on error.
       +
       +
       +**************************************************************************/
       +
       +#ifndef _MIXLIB_H
       +#define _MIXLIB_H
       +
       +#include <stdio.h>
       +#include <time.h>
       +#ifdef WIN32
       +#include <windows.h>
       +#endif /* WIN32 */
       +
       +typedef unsigned char byte;
       +
       +typedef struct {
       +  byte *data;
       +  long length;
       +  long ptr;
       +  long size;
       +  byte sensitive;
       +} BUFFER;
       +
       +int mix_init(char *);
       +void mix_exit(void);
       +void rnd_update(byte *b, int n);
       +void rnd_initialized(void);
       +#ifdef WIN32
       +int rnd_mouse(UINT i, WPARAM w, LPARAM l);
       +#endif /* WIN32 */
       +
       +BUFFER *buf_new(void);
       +int buf_free(BUFFER *buf);
       +int buf_read(BUFFER *message, FILE *infile);
       +int buf_write(BUFFER *message, FILE *outfile);
       +int buf_write_sync(BUFFER *message, FILE *outfile);
       +
       +#define MSG_MAIL 1
       +#define MSG_POST 2
       +#define MSG_NULL 0
       +
       +extern char MIXDIR[];
       +
       +int mix_encrypt(int type, BUFFER *message, char *chain, int numcopies,
       +                BUFFER *feedback);
       +int mix_decrypt(BUFFER *message);
       +int mix_send(void);
       +
       +#define FORCE_POOL 1
       +#define FORCE_POP3 2
       +#define FORCE_DAILY 4
       +#define FORCE_MAILIN 8
       +#define FORCE_STATS 16
       +void mix_check_timeskew(void);
       +int mix_regular(int force);
       +int mix_daemon(void);
       +int process_mailin(void);
       +
       +#ifdef USE_PGP
       +
       +#define NYM_CREATE 0
       +#define NYM_MODIFY 1
       +#define NYM_DELETE 2
       +
       +int nym_config(int mode, char *nym, char *nymserver, BUFFER *pseudonym,
       +               char *sendchain, int sendnumcopies, BUFFER *chains,
       +               BUFFER *options);
       +int nym_encrypt(BUFFER *msg, char *nym, int type);
       +int nym_decrypt(BUFFER *msg, char *nym, BUFFER *log);
       +
       +#define PGP_SIGN 1
       +#define PGP_ENCRYPT 2
       +#define PGP_CONVENTIONAL 4
       +#define PGP_REMAIL 8
       +#define PGP_TEXT 16
       +#define PGP_NOARMOR 32
       +#define PGP_DETACHEDSIG 64
       +#define PGP_NCONVENTIONAL 128
       +#define PGP_CONV3DES 256
       +#define PGP_CONVCAST 512
       +
       +/* error codes */
       +#define PGP_OK 0                /* valid message, not signed */
       +#define PGP_SIGOK 1                /* valid signature */
       +#define PGP_NOMSG 2                /* is not an OpenPGP message */
       +#define PGP_NODATA 3                /* OpenPGP packet does not contain user data */
       +#define PGP_SIGNKEY 4                /* can't verify signature */
       +#define PGP_ERR -1                /* can't read message, no matching key found */
       +#define PGP_PASS -2                /* bad passphrase */
       +#define PGP_SIGBAD -3                /* bad signature */
       +
       +
       +/* algorithms */
       +#define PGP_ANY 0
       +#define PGP_ES_RSA 1
       +#define PGP_E_ELG 16
       +#define PGP_S_DSA 17
       +
       +int pgp_encrypt(int mode, BUFFER *message, BUFFER *encr, BUFFER *sigid,
       +                BUFFER *pass, char *pubring, char *secring);
       +int pgp_decrypt(BUFFER *message, BUFFER *pass, BUFFER *sig, char *pubring,
       +                char *secring);
       +int pgp_keygen(int algo, int bits, BUFFER *userid, BUFFER *pass,
       +                  char *pubring, char *secring, int remail);
       +#endif /* USE_PGP */
       +
       +
       +/* parsedate */
       +time_t parsedate(char *p);
       +
       +
       +
       +#ifdef WIN32
       +
       +#define sleep(x) Sleep((x)*1000)
       +#define strcasecmp stricmp
       +
       +#endif /* WIN32 */
       +
       +#endif /* not _MIXLIB_H */
   DIR diff --git a/Src/mix3.h b/Src/mix3.h
       t@@ -0,0 +1,443 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Function prototypes
       +   $Id: mix3.h 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#ifndef _MIX3_H
       +#define _MIX3_H
       +#define COPYRIGHT "Copyright Anonymizer Inc. et al."
       +
       +#include "config.h"
       +#include "mix.h"
       +
       +#ifdef WIN32
       +#ifndef USE_SOCK
       +#define _WINSOCKAPI_                /* don't include winsock */
       +#endif /* not USE_SOCK */
       +#include <windows.h>
       +#ifdef _MSC
       +#define snprintf _snprintf
       +#endif /* _MSC */
       +#define DIRSEP '\\'
       +#define DIRSEPSTR "\\"
       +#else /* end of WIN32 */
       +#define DIRSEP '/'
       +#define DIRSEPSTR "/"
       +#endif /* else if not WIN32 */
       +
       +#define NOT_IMPLEMENTED {printf("Function not implemented.\n");return -1;}
       +#define SECONDSPERDAY 86400
       +
       +#include <time.h>
       +
       +/* Dynamically allocated buffers */
       +
       +int buf_reset(BUFFER *buffer);
       +int buf_clear(BUFFER *buffer);
       +int buf_append(BUFFER *buffer, byte *mess, int len);
       +int buf_cat(BUFFER *to, BUFFER *from);
       +int buf_set(BUFFER *to, BUFFER *from);
       +int buf_rest(BUFFER *to, BUFFER *from);
       +int buf_appendrnd(BUFFER *to, int n);
       +int buf_appendzero(BUFFER *to, int n);
       +int buf_setc(BUFFER *buf, byte c);
       +int buf_appendc(BUFFER *to, byte b);
       +int buf_setrnd(BUFFER *b, int n);
       +int buf_setf(BUFFER *buffer, char *fmt, ...);
       +int buf_appendf(BUFFER *buffer, char *fmt, ...);
       +int buf_sets(BUFFER *buf, char *s);
       +int buf_appends(BUFFER *buffer, char *s);
       +int buf_nl(BUFFER *buffer);
       +int buf_pad(BUFFER *buffer, int size);
       +int buf_prepare(BUFFER *buffer, int size);
       +int buf_rewind(BUFFER *buffer);
       +int buf_getc(BUFFER *buffer);
       +void buf_ungetc(BUFFER *buffer);
       +int buf_get(BUFFER *buffer, BUFFER *to, int n);
       +int buf_getline(BUFFER *buffer, BUFFER *line);
       +int buf_chop(BUFFER *b);
       +void buf_move(BUFFER *dest, BUFFER *src);
       +byte *buf_data(BUFFER *buffer);
       +int buf_isheader(BUFFER *buffer);
       +int buf_getheader(BUFFER *buffer, BUFFER *field, BUFFER *content);
       +int buf_appendheader(BUFFER *buffer, BUFFER *field, BUFFER *contents);
       +int buf_lookahead(BUFFER *buffer, BUFFER *line);
       +int buf_eq(BUFFER *b1, BUFFER *b2);
       +int buf_ieq(BUFFER *b1, BUFFER *b2);
       +void buf_cut_out(BUFFER *buffer, BUFFER *cut_out, BUFFER *rest,
       +                 int from, int len);
       +
       +int buf_appendl(BUFFER *b, long l);
       +int buf_appendl_lo(BUFFER *b, long l);
       +long buf_getl(BUFFER *b);
       +long buf_getl_lo(BUFFER *b);
       +int buf_appendi(BUFFER *b, int i);
       +int buf_appendi_lo(BUFFER *b, int i);
       +int buf_geti(BUFFER *b);
       +int buf_geti_lo(BUFFER *b);
       +
       +/* String comparison */
       +int strieq(const char *s1, const char *s2);
       +int strileft(const char *string, const char *keyword);
       +int striright(const char *string, const char *keyword);
       +int strifind(const char *string, const char *keyword);
       +
       +int streq(const char *s1, const char *s2);
       +int strfind(const char *string, const char *keyword);
       +int strleft(const char *string, const char *keyword);
       +
       +void strcatn(char *dest, const char *src, int n);
       +
       +int bufleft(BUFFER *b, char *k);
       +int buffind(BUFFER *b, char *k);
       +int bufeq(BUFFER *b, char *k);
       +
       +int bufileft(BUFFER *b, char *k);
       +int bufifind(BUFFER *b, char *k);
       +int bufiright(BUFFER *b, char *k);
       +int bufieq(BUFFER *b, char *k);
       +
       +/* Utility functions */
       +void whoami(char *addr, char *defaultname);
       +int sendinfofile(char *name, char *log, BUFFER *address, BUFFER *subject);
       +int stats(BUFFER *out);
       +int conf(BUFFER *out);
       +void conf_premail(BUFFER *out);
       +
       +void rfc822_addr(BUFFER *line, BUFFER *list);
       +void rfc822_name(BUFFER *line, BUFFER *name);
       +void sendmail_begin(void);        /* begin mail sending session */
       +void sendmail_end(void);        /* end mail sending session */
       +int sendmail_loop(BUFFER *message, char *from, BUFFER *address);
       +int sendmail(BUFFER *message, char *from, BUFFER *address);
       +int mixfile(char *path, const char *name);
       +int file_to_out(const char *name);
       +FILE *mix_openfile(const char *name, const char *a);
       +FILE *openpipe(const char *prog);
       +int closepipe(FILE *fp);
       +int maildirWrite(char *maildir, BUFFER *message, int create);
       +int write_pidfile(char *pidfile);
       +int clear_pidfile(char *pidfile);
       +time_t parse_yearmonthday(char* str);
       +
       +int url_download(char* url, char* dest);
       +int download_stats(char *sourcename);
       +
       +typedef struct {
       +  char *name;
       +  FILE *f;
       +} LOCK;
       +
       +int lock(FILE *f);
       +int unlock(FILE *f);
       +LOCK *lockfile(char *filename);
       +int unlockfile(LOCK *lock);
       +
       +int filtermsg(BUFFER *msg);
       +BUFFER *readdestblk( );
       +int doblock(BUFFER *line, BUFFER *filter, int logandreset);
       +int doallow(BUFFER *line, BUFFER *filter);
       +int allowmessage(BUFFER *in);
       +
       +void errlog(int type, char *format,...);
       +void clienterr(BUFFER *msgbuf, char *err);
       +void logmail(char *mailbox, BUFFER *message);
       +
       +void mix_status(char *fmt,...);
       +void mix_genericerror(void);
       +
       +#define ERRORMSG 1
       +#define WARNING 2
       +#define NOTICE 3
       +#define LOG 4
       +#define DEBUGINFO 5
       +
       +int decode(BUFFER *in, BUFFER *out);
       +int encode(BUFFER *b, int linelen);
       +void id_encode(byte id[], byte *s);
       +void id_decode(byte *s, byte id[]);
       +
       +int decode_header(BUFFER *content);
       +int boundary(BUFFER *line, BUFFER *mboundary);
       +void get_parameter(BUFFER *content, char *attribute, BUFFER *value);
       +int get_type(BUFFER *content, BUFFER *type, BUFFER *subtype);
       +int mail_encode(BUFFER *in, int encoding);
       +int hdr_encode(BUFFER *in, int n);
       +int attachfile(BUFFER *message, BUFFER *filename);
       +int pgpmime_sign(BUFFER *message, BUFFER *uid, BUFFER *pass, char *secring);
       +int mime_attach(BUFFER *message, BUFFER *attachment, BUFFER *type);
       +void mimedecode(BUFFER *msg);
       +int qp_decode_message(BUFFER *msg);
       +
       +#define MIME_8BIT 1   /* transport is 8bit */
       +#define MIME_7BIT 2   /* transport is 7bit */
       +
       +/* randomness */
       +int rnd_bytes(byte *b, int n);
       +byte rnd_byte(void);
       +int rnd_number(int n);
       +int rnd_add(byte *b, int l);
       +int rnd_seed(void);
       +void rnd_time(void);
       +
       +int rnd_init(void);
       +int rnd_final(void);
       +void rnd_error(void);
       +
       +#define RND_QUERY 0
       +#define RND_NOTSEEDED -1
       +#define RND_SEEDED 1
       +#define RND_WILLSEED 2
       +extern int rnd_state; /* flag for PRNG status */
       +
       +/* compression */
       +int buf_compress(BUFFER *b);
       +int buf_zip(BUFFER *out, BUFFER *in, int bits);
       +int buf_uncompress(BUFFER *b);
       +int buf_unzip(BUFFER *b, int type);
       +
       +/* crypto functions */
       +int digest_md5(BUFFER *b, BUFFER *md);
       +int isdigest_md5(BUFFER *b, BUFFER *md);
       +int digestmem_md5(byte *b, int n, BUFFER *md);
       +int digest_sha1(BUFFER *b, BUFFER *md);
       +int digest_rmd160(BUFFER *b, BUFFER *md);
       +
       +#define KEY_ID_LEN 32
       +int keymgt(int force);
       +int key(BUFFER *b);
       +int adminkey(BUFFER *b);
       +
       +#define ENCRYPT 1
       +#define DECRYPT 0
       +int buf_crypt(BUFFER *b, BUFFER *key, BUFFER *iv, int enc);
       +
       +#ifdef USE_IDEA
       +int buf_ideacrypt(BUFFER *b, BUFFER *key, BUFFER *iv, int enc);
       +#endif /* USE_IDEA */
       +int buf_bfcrypt(BUFFER *b, BUFFER *key, BUFFER *iv, int enc);
       +int buf_3descrypt(BUFFER *b, BUFFER *key, BUFFER *iv, int enc);
       +int buf_castcrypt(BUFFER *b, BUFFER *key, BUFFER *iv, int enc);
       +#ifdef USE_AES
       +int buf_aescrypt(BUFFER *b, BUFFER *key, BUFFER *iv, int enc);
       +#endif /* USE_AES */
       +
       +int db_getseckey(byte keyid[], BUFFER *key);
       +int db_getpubkey(byte keyid[], BUFFER *key);
       +int pk_decrypt(BUFFER *encrypted, BUFFER *privkey);
       +int pk_encrypt(BUFFER *plaintext, BUFFER *privkey);
       +int check_seckey(BUFFER *buf, const byte id[]);
       +int check_pubkey(BUFFER *buf, const byte id[]);
       +int v2createkey(void);
       +int getv2seckey(byte keyid[], BUFFER *key);
       +int seckeytopub(BUFFER *pub, BUFFER *sec, byte keyid[]);
       +
       +/* configuration, general remailer functions */
       +int mix_configline(char *line);
       +int mix_config(void);
       +int mix_initialized(void);
       +int mix_daily(void);
       +
       +/* message pool */
       +#define INTERMEDIATE 0
       +int pool_send(void);
       +int pool_read(BUFFER *pool);
       +int pool_add(BUFFER *msg, char *type);
       +FILE *pool_new(char *type, char *tmpname, char *path);
       +int mix_pool(BUFFER *msg, int type, long latent);
       +int pool_packetfile(char *fname, BUFFER *mid, int packetnum);
       +void pool_packetexp(void);
       +int idexp(void);
       +int pgpmaxexp(void);
       +void pop3get(void);
       +
       +typedef struct {  /* added for binary id.log change */
       +  char id[16];
       +  long time;
       +} idlog_t;
       +
       +/* statistics */
       +int stats_log(int);
       +int stats_out(int);
       +
       +/* OpenPGP */
       +#define PGP_ARMOR_NORMAL        0
       +#define PGP_ARMOR_REM           1
       +#define PGP_ARMOR_KEY           2
       +#define PGP_ARMOR_NYMKEY        3
       +#define PGP_ARMOR_NYMSIG        4
       +#define PGP_ARMOR_SECKEY        5
       +
       +#define PGP_TYPE_UNDEFINED        0
       +#define PGP_TYPE_PRIVATE        1
       +#define PGP_TYPE_PUBLIC                2
       +
       +int pgp_keymgt(int force);
       +int pgp_latestkeys(BUFFER* outtxt, int algo);
       +int pgp_armor(BUFFER *buf, int mode);
       +int pgp_dearmor(BUFFER *buf, BUFFER *out);
       +int pgp_pubkeycert(BUFFER *userid, char *keyring, BUFFER *pass,
       +                   BUFFER *out, int remail);
       +int pgp_signtxt(BUFFER *msg, BUFFER *uid, BUFFER *pass,
       +                char *secring, int remail);
       +int pgp_isconventional(BUFFER *buf);
       +int pgp_mailenc(int mode, BUFFER *msg, char *sigid,
       +                BUFFER *pass, char *pubring, char *secring);
       +int pgp_signhashalgo(BUFFER *algo, BUFFER *userid, char *secring,
       +                     BUFFER *pass);
       +
       +/* menu */
       +int menu_initialized;
       +void menu_main(void);
       +void menu_folder(char command, char *name);
       +int menu_getuserpass(BUFFER *p, int mode);
       +
       +int user_pass(BUFFER *b);
       +int user_confirmpass(BUFFER *b);
       +void user_delpass(void);
       +
       +/* remailer */
       +typedef struct {
       +  char name[20];
       +  int version;
       +  char addr[128];
       +  byte keyid[16];
       +  struct {
       +    unsigned int mix:1;
       +    unsigned int compress:1;
       +
       +    unsigned int cpunk:1;
       +    unsigned int pgp:1;
       +    unsigned int pgponly:1;
       +    unsigned int latent:1;
       +    unsigned int hash:1;
       +    unsigned int ek:1;
       +    unsigned int esub:1;
       +
       +    unsigned int nym:1;
       +    unsigned int newnym:1;
       +
       +    unsigned int post:1;
       +    unsigned int middle:1;
       +
       +    unsigned int star_ex:1;
       +  } flags;
       +  struct rinfo {
       +    int reliability;
       +    int latency;
       +    char history[13];
       +  } info[2];
       +} REMAILER;
       +
       +#define CHAINMAX 421
       +#define MAXREM 100
       +int prepare_type2list(BUFFER *out);
       +int mix2_rlist(REMAILER remailer[], int badchains[MAXREM][MAXREM]);
       +int t1_rlist(REMAILER remailer[], int badchains[MAXREM][MAXREM]);
       +int pgp_rlist(REMAILER remailer[], int n);
       +int pgp_rkeylist(REMAILER remailer[], int keyid[], int n);
       +void parse_badchains(int badchains[MAXREM][MAXREM], char *file, char *startindicator, REMAILER *remailer, int maxrem);
       +int chain_select(int hop[], char *chainstr, int maxrem, REMAILER *remailer,
       +                 int type, BUFFER *feedback);
       +int chain_rand(REMAILER *remailer, int badchains[MAXREM][MAXREM], int maxrem,
       +               int thischain[], int chainlen, int t, int ignore_constraints_if_necessary);
       +int chain_randfinal(int type, REMAILER *remailer, int badchains[MAXREM][MAXREM],
       +               int maxrem, int rtype, int chain[], int chainlen, int ignore_constraints_if_necessary);
       +
       +float chain_reliability(char *chain, int chaintype,
       +                        char *reliability_string);
       +int redirect_message(BUFFER *sendmsg, char *chain, int numcopies, BUFFER *chainlist);
       +int mix2_encrypt(int type, BUFFER *message, char *chainstr, int numcopies,
       +                int ignore_constraints_if_necessary, BUFFER *feedback);
       +int t1_encrypt(int type, BUFFER *message, char *chainstr, int latency,
       +               BUFFER *ek, BUFFER *feedback);
       +
       +int t1_getreply(BUFFER *msg, BUFFER *ek, int len);
       +
       +int t1_decrypt(BUFFER *in);
       +int t2_decrypt(BUFFER *in);
       +
       +int mix2_decrypt(BUFFER *m);
       +int v2body(BUFFER *body);
       +int v2body_setlen(BUFFER *body);
       +int v2partial(BUFFER *body, BUFFER *mid, int packet, int numpackets);
       +int v2_merge(BUFFER *mid);
       +int mix_armor(BUFFER *in);
       +int mix_dearmor(BUFFER *armored, BUFFER *bin);
       +
       +/* type 1 */
       +#define HDRMARK "::"
       +#define EKMARK "**"
       +#define HASHMARK "##"
       +int isline(BUFFER *line, char *text);
       +
       +/* nym database */
       +
       +#define NYM_WAITING 0
       +#define NYM_OK 1
       +#define NYM_DELETED 2
       +#define NYM_ANY -1
       +
       +int nymlist_read(BUFFER *n);
       +int nymlist_write(BUFFER *list);
       +int nymlist_get(BUFFER *list, char *nym, BUFFER *config, BUFFER *ek,
       +                BUFFER *options, BUFFER *name, BUFFER *rblocks, int *status);
       +int nymlist_append(BUFFER *list, char *nym, BUFFER *config, BUFFER *options,
       +                   BUFFER *name, BUFFER *chains, BUFFER *eklist, int status);
       +int nymlist_del(BUFFER *list, char *nym);
       +int nymlist_getnym(char *nym, BUFFER *config, BUFFER *ek, BUFFER *opt,
       +                   BUFFER *name, BUFFER *rblocks);
       +int nymlist_getstatus(char *nym);
       +
       +/* Visual C lacks dirent */
       +#ifdef _MSC
       +typedef HANDLE DIR;
       +
       +struct dirent {
       +  char d_name[PATHMAX];
       +};
       +
       +DIR *opendir(const char *name);
       +struct dirent *readdir(DIR *dir);
       +int closedir(DIR *dir);
       +#endif /* _MSC */
       +
       +/* sockets */
       +#if defined(WIN32) && defined(USE_SOCK)
       +#include <winsock.h>
       +int sock_init(void);
       +void sock_exit(void);
       +
       +#else /* end of defined(WIN32) && defined(USE_SOCK) */
       +typedef int SOCKET;
       +
       +#define INVALID_SOCKET -1
       +SOCKET opensocket(char *hostname, int port);
       +int closesocket(SOCKET s);
       +
       +#endif /* else if not defined(WIN32) && defined(USE_SOCK) */
       +
       +#ifdef WIN32
       +int is_nt_service(void);
       +void set_nt_exit_event();
       +#endif /* WIN32 */
       +
       +/* check for memory leaks */
       +#ifdef DEBUG
       +#define malloc mix3_malloc
       +#define free mix3_free
       +BUFFER *mix3_bufnew(char *, int, char*);
       +#if __GNUC__ >= 2
       +# define buf_new() mix3_bufnew(__FILE__, __LINE__, __PRETTY_FUNCTION__)
       +#else /* end of __GNUC__ >= 2 */
       +# define buf_new() mix3_bufnew(__FILE__, __LINE__, "file")
       +#endif /* else if not __GNUC__ >= 2 */
       +#endif /* DEBUG */
       +
       +#endif /* not _MIX3_H */
   DIR diff --git a/Src/mixlib.def b/Src/mixlib.def
       t@@ -0,0 +1,121 @@
       +LIBRARY         MIXLIB
       +
       +DESCRIPTION     'Mixmaster MIXLIB.DLL - http://mixmaster.anonymizer.com'
       +
       +EXPORTS
       +    mix_init                          @1
       +    mix_exit                          @2
       +    buf_new                           @3
       +    buf_free                          @4
       +    buf_read                          @5
       +    buf_write                         @6
       +    mix_encrypt                       @7
       +    mix_decrypt                       @8
       +    mix_send                          @9
       +    mix_regular                      @10
       +;   nym_config                       @11
       +;   nym_encrypt                      @12
       +;   nym_decrypt                      @13
       +    t1_decrypt                       @14
       +    t2_decrypt                       @15
       +    mix_pool                         @16
       +    pgp_encrypt                      @17
       +    pgp_mailenc                      @18
       +    pgp_decrypt                      @19
       +    pgp_keygen                       @20
       +    buf_reset                        @21
       +    buf_clear                        @22
       +    buf_eq                           @23
       +    buf_append                       @24
       +    buf_appendc                      @25
       +    buf_appends                      @26
       +    buf_appendf                      @27
       +    buf_sets                         @28
       +    buf_nl                           @29
       +    buf_cat                          @30
       +    buf_rest                         @31
       +    buf_set                          @32
       +    buf_move                         @33
       +    buf_appendrnd                    @34
       +    buf_setrnd                       @35
       +    buf_appendzero                   @36
       +    buf_appendi                      @37
       +    buf_appendi_lo                   @38
       +    buf_appendl                      @39
       +    buf_appendl_lo                   @40
       +    buf_prepare                      @41
       +    buf_getc                         @42
       +    buf_geti                         @43
       +    buf_geti_lo                      @44
       +    buf_getl                         @45
       +    buf_getl_lo                      @46
       +    buf_ungetc                       @47
       +    buf_appendb                      @48
       +    buf_getb                         @49
       +    buf_getline                      @50
       +    buf_lookahead                    @51
       +    buf_chop                         @52
       +    buf_getheader                    @53
       +    buf_rewind                       @54
       +    rnd_init                         @55
       +    streq                            @56
       +    strieq                           @57
       +    strleft                          @58
       +    strileft                         @59
       +    strfind                          @60
       +    strifind                         @61
       +    rfc822_addr                      @62
       +    rfc822_name                      @63
       +    mixfile                          @64
       +    mix_daemon                       @65
       +    mix_openfile                     @66
       +    sendmail                         @67
       +    encode                           @68
       +    decode                           @69
       +    hdr_encode                       @70
       +    mail_encode                      @71
       +    id_encode                        @72
       +    id_decode                        @73
       +    errlog                           @74
       +    keymgt                           @75
       +    menu_folder                      @76
       +    user_pass                        @77
       +    pop3get                          @78
       +    mix_configline                   @79
       +    rnd_time                         @80
       +    rnd_add                          @81
       +    rnd_update                       @82
       +    pool_read                        @83
       +    bufieq                           @84
       +    buf_appendheader                 @85
       +    attachfile                       @86
       +    rnd_initialized                  @87
       +    rnd_mouse                        @88
       +    user_delpass                     @89
       +    strcatn                          @90
       +    file_to_out                      @91
       +    is_nt_service                    @92
       +    set_nt_exit_event                @93
       +    prepare_type2list                @94
       +    NYMSECRING                       @95
       +    pgp_dearmor                      @96
       +    pgp_armor                        @97
       +    pgp_compress                     @98
       +    pgp_literal                      @99
       +    PGPSECRING                      @100
       +    PGPPUBRING                      @101
       +    VERBOSE                         @102
       +    pgp_signtxt                     @103
       +    pool_add                        @104
       +    getv2seckey                     @105
       +    pgpdb_getkey                    @106
       +    ENTEREDPASSPHRASE               @107
       +    PASSPHRASE                      @108
       +    mix_config                      @109
       +    RATE                            @110
       +    SENDPOOLTIME                    @111
       +    CLIENTAUTOFLUSH                 @112
       +    redirect_message                @113
       +    mix_check_timeskew              @114
       +    MIXCONF                         @115
       +    menu_main                       @116
   DIR diff --git a/Src/mpgp.c b/Src/mpgp.c
       t@@ -0,0 +1,264 @@
       +/* mpgp -- (C) 2000 - 2006 Ulf Moeller and others.
       +
       +   mpgp may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Test application for OpenPGP features
       +   $Id: mpgp.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +#define MPGPVERSION "0.3.0"
       +
       +#include "mix3.h"
       +#include "pgp.h"
       +#include <stdlib.h>
       +#include <string.h>
       +#include <fcntl.h>
       +#include <assert.h>
       +#include <sys/types.h>
       +#include <sys/stat.h>
       +#include <time.h>
       +#include <fcntl.h>
       +#ifdef POSIX
       +#include <unistd.h>
       +#include <termios.h>
       +#endif /* POSIX */
       +
       +int pass(BUFFER *b)
       +{
       +  char p[LINELEN];
       +  int fd;
       +  int n;
       +
       +#ifdef HAVE_TERMIOS
       +  struct termios attr;
       +#endif /* HAVE_TERMIOS */
       +
       +  fprintf(stderr, "enter passphrase: ");
       +  fflush(stderr);
       +#ifdef HAVE_TERMIOS
       +  fd = open("/dev/tty", O_RDONLY);
       +  if (tcgetattr(fd, &attr) != 0)
       +    return (-1);
       +  attr.c_lflag &= ~ECHO;
       +  attr.c_lflag |= ICANON;
       +  if (tcsetattr(fd, TCSAFLUSH, &attr) != 0)
       +    return (-1);
       +  n = read(fd, p, LINELEN);
       +
       +  attr.c_lflag |= ECHO;
       +  if (tcsetattr(fd, TCSAFLUSH, &attr) != 0)
       +    return (-1);
       +  close(fd);
       +  p[n - 1] = 0;
       +
       +#else /* end of HAVE_TERMIOS */
       +  fgets(p, LINELEN, stdin);
       +  if (p[strlen(p)-1]=='\n')
       +    p[strlen(p)-1] = 0;
       +#endif /* else if not HAVE_TERMIOS */
       +
       +  fprintf(stderr, "\n");
       +  buf_appends(b, p);
       +  return (0);
       +}
       +
       +void usage(char *n)
       +{
       +  fprintf(stderr, "Usage: %s -e [-b] user@domain\n", n);
       +  fprintf(stderr, "       %s -s [-b] [yourname@domain]\n", n);
       +  fprintf(stderr, "       %s -c [-b]\n", n);
       +  fprintf(stderr, "       %s -C [-b]\n", n);
       +  fprintf(stderr, "       %s -d [passphrase]\n", n);
       +  fprintf(stderr, "       %s -g[r] yourname@domain [bits]\n", n);
       +  fprintf(stderr, "       %s -a[+-] [-b]\n", n);
       +  fprintf(stderr, "       %s -V\n\n", n);
       +  fprintf(stderr, "PGP public key ring: %s\n", PGPPUBRING);
       +  fprintf(stderr, "PGP secret key ring: %s\n", PGPSECRING);
       +}
       +
       +int decrypt(BUFFER *u, BUFFER *option, char *n)
       +{
       +  BUFFER *v;
       +  BUFFER *sig;
       +  int err = 0;
       +
       +  v = buf_new();
       +  sig = buf_new();
       +
       +  buf_set(v, u);
       +  err = pgp_decrypt(v, NULL, sig, PGPPUBRING, PGPSECRING);
       +  if (err >= 0 || err == PGP_SIGBAD)
       +    buf_move(u, v);
       +
       +  if (err == PGP_ERR) {
       +    pass(option);
       +    err = pgp_decrypt(u, option, sig, PGPPUBRING, PGPSECRING);
       +  }
       +  switch (err) {
       +  case PGP_NOMSG:
       +    fprintf(stderr, "%s: Not a PGP message.\n", n);
       +    break;
       +  case PGP_ERR:
       +    fprintf(stderr, "%s: Can't read message.\n", n);
       +    break;
       +  case PGP_SIGOK:
       +    fprintf(stderr, "%s: Valid signature: %s\n", n, sig->data);
       +    err = 0;
       +    break;
       +  case PGP_SIGNKEY:
       +    fprintf(stderr, "%s: Unknown signature key %s, cannot verify.\n", n, sig->data);
       +    err = 1;
       +    break;
       +  case PGP_SIGBAD:
       +    fprintf(stderr, "%s: Bad signature.\n", n);
       +    err = 1;
       +    break;
       +  }
       +
       +  buf_free(v);
       +  buf_free(sig);
       +
       +  return (err);
       +}
       +
       +int main(int argc, char *argv[])
       +{
       +  BUFFER *u, *option, *pp;
       +  char *filename = NULL;
       +  char *cmd = NULL;
       +  int text = 1;
       +  int err = 99;
       +  int bits = 0;
       +
       +  mix_init(NULL);
       +  VERBOSE = 3;
       +
       +  u = buf_new();
       +  option = buf_new();
       +  pp = buf_new();
       +
       +  if (argc > 1 && argv[1][0] == '-')
       +    cmd = argv[1];
       +
       +  if (argc == 1 || (cmd > 0 && (cmd[1] == 'e' || cmd[1] == 'c' ||
       +                                cmd[1] == 'd' || cmd[1] == 'a' ||
       +                                cmd[1] == 's' || cmd[1] == 'C'))) {
       +    if ((argc > 2 && (cmd == NULL || cmd[1] == 'a')) || argc > 3) {
       +      FILE *f;
       +
       +      f = fopen(argv[argc - 1], "rb");
       +      if (f == NULL) {
       +        fprintf(stderr, "%s: Can't open %s\n", argv[0], argv[argc - 1]);
       +        err = -1;
       +      } else {
       +        buf_read(u, f);
       +        fclose(f);
       +        filename = argv[argc - 1];
       +        argc--;
       +      }
       +    } else
       +      buf_read(u, stdin);
       +  }
       +  if (argc == 1)
       +    err = decrypt(u, option, argv[0]);
       +
       +  if (argc > 2 && argv[2][0] == '-' && argv[2][1] == 'b') {
       +    text = 0;
       +    if (argc > 3)
       +      buf_appends(option, argv[3]);
       +  } else if (argc > 2)
       +    buf_appends(option, argv[2]);
       +
       +  if (cmd)
       +    switch (cmd[1]) {
       +    case 's':
       +      err = pgp_encrypt(PGP_SIGN | (text ? PGP_TEXT : 0), u, NULL, option,
       +                        NULL, PGPPUBRING, PGPSECRING);
       +      if (err != 0) {
       +        pass(pp);
       +        err = pgp_encrypt(PGP_SIGN | (text ? PGP_TEXT : 0), u, NULL, option,
       +                          pp, PGPPUBRING, PGPSECRING);
       +      }
       +      if (err != 0)
       +        fprintf(stderr, "Error.\n");
       +      break;
       +    case 'e':
       +      if (option->length) {
       +        err = pgp_encrypt(PGP_ENCRYPT | (text ? PGP_TEXT : 0), u, option, NULL,
       +                          NULL, PGPPUBRING, PGPSECRING);
       +        if (err < 0)
       +          fprintf(stderr, "%s: can't encrypt message for %s\n",
       +                  argv[0], argv[2]);
       +      }
       +      break;
       +    case 'c':
       +      pass(option);
       +      err = pgp_encrypt(PGP_CONVENTIONAL | (text ? PGP_TEXT : 0), u, option,
       +                        NULL, NULL, PGPPUBRING, PGPSECRING);
       +      if (err < 0)
       +        fprintf(stderr, "%s: can't encrypt message\n", argv[0]);
       +      break;
       +    case 'C':
       +      pass(option);
       +      err = pgp_encrypt(PGP_NCONVENTIONAL | (text ? PGP_TEXT : 0), u, option,
       +                        NULL, NULL, PGPPUBRING, PGPSECRING);
       +      if (err < 0)
       +        fprintf(stderr, "%s: can't encrypt message\n", argv[0]);
       +      break;
       +    case 'g':
       +      if (argc < 3) {
       +        err = 99;
       +        goto end;
       +      }
       +      pass(pp);
       +      if (argc == 4)
       +        sscanf(argv[3], "%d", &bits);
       +      err = pgp_keygen(cmd[2] == 'r' ? PGP_ES_RSA : PGP_E_ELG,
       +                       bits, option, pp, PGPPUBRING, PGPSECRING, 0);
       +      break;
       +    case 'a':
       +      switch (cmd[2]) {
       +      case '-':
       +        err = pgp_dearmor(u, u);
       +        if (err == -1)
       +          fprintf(stderr, "Not a PGP-armored message\n");
       +        goto end;
       +      case '+':
       +        break;
       +      default:
       +        pgp_literal(u, filename, text);
       +        pgp_compress(u);
       +        break;
       +      }
       +      err = pgp_armor(u, PGP_ARMOR_NORMAL);
       +      break;
       +    case 'd':
       +      err = decrypt(u, option, argv[0]);
       +      break;
       +    case 'h':
       +      usage(argv[0]);
       +      err = 0;
       +      break;
       +    case 'V':
       +      fprintf(stderr, "mpgp version %s\n", MPGPVERSION);
       +      fprintf(stderr, "(C) 2000 - 2004 Ulf Moeller and others.\n");
       +      fprintf(stderr, "See the file COPYRIGHT for details.\n");
       +      err = 0;
       +      break;
       +    }
       +end:
       +  if (err == 99)
       +    usage(argv[0]);
       +
       +  if (err >= 0)
       +    buf_write(u, stdout);
       +
       +  buf_free(option);
       +  buf_free(pp);
       +  buf_free(u);
       +
       +  mix_exit();
       +  return (err == -1 ? 1 : err);
       +}
   DIR diff --git a/Src/nym.c b/Src/nym.c
       t@@ -0,0 +1,669 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Create nym server messages
       +   $Id: nym.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#ifdef NYMSUPPORT
       +
       +#include "mix3.h"
       +#include "pgp.h"
       +#include <string.h>
       +#include <time.h>
       +#include <assert.h>
       +
       +int nym_config(int mode, char *nym, char *nymserver, BUFFER *pseudonym,
       +               char *sendchain, int sendnumcopies, BUFFER *chains,
       +               BUFFER *options)
       +{
       +#ifndef USE_PGP
       +  return (-1);
       +#else /* end of not USE_PGP */
       +  REMAILER remailer[MAXREM];
       +  int badchains[MAXREM][MAXREM];
       +  KEYRING *r;
       +  int maxrem;
       +  int chain[20];
       +  char rchain[CHAINMAX];
       +  BUFFER *userid, *msg, *req, *k, *line, *ek, *eklist, *key, *pubkey, *out,
       +      *oldchains;
       +  int latency;
       +  int err = -1;
       +  int status;
       +  int desttype = MSG_MAIL;
       +  int rblock = 0;
       +  BUFFER *nymlist, *userpass, *config;
       +  LOCK *nymlock;
       +
       +  userid = buf_new();
       +  msg = buf_new();
       +  req = buf_new();
       +  k = buf_new();
       +  line = buf_new();
       +  ek = buf_new();
       +  eklist = buf_new();
       +  key = buf_new();
       +  pubkey = buf_new();
       +  out = buf_new();
       +  config = buf_new();
       +  nymlist = buf_new();
       +  userpass = buf_new();
       +  oldchains = buf_new();
       +
       +  for (;;) {
       +    user_pass(userpass);
       +    if (user_confirmpass(userpass))
       +      break;
       +    user_delpass();
       +  }
       +
       +  if (nymserver) {
       +    maxrem = t1_rlist(remailer, badchains);
       +    if (maxrem < 1)
       +      return (-1);
       +    if (chain_select(chain, nymserver, maxrem, remailer, 2, NULL) != 1)
       +      return (-1);
       +    if (chain[0] == 0)
       +      chain[0] = chain_randfinal(MSG_MAIL, remailer, badchains, maxrem, 2, NULL, -1);
       +    if (chain[0] == -1)
       +      return (-1);
       +    assert(strchr(nym, '@') == NULL && strchr(remailer[chain[0]].addr, '@'));
       +    strcatn(nym, strchr(remailer[chain[0]].addr, '@'), LINELEN);
       +    buf_appends(config, remailer[chain[0]].addr);
       +  } else
       +    assert(strchr(nym, '@') != NULL);
       +
       +  status = nymlist_getnym(nym, config->length ? NULL : config, eklist, NULL,
       +                          NULL, oldchains);
       +  if (mode == NYM_CREATE && status == NYM_OK)
       +    mode = NYM_MODIFY;
       +
       +  buf_appendc(userid, '<');
       +  buf_appends(userid, nym);
       +  buf_appendc(userid, '>');
       +
       +  buf_sets(req, "Config:\nFrom: ");
       +  buf_append(req, nym, strchr(nym, '@') - nym);
       +  buf_appends(req, "\nNym-Commands:");
       +  if (mode == NYM_CREATE)
       +    buf_appends(req, " create?");
       +  if (mode == NYM_DELETE)
       +    buf_appends(req, " delete");
       +  else {
       +    if (options && options->length > 0) {
       +      if (!bufleft(options, " "))
       +        buf_appendc(req, ' ');
       +      buf_cat(req, options);
       +    }
       +    if (pseudonym && pseudonym->length > 0) {
       +      buf_appends(req, " name=\"");
       +      buf_cat(req, pseudonym);
       +      buf_appendc(req, '\"');
       +    }
       +  }
       +  buf_nl(req);
       +  if (mode == NYM_CREATE) {
       +    buf_appends(req, "Public-Key:\n");
       +
       +  getkey:
       +    r = pgpdb_open(NYMSECRING, userpass, 0, PGP_TYPE_PRIVATE);
       +    if (r == NULL) {
       +      err = -3;
       +      goto end;
       +    }
       +    if (r->filetype == -1)
       +      r->filetype = 0;
       +
       +    while (pgpdb_getnext(r, key, NULL, userid) != -1)
       +      if (pgp_makepubkey(key, NULL, pubkey, userpass, 0) == 0)
       +        err = 0;
       +    pgpdb_close(r);
       +    if (err != 0) {
       +      if (err == -2)
       +        goto end;
       +      err = -2;
       +      if (pseudonym && pseudonym->length) {
       +        buf_set(userid, pseudonym);
       +        buf_appendc(userid, ' ');
       +      } else
       +        buf_clear(userid);
       +      buf_appendf(userid, "<%s>", nym);
       +      pgp_keygen(PGP_ES_RSA, 0, userid, userpass, NULL, NYMSECRING, 2);
       +      goto getkey;
       +    }
       +    pgp_armor(pubkey, PGP_ARMOR_NYMKEY);
       +    buf_cat(req, pubkey);
       +  }
       +  if (mode != NYM_DELETE) {
       +    if (nymlist_read(nymlist) == -1) {
       +      user_delpass();
       +      err = -1;
       +      goto end;
       +    }
       +    if (chains)
       +      for (;;) {
       +        err = buf_getheader(chains, k, line);
       +        if (err == -1 && rblock == 0)
       +          break;
       +        if (err != 0 && rblock == 1) {
       +          buf_setrnd(ek, 16);
       +          if (t1_encrypt(desttype, msg, rchain, latency, ek, NULL) != 0) {
       +            err = -2;
       +            goto end;
       +          }
       +          encode(ek, 0);
       +          buf_cat(eklist, ek);
       +          buf_nl(eklist);
       +          buf_appends(req, "Reply-Block:\n");
       +          buf_cat(req, msg);
       +          buf_clear(msg);
       +          rblock = 0;
       +          continue;
       +        }
       +        if (bufieq(k, "Chain"))
       +          strncpy(rchain, line->data, sizeof(rchain));
       +        else if (bufieq(k, "Latency"))
       +          sscanf(line->data, "%d", &latency);
       +        else if (bufieq(k, "Null"))
       +          desttype = MSG_NULL, rblock = 1;
       +        else {
       +          buf_appendheader(msg, k, line);
       +          if (bufieq(k, "To"))
       +            desttype = MSG_MAIL, rblock = 1;
       +          if (bufieq(k, "Newsgroups"))
       +            desttype = MSG_POST, rblock = 1;
       +        }
       +      }
       +  }
       +  nymlock = lockfile(NYMDB);
       +  if (nymlist_read(nymlist) == 0) {
       +    nymlist_del(nymlist, nym);
       +    nymlist_append(nymlist, nym, config, options, pseudonym,
       +                   chains ? chains : oldchains, eklist,
       +                   mode == NYM_DELETE ? NYM_DELETED :
       +                   (status == -1 ? NYM_WAITING : status));
       +    nymlist_write(nymlist);
       +  } else
       +    err = -1;
       +  unlockfile(nymlock);
       +
       +#ifdef DEBUG
       +  buf_write(req, stderr);
       +#endif /* DEBUG */
       +  buf_clear(line);
       +  buf_appendc(line, '<');
       +  buf_cat(line, config);
       +  buf_appendc(line, '>');
       +
       +  err = pgp_encrypt(PGP_ENCRYPT | PGP_SIGN | PGP_TEXT | PGP_REMAIL,
       +                    req, line, userid, userpass, NULL, NYMSECRING);
       +  if (err != 0)
       +    goto end;
       +#ifdef DEBUG
       +  buf_write(req, stderr);
       +#endif /* DEBUG */
       +  buf_sets(out, "To: ");
       +  buf_cat(out, config);
       +  buf_nl(out);
       +  buf_nl(out);
       +  buf_cat(out, req);
       +
       +  err = mix_encrypt(desttype, out, sendchain, sendnumcopies, line);
       +  if (err)
       +    mix_status("%s\n", line->data);
       +
       +end:
       +  if (strchr(nym, '@')) *strchr(nym, '@') = '\0';
       +  buf_free(userid);
       +  buf_free(msg);
       +  buf_free(req);
       +  buf_free(k);
       +  buf_free(line);
       +  buf_free(ek);
       +  buf_free(eklist);
       +  buf_free(key);
       +  buf_free(pubkey);
       +  buf_free(out);
       +  buf_free(nymlist);
       +  buf_free(userpass);
       +  buf_free(oldchains);
       +  buf_free(config);
       +  return (err);
       +#endif /* else if USE_PGP */
       +}
       +
       +int nym_encrypt(BUFFER *msg, char *nym, int type)
       +{
       +#ifndef USE_PGP
       +  return (-1);
       +#else /* end of not USE_PGP */
       +  BUFFER *out, *userpass, *sig, *config;
       +  int err = -1;
       +
       +  out = buf_new();
       +  userpass = buf_new();
       +  sig = buf_new();
       +  config = buf_new();
       +
       +  if (nymlist_getnym(nym, config, NULL, NULL, NULL, NULL) == NYM_OK) {
       +    buf_appends(out, "From: ");
       +    buf_append(out, nym, strchr(nym, '@') - nym);
       +    buf_nl(out);
       +    if (type == MSG_POST) {
       +      buf_appends(out, "To: ");
       +      buf_appends(out, MAILtoNEWS);
       +      buf_nl(out);
       +    }
       +    buf_cat(out, msg);
       +    mail_encode(out, 0);
       +    buf_appendc(sig, '<');
       +    buf_appends(sig, nym);
       +    buf_appendc(sig, '>');
       +#ifdef DEBUG
       +    buf_write(out, stderr);
       +#endif /* DEBUG */
       +    user_pass(userpass);
       +    err = pgp_encrypt(PGP_ENCRYPT | PGP_SIGN | PGP_TEXT | PGP_REMAIL,
       +                      out, config, sig, userpass, NULL, NYMSECRING);
       +    if (err == 0) {
       +      buf_clear(msg);
       +      buf_appends(msg, "To: send");
       +      buf_appends(msg, strchr(nym, '@'));
       +      buf_nl(msg);
       +      buf_nl(msg);
       +      buf_cat(msg, out);
       +    }
       +  }
       +  buf_free(out);
       +  buf_free(config);
       +  buf_free(userpass);
       +  buf_free(sig);
       +  return (err);
       +#endif /* else if USE_PGP */
       +}
       +
       +int nym_decrypt(BUFFER *msg, char *thisnym, BUFFER *log)
       +{
       +#ifndef USE_PGP
       +  return (-1);
       +#else /* end of not USE_PGP */
       +  BUFFER *pgpmsg, *out, *line;
       +  BUFFER *nymlist, *userpass;
       +  BUFFER *decr, *sig, *mid;
       +  BUFFER *name, *rblocks, *eklist, *config;
       +  int decrypted = 0;
       +  int err = 1;
       +  long ptr;
       +  char nym[LINELEN];
       +  BUFFER *ek, *opt;
       +  int status;
       +  LOCK *nymlock;
       +  time_t t;
       +  struct tm *tc;
       +  char timeline[LINELEN];
       +
       +  pgpmsg = buf_new();
       +  out = buf_new();
       +  line = buf_new();
       +  nymlist = buf_new();
       +  userpass = buf_new();
       +  config = buf_new();
       +  ek = buf_new();
       +  decr = buf_new();
       +  sig = buf_new();
       +  mid = buf_new();
       +  opt = buf_new();
       +  name = buf_new();
       +  rblocks = buf_new();
       +  eklist = buf_new();
       +
       +  if (thisnym)
       +    thisnym[0] = '\0';
       +  while ((ptr = msg->ptr, err = buf_getline(msg, line)) != -1) {
       +    if (bufleft(line, begin_pgpmsg)) {
       +      err = -1;
       +      msg->ptr = ptr;
       +      pgp_dearmor(msg, pgpmsg);
       +      if (pgp_isconventional(pgpmsg)) {
       +        user_pass(userpass);
       +        nymlock = lockfile(NYMDB);
       +        if (nymlist_read(nymlist) == -1)
       +          user_delpass();
       +        while (nymlist_get(nymlist, nym, config, eklist, opt, name,
       +                           rblocks, &status) >= 0) {
       +          while (buf_getline(eklist, ek) == 0) {
       +            decode(ek, ek);
       +            if (t1_getreply(pgpmsg, ek, 20) == 0) {
       +              buf_clear(out);
       +              err = pgp_decrypt(pgpmsg, userpass, sig, NULL,
       +                                NYMSECRING);
       +              buf_sets(out, "From nymserver ");
       +              if (strchr(sig->data, '[') && strchr(sig->data, ']'))
       +                buf_append(out, strchr(sig->data, '[') + 1,
       +                           strchr(sig->data, ']') -
       +                           strchr(sig->data, '[') - 1);
       +              else {
       +                t = time(NULL);
       +                tc = localtime(&t);
       +                strftime(timeline, LINELEN, "%a %b %d %H:%M:%S %Y", tc);
       +                buf_appends(out, timeline);
       +              }
       +              buf_nl(out);
       +              if (err == PGP_SIGOK &&
       +                  bufifind(sig, config->data)) {
       +                buf_appends(out, "Nym: ");
       +                if (status == NYM_WAITING)
       +                  buf_appends(out, "confirm ");
       +                buf_appends(out, nym);
       +                buf_nl(out);
       +                if (thisnym && status == NYM_OK)
       +                  strncpy(thisnym, nym, LINELEN);
       +              } else
       +                buf_appends(out, "Warning: Signature verification failed!\n");
       +              buf_cat(out, pgpmsg);
       +              decrypted = 2;
       +              if (log) {
       +                digest_md5(out, mid);
       +                encode(mid, 0);
       +                if (buffind(log, mid->data)) {
       +                  decrypted = -1;
       +                  unlockfile(nymlock);
       +                  goto end;
       +                } else {
       +                  buf_cat(log, mid);
       +                  buf_nl(log);
       +                }
       +              }
       +              if (status == NYM_WAITING) {
       +                nymlist_del(nymlist, nym);
       +                nymlist_append(nymlist, nym, config, opt,
       +                               name, rblocks, eklist, NYM_OK);
       +              }
       +              break;
       +            }
       +          }
       +        }
       +        nymlist_write(nymlist);
       +        unlockfile(nymlock);
       +      }
       +      if (decrypted == 0) {
       +        user_pass(userpass);
       +        err = pgp_decrypt(pgpmsg, userpass, sig, PGPPUBRING, PGPSECRING);
       +        if (err == PGP_ERR)
       +          err = pgp_decrypt(pgpmsg, userpass, sig, PGPPUBRING,
       +                            NYMSECRING);
       +#if 0
       +        if (err == PGP_PASS || err == PGP_ERR)
       +          user_delpass();
       +#endif /* 0 */
       +        if (err != PGP_ERR && err != PGP_PASS && err != PGP_NOMSG &&
       +            err != PGP_NODATA) {
       +          buf_appends(out, info_beginpgp);
       +          if (err == PGP_SIGOK)
       +            buf_appendf(out, " (SIGNED)\n%s%b", info_pgpsig, sig);
       +          buf_nl(out);
       +          buf_cat(out, pgpmsg);
       +          buf_appends(out, info_endpgp);
       +          buf_nl(out);
       +          decrypted = 1;
       +        }
       +      }
       +      if (decrypted == 0) {
       +        buf_cat(out, line);
       +        buf_nl(out);
       +      }
       +    } else {
       +      if (bufileft(line, info_beginpgp))
       +          buf_appendc(out, ' '); /* escape info line in text */
       +      buf_cat(out, line);
       +      buf_nl(out);
       +    }
       +  }
       +
       +  if (decrypted)
       +    buf_move(msg, out);
       +  else
       +    buf_rewind(msg);
       +  if (decrypted == 2)
       +    nym_decrypt(msg, thisnym, NULL);
       +end:
       +  buf_free(pgpmsg);
       +  buf_free(out);
       +  buf_free(line);
       +  buf_free(decr);
       +  buf_free(sig);
       +  buf_free(mid);
       +  buf_free(opt);
       +  buf_free(name);
       +  buf_free(config);
       +  buf_free(rblocks);
       +  buf_free(eklist);
       +  buf_free(nymlist);
       +  buf_free(userpass);
       +  buf_free(ek);
       +  return (decrypted);
       +#endif /* else if USE_PGP */
       +}
       +
       +int nymlist_read(BUFFER *list)
       +{
       +#ifdef USE_PGP
       +  BUFFER *key;
       +
       +#endif /* USE_PGP */
       +  FILE *f;
       +  int err = 0;
       +
       +  buf_clear(list);
       +  f = mix_openfile(NYMDB, "rb");
       +  if (f != NULL) {
       +    buf_read(list, f);
       +    fclose(f);
       +#ifdef USE_PGP
       +    key = buf_new();
       +    user_pass(key);
       +    if (key->length)
       +      if (pgp_decrypt(list, key, NULL, NULL, NULL) < 0) {
       +        buf_clear(list);
       +        err = -1;
       +      }
       +    buf_free(key);
       +#endif /* USE_PGP */
       +  }
       +  return (err);
       +}
       +
       +int nymlist_write(BUFFER *list)
       +{
       +#ifdef USE_PGP
       +  BUFFER *key;
       +
       +#endif /* USE_PGP */
       +  FILE *f;
       +
       +  if (list->length == 0)
       +    return (-1);
       +
       +#ifdef USE_PGP
       +  key = buf_new();
       +  user_pass(key);
       +  if (key->length)
       +    pgp_encrypt(PGP_NCONVENTIONAL | PGP_NOARMOR, list, key, NULL, NULL, NULL,
       +                NULL);
       +  buf_free(key);
       +#endif /* USE_PGP */
       +  f = mix_openfile(NYMDB, "wb");
       +  if (f == NULL)
       +    return (-1);
       +  else {
       +    buf_write(list, f);
       +    fclose(f);
       +  }
       +  return (0);
       +}
       +
       +int nymlist_get(BUFFER *list, char *nym, BUFFER *config, BUFFER *ek,
       +                BUFFER *opt, BUFFER *name, BUFFER *chains, int *status)
       +{
       +  BUFFER *line;
       +  int err = -1;
       +
       +  line = buf_new();
       +  if (ek)
       +    buf_clear(ek);
       +  if (opt)
       +    buf_clear(opt);
       +  if (name)
       +    buf_clear(name);
       +  if (chains)
       +    buf_clear(chains);
       +  if (config)
       +    buf_clear(config);
       +
       +  for (;;) {
       +    if (buf_getline(list, line) == -1)
       +      goto end;
       +    if (bufleft(line, "nym="))
       +      break;
       +  }
       +  strncpy(nym, line->data + 4, LINELEN);
       +
       +  for (;;) {
       +    if (buf_getline(list, line) == -1)
       +      break;
       +    if (opt && bufleft(line, "opt="))
       +      line->ptr = 4, buf_rest(opt, line);
       +    if (name && bufleft(line, "name="))
       +      line->ptr = 5, buf_rest(name, line);
       +    if (config && bufleft(line, "config="))
       +      line->ptr = 7, buf_rest(config, line);
       +    if (bufeq(line, "ek=")) {
       +      while (buf_getline(list, line) == 0 && !bufeq(line, "end ek"))
       +        if (ek) {
       +          buf_cat(ek, line);
       +          buf_nl(ek);
       +        }
       +    }
       +    if (bufeq(line, "chains=")) {
       +      while (buf_getline(list, line) == 0 && !bufeq(line, "end chains"))
       +        if (chains) {
       +          buf_cat(chains, line);
       +          buf_nl(chains);
       +        }
       +    }
       +    if (status && bufleft(line, "status="))
       +      *status = line->data[7] - '0';
       +    if (bufeq(line, "end")) {
       +      err = 0;
       +      break;
       +    }
       +  }
       +end:
       +  buf_free(line);
       +  return (err);
       +}
       +
       +int nymlist_append(BUFFER *list, char *nym, BUFFER *config, BUFFER *opt,
       +                   BUFFER *name, BUFFER *rblocks, BUFFER *eklist, int status)
       +{
       +  buf_appends(list, "nym=");
       +  buf_appends(list, nym);
       +  buf_nl(list);
       +  buf_appends(list, "config=");
       +  buf_cat(list, config);
       +  buf_nl(list);
       +  buf_appends(list, "status=");
       +  buf_appendc(list, (byte) (status + '0'));
       +  buf_nl(list);
       +  if (name) {
       +    buf_appends(list, "name=");
       +    buf_cat(list, name);
       +    buf_nl(list);
       +  }
       +  buf_appends(list, "opt=");
       +  buf_cat(list, opt);
       +  buf_nl(list);
       +  buf_appends(list, "chains=\n");
       +  buf_cat(list, rblocks);
       +  buf_appends(list, "end chains\n");
       +  buf_appends(list, "ek=\n");
       +  buf_cat(list, eklist);
       +  buf_appends(list, "end ek\n");
       +  buf_appends(list, "end\n");
       +  return (0);
       +}
       +
       +int nymlist_del(BUFFER *list, char *nym)
       +{
       +  BUFFER *new;
       +  char thisnym[LINELEN];
       +  BUFFER *config, *ek, *name, *rblocks, *opt;
       +  int thisstatus;
       +
       +  new = buf_new();
       +  config = buf_new();
       +  ek = buf_new();
       +  name = buf_new();
       +  rblocks = buf_new();
       +  opt = buf_new();
       +
       +  buf_rewind(list);
       +  while (nymlist_get(list, thisnym, config, ek, opt, name, rblocks,
       +                     &thisstatus) >= 0)
       +    if (!streq(nym, thisnym))
       +      nymlist_append(new, thisnym, config, opt, name, rblocks, ek,
       +                     thisstatus);
       +
       +  buf_move(list, new);
       +  buf_free(new);
       +  buf_free(name);
       +  buf_free(opt);
       +  buf_free(rblocks);
       +  buf_free(config);
       +  buf_free(ek);
       +  return (0);
       +}
       +
       +int nymlist_getnym(char *nym, BUFFER *config, BUFFER *ek, BUFFER *opt,
       +                   BUFFER *name, BUFFER *rblocks)
       +     /* "nym@nymserver.domain" or "nym@" */
       +{
       +  BUFFER *nymlist, *userpass;
       +  char n[LINELEN];
       +  int err = -1;
       +  int status;
       +
       +  nymlist = buf_new();
       +  userpass = buf_new();
       +
       +  user_pass(userpass);
       +  if (nymlist_read(nymlist) != -1) {
       +    while (nymlist_get(nymlist, n, config, ek, opt, name, rblocks,
       +                       &status) >= 0)
       +      if (streq(nym, n) || (nym[strlen(nym) - 1] == '@' && strleft(n, nym))) {
       +        err = status;
       +        strncpy(nym, n, LINELEN);
       +        break;
       +      }
       +  }
       +  buf_free(userpass);
       +  buf_free(nymlist);
       +  return (err);
       +}
       +
       +int nymlist_getstatus(char *nym)
       +{
       +  int status;
       +
       +  if ((status = nymlist_getnym(nym, NULL, NULL, NULL, NULL, NULL)) == 0)
       +    return (status);
       +  else
       +    return (-1);
       +}
       +
       +#endif /* NYMSUPPORT */
   DIR diff --git a/Src/parsedate.y b/Src/parsedate.y
       t@@ -0,0 +1,879 @@
       +%{
       +/*  $Id: parsedate.y 647 2003-10-25 23:34:13Z weasel $
       +**
       +**  Originally written by Steven M. Bellovin <smb@research.att.com> while
       +**  at the University of North Carolina at Chapel Hill.  Later tweaked by
       +**  a couple of people on Usenet.  Completely overhauled by Rich $alz
       +**  <rsalz@osf.org> and Jim Berets <jberets@bbn.com> in August, 1990.
       +**  Further revised (removed obsolete constructs and cleaned up timezone
       +**  names) in August, 1991, by Rich.  Paul Eggert <eggert@twinsun.com>
       +**  helped in September, 1992.
       +**
       +**  This grammar has six shift/reduce conflicts.
       +**
       +**  This code is in the public domain and has no copyright.
       +*/
       +
       +#include <stdio.h>
       +#include <string.h>
       +
       +// #include "config.h"
       +// #include "clibrary.h"
       +#include <ctype.h>
       +
       +#if defined(_HPUX_SOURCE)
       +# include <alloca.h>
       +#endif
       +
       +#ifdef TM_IN_SYS_TIME
       +# include <sys/time.h>
       +#else
       +# include <time.h>
       +#endif
       +
       +// #include "libinn.h"
       +
       +/* Used for iterating through arrays.  ARRAY_SIZE returns the number of
       +   elements in the array (useful for a < upper bound in a for loop) and
       +   ARRAY_END returns a pointer to the element past the end (ISO C99 makes it
       +   legal to refer to such a pointer as long as it's never dereferenced). */
       +#define ARRAY_SIZE(array)       (sizeof(array) / sizeof((array)[0]))
       +#define ARRAY_END(array)        (&(array)[ARRAY_SIZE(array)])
       +
       +/* On some systems, the macros defined by <ctype.h> are only vaild on ASCII
       +   characters (those characters that isascii() says are ASCII).  This comes
       +   into play when applying <ctype.h> macros to eight-bit data.  autoconf
       +   checks for this with as part of AC_HEADER_STDC, so if autoconf doesn't
       +   think our headers are standard, check isascii() first. */
       +#if STDC_HEADERS
       +# define CTYPE(isXXXXX, c) (isXXXXX((unsigned char)(c)))
       +#else
       +# define CTYPE(isXXXXX, c) \
       +    (isascii((unsigned char)(c)) && isXXXXX((unsigned char)(c)))
       +#endif
       +
       +
       +#define yylhs                date_yylhs
       +#define yylen                date_yylen
       +#define yydefred        date_yydefred
       +#define yydgoto                date_yydgoto
       +#define yysindex        date_yysindex
       +#define yyrindex        date_yyrindex
       +#define yygindex        date_yygindex
       +#define yytable                date_yytable
       +#define yycheck                date_yycheck
       +#define yyparse                date_parse
       +#define yylex                date_lex
       +#define yyerror                date_error
       +#define yymaxdepth        date_yymaxdepth
       +
       +
       +static int date_lex(void);
       +
       +
       +    /* See the LeapYears table in Convert. */
       +#define EPOCH                1970
       +#define END_OF_TIME        2038
       +    /* Constants for general time calculations. */
       +#define DST_OFFSET        1
       +#define SECSPERDAY        (24L * 60L * 60L)
       +    /* Readability for TABLE stuff. */
       +#define HOUR(x)                (x * 60)
       +
       +#define LPAREN                '('
       +#define RPAREN                ')'
       +#define IS7BIT(x)        ((unsigned int)(x) < 0200)
       +
       +
       +/*
       +**  An entry in the lexical lookup table.
       +*/
       +typedef struct _TABLE {
       +    const char * name;
       +    int          type;
       +    time_t       value;
       +} TABLE;
       +
       +/*
       +**  Daylight-savings mode:  on, off, or not yet known.
       +*/
       +typedef enum _DSTMODE {
       +    DSTon, DSToff, DSTmaybe
       +} DSTMODE;
       +
       +/*
       +**  Meridian:  am, pm, or 24-hour style.
       +*/
       +typedef enum _MERIDIAN {
       +    MERam, MERpm, MER24
       +} MERIDIAN;
       +
       +
       +/*
       +**  Global variables.  We could get rid of most of them by using a yacc
       +**  union, but this is more efficient.  (This routine predates the
       +**  yacc %union construct.)
       +*/
       +static char        *yyInput;
       +static DSTMODE        yyDSTmode;
       +static int        yyHaveDate;
       +static int        yyHaveRel;
       +static int        yyHaveTime;
       +static time_t        yyTimezone;
       +static time_t        yyDay;
       +static time_t        yyHour;
       +static time_t        yyMinutes;
       +static time_t        yyMonth;
       +static time_t        yySeconds;
       +static time_t        yyYear;
       +static MERIDIAN        yyMeridian;
       +static time_t        yyRelMonth;
       +static time_t        yyRelSeconds;
       +
       +
       +/* extern struct tm        *localtime(); */
       +
       +static void                date_error(const char *s);
       +%}
       +
       +%union {
       +    time_t                Number;
       +    enum _MERIDIAN        Meridian;
       +}
       +
       +%token        tDAY tDAYZONE tMERIDIAN tMONTH tMONTH_UNIT tSEC_UNIT tSNUMBER
       +%token        tUNUMBER tZONE
       +
       +%type        <Number>        tDAYZONE tMONTH tMONTH_UNIT tSEC_UNIT
       +%type        <Number>        tSNUMBER tUNUMBER tZONE numzone zone
       +%type        <Meridian>        tMERIDIAN o_merid
       +
       +%%
       +
       +spec        : /* NULL */
       +        | spec item
       +        ;
       +
       +item        : time {
       +            yyHaveTime++;
       +#if        defined(lint)
       +            /* I am compulsive about lint natterings... */
       +            if (yyHaveTime == -1) {
       +                YYERROR;
       +            }
       +#endif        /* defined(lint) */
       +        }
       +        | time zone {
       +            yyHaveTime++;
       +            yyTimezone = $2;
       +        }
       +        | date {
       +            yyHaveDate++;
       +        }
       +        | rel {
       +            yyHaveRel = 1;
       +        }
       +        ;
       +
       +time        : tUNUMBER o_merid {
       +            if ($1 < 100) {
       +                yyHour = $1;
       +                yyMinutes = 0;
       +            }
       +            else {
       +                yyHour = $1 / 100;
       +                yyMinutes = $1 % 100;
       +            }
       +            yySeconds = 0;
       +            yyMeridian = $2;
       +        }
       +        | tUNUMBER ':' tUNUMBER o_merid {
       +            yyHour = $1;
       +            yyMinutes = $3;
       +            yySeconds = 0;
       +            yyMeridian = $4;
       +        }
       +        | tUNUMBER ':' tUNUMBER numzone {
       +            yyHour = $1;
       +            yyMinutes = $3;
       +            yyTimezone = $4;
       +            yyMeridian = MER24;
       +            yyDSTmode = DSToff;
       +        }
       +        | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
       +            yyHour = $1;
       +            yyMinutes = $3;
       +            yySeconds = $5;
       +            yyMeridian = $6;
       +        }
       +        | tUNUMBER ':' tUNUMBER ':' tUNUMBER numzone {
       +            yyHour = $1;
       +            yyMinutes = $3;
       +            yySeconds = $5;
       +            yyTimezone = $6;
       +            yyMeridian = MER24;
       +            yyDSTmode = DSToff;
       +        }
       +        ;
       +
       +zone        : tZONE {
       +            $$ = $1;
       +            yyDSTmode = DSToff;
       +        }
       +        | tDAYZONE {
       +            $$ = $1;
       +            yyDSTmode = DSTon;
       +        }
       +        | tZONE numzone {
       +            /* Only allow "GMT+300" and "GMT-0800" */
       +            if ($1 != 0) {
       +                YYABORT;
       +            }
       +            $$ = $2;
       +            yyDSTmode = DSToff;
       +        }
       +        | numzone {
       +            $$ = $1;
       +            yyDSTmode = DSToff;
       +        }
       +        ;
       +
       +numzone        : tSNUMBER {
       +            int                i;
       +
       +            /* Unix and GMT and numeric timezones -- a little confusing. */
       +            if ($1 < 0) {
       +                /* Don't work with negative modulus. */
       +                $1 = -$1;
       +                if ($1 > 9999 || (i = $1 % 100) >= 60) {
       +                    YYABORT;
       +                }
       +                $$ = ($1 / 100) * 60 + i;
       +            }
       +            else {
       +                if ($1 > 9999 || (i = $1 % 100) >= 60) {
       +                    YYABORT;
       +                }
       +                $$ = -(($1 / 100) * 60 + i);
       +            }
       +        }
       +        ;
       +
       +date        : tUNUMBER '/' tUNUMBER {
       +            yyMonth = $1;
       +            yyDay = $3;
       +        }
       +        | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
       +            if ($1 > 100) {
       +                /* assume YYYY/MM/DD format, so need not to add 1900 */
       +                if ($1 > 999) {
       +                    yyYear = $1;
       +                } else {
       +                    yyYear = 1900 + $1;
       +                }
       +                yyMonth = $3;
       +                yyDay = $5;
       +            }
       +            else {
       +                /* assume MM/DD/YY* format */
       +                yyMonth = $1;
       +                yyDay = $3;
       +                if ($5 > 999) {
       +                    /* assume year is YYYY format, so need not to add 1900 */
       +                    yyYear = $5;
       +                } else if ($5 < 100) {
       +                    /* assume year is YY format, so need to add 1900 */
       +                    yyYear = $5 + (yyYear / 100 + (yyYear % 100 - $5) / 50) * 100;
       +                } else {
       +                    yyYear = 1900 + $5;
       +                }
       +            }
       +        }
       +        | tMONTH tUNUMBER {
       +            yyMonth = $1;
       +            yyDay = $2;
       +        }
       +        | tMONTH tUNUMBER ',' tUNUMBER {
       +            yyMonth = $1;
       +            yyDay = $2;
       +            if ($4 > 999) {
       +                /* assume year is YYYY format, so need not to add 1900 */
       +                yyYear = $4;
       +            } else if ($4 < 100) {
       +                /* assume year is YY format, so need to add 1900 */
       +                yyYear = $4 + (yyYear / 100 + (yyYear % 100 - $4) / 50) * 100;
       +            } else {
       +                yyYear = 1900 + $4;
       +            }
       +        }
       +        | tUNUMBER tMONTH {
       +            yyDay = $1;
       +            yyMonth = $2;
       +        }
       +        | tUNUMBER tMONTH tUNUMBER {
       +            yyDay = $1;
       +            yyMonth = $2;
       +            if ($3 > 999) {
       +                /* assume year is YYYY format, so need not to add 1900 */
       +                yyYear = $3;
       +            } else if ($3 < 100) {
       +                /* assume year is YY format, so need to add 1900 */
       +                yyYear = $3 + (yyYear / 100 + (yyYear % 100 - $3) / 50) * 100;
       +            } else {
       +                yyYear = 1900 + $3;
       +            }
       +        }
       +        | tDAY ',' tUNUMBER tMONTH tUNUMBER {
       +            yyDay = $3;
       +            yyMonth = $4;
       +            if ($5 > 999) {
       +                /* assume year is YYYY format, so need not to add 1900 */
       +                yyYear = $5;
       +            } else if ($5 < 100) {
       +                /* assume year is YY format, so need to add 1900 */
       +                yyYear = $5 + (yyYear / 100 + (yyYear % 100 - $5) / 50) * 100;
       +            } else {
       +                yyYear = 1900 + $5;
       +            }
       +        }
       +        ;
       +
       +rel        : tSNUMBER tSEC_UNIT {
       +            yyRelSeconds += $1 * $2;
       +        }
       +        | tUNUMBER tSEC_UNIT {
       +            yyRelSeconds += $1 * $2;
       +        }
       +        | tSNUMBER tMONTH_UNIT {
       +            yyRelMonth += $1 * $2;
       +        }
       +        | tUNUMBER tMONTH_UNIT {
       +            yyRelMonth += $1 * $2;
       +        }
       +        ;
       +
       +o_merid        : /* NULL */ {
       +            $$ = MER24;
       +        }
       +        | tMERIDIAN {
       +            $$ = $1;
       +        }
       +        ;
       +
       +%%
       +
       +/* Month and day table. */
       +static TABLE        MonthDayTable[] = {
       +    { "january",        tMONTH,  1 },
       +    { "february",        tMONTH,  2 },
       +    { "march",                tMONTH,  3 },
       +    { "april",                tMONTH,  4 },
       +    { "may",                tMONTH,  5 },
       +    { "june",                tMONTH,  6 },
       +    { "july",                tMONTH,  7 },
       +    { "august",                tMONTH,  8 },
       +    { "september",        tMONTH,  9 },
       +    { "october",        tMONTH, 10 },
       +    { "november",        tMONTH, 11 },
       +    { "december",        tMONTH, 12 },
       +        /* The value of the day isn't used... */
       +    { "sunday",                tDAY, 0 },
       +    { "monday",                tDAY, 0 },
       +    { "tuesday",        tDAY, 0 },
       +    { "wednesday",        tDAY, 0 },
       +    { "thursday",        tDAY, 0 },
       +    { "friday",                tDAY, 0 },
       +    { "saturday",        tDAY, 0 },
       +};
       +
       +/* Time units table. */
       +static TABLE        UnitsTable[] = {
       +    { "year",                tMONTH_UNIT,        12 },
       +    { "month",                tMONTH_UNIT,        1 },
       +    { "week",                tSEC_UNIT,        7 * 24 * 60 * 60 },
       +    { "day",                tSEC_UNIT,        1 * 24 * 60 * 60 },
       +    { "hour",                tSEC_UNIT,        60 * 60 },
       +    { "minute",                tSEC_UNIT,        60 },
       +    { "min",                tSEC_UNIT,        60 },
       +    { "second",                tSEC_UNIT,        1 },
       +    { "sec",                tSEC_UNIT,        1 },
       +};
       +
       +/* Timezone table. */
       +static TABLE        TimezoneTable[] = {
       +    { "gmt",        tZONE,     HOUR( 0) },        /* Greenwich Mean */
       +    { "ut",        tZONE,     HOUR( 0) },        /* Universal */
       +    { "utc",        tZONE,     HOUR( 0) },        /* Universal Coordinated */
       +    { "cut",        tZONE,     HOUR( 0) },        /* Coordinated Universal */
       +    { "z",        tZONE,     HOUR( 0) },        /* Greenwich Mean */
       +    { "wet",        tZONE,     HOUR( 0) },        /* Western European */
       +    { "bst",        tDAYZONE,  HOUR( 0) },        /* British Summer */
       +    { "nst",        tZONE,     HOUR(3)+30 }, /* Newfoundland Standard */
       +    { "ndt",        tDAYZONE,  HOUR(3)+30 }, /* Newfoundland Daylight */
       +    { "ast",        tZONE,     HOUR( 4) },        /* Atlantic Standard */
       +    { "adt",        tDAYZONE,  HOUR( 4) },        /* Atlantic Daylight */
       +    { "est",        tZONE,     HOUR( 5) },        /* Eastern Standard */
       +    { "edt",        tDAYZONE,  HOUR( 5) },        /* Eastern Daylight */
       +    { "cst",        tZONE,     HOUR( 6) },        /* Central Standard */
       +    { "cdt",        tDAYZONE,  HOUR( 6) },        /* Central Daylight */
       +    { "mst",        tZONE,     HOUR( 7) },        /* Mountain Standard */
       +    { "mdt",        tDAYZONE,  HOUR( 7) },        /* Mountain Daylight */
       +    { "pst",        tZONE,     HOUR( 8) },        /* Pacific Standard */
       +    { "pdt",        tDAYZONE,  HOUR( 8) },        /* Pacific Daylight */
       +    { "yst",        tZONE,     HOUR( 9) },        /* Yukon Standard */
       +    { "ydt",        tDAYZONE,  HOUR( 9) },        /* Yukon Daylight */
       +    { "akst",        tZONE,     HOUR( 9) },        /* Alaska Standard */
       +    { "akdt",        tDAYZONE,  HOUR( 9) },        /* Alaska Daylight */
       +    { "hst",        tZONE,     HOUR(10) },        /* Hawaii Standard */
       +    { "hast",        tZONE,     HOUR(10) },        /* Hawaii-Aleutian Standard */
       +    { "hadt",        tDAYZONE,  HOUR(10) },        /* Hawaii-Aleutian Daylight */
       +    { "ces",        tDAYZONE,  -HOUR(1) },        /* Central European Summer */
       +    { "cest",        tDAYZONE,  -HOUR(1) },        /* Central European Summer */
       +    { "mez",        tZONE,     -HOUR(1) },        /* Middle European */
       +    { "mezt",        tDAYZONE,  -HOUR(1) },        /* Middle European Summer */
       +    { "cet",        tZONE,     -HOUR(1) },        /* Central European */
       +    { "met",        tZONE,     -HOUR(1) },        /* Middle European */
       +    { "eet",        tZONE,     -HOUR(2) },        /* Eastern Europe */
       +    { "msk",        tZONE,     -HOUR(3) },        /* Moscow Winter */
       +    { "msd",        tDAYZONE,  -HOUR(3) },        /* Moscow Summer */
       +    { "wast",        tZONE,     -HOUR(8) },        /* West Australian Standard */
       +    { "wadt",        tDAYZONE,  -HOUR(8) },        /* West Australian Daylight */
       +    { "hkt",        tZONE,     -HOUR(8) },        /* Hong Kong */
       +    { "cct",        tZONE,     -HOUR(8) },        /* China Coast */
       +    { "jst",        tZONE,     -HOUR(9) },        /* Japan Standard */
       +    { "kst",        tZONE,     -HOUR(9) },        /* Korean Standard */
       +    { "kdt",        tZONE,     -HOUR(9) },        /* Korean Daylight */
       +    { "cast",        tZONE,     -(HOUR(9)+30) }, /* Central Australian Standard */
       +    { "cadt",        tDAYZONE,  -(HOUR(9)+30) }, /* Central Australian Daylight */
       +    { "east",        tZONE,     -HOUR(10) },        /* Eastern Australian Standard */
       +    { "eadt",        tDAYZONE,  -HOUR(10) },        /* Eastern Australian Daylight */
       +    { "nzst",        tZONE,     -HOUR(12) },        /* New Zealand Standard */
       +    { "nzdt",        tDAYZONE,  -HOUR(12) },        /* New Zealand Daylight */
       +
       +    /* For completeness we include the following entries. */
       +#if        0
       +
       +    /* Duplicate names.  Either they conflict with a zone listed above
       +     * (which is either more likely to be seen or just been in circulation
       +     * longer), or they conflict with another zone in this section and
       +     * we could not reasonably choose one over the other. */
       +    { "fst",        tZONE,     HOUR( 2) },        /* Fernando De Noronha Standard */
       +    { "fdt",        tDAYZONE,  HOUR( 2) },        /* Fernando De Noronha Daylight */
       +    { "bst",        tZONE,     HOUR( 3) },        /* Brazil Standard */
       +    { "est",        tZONE,     HOUR( 3) },        /* Eastern Standard (Brazil) */
       +    { "edt",        tDAYZONE,  HOUR( 3) },        /* Eastern Daylight (Brazil) */
       +    { "wst",        tZONE,     HOUR( 4) },        /* Western Standard (Brazil) */
       +    { "wdt",        tDAYZONE,  HOUR( 4) },        /* Western Daylight (Brazil) */
       +    { "cst",        tZONE,     HOUR( 5) },        /* Chile Standard */
       +    { "cdt",        tDAYZONE,  HOUR( 5) },        /* Chile Daylight */
       +    { "ast",        tZONE,     HOUR( 5) },        /* Acre Standard */
       +    { "adt",        tDAYZONE,  HOUR( 5) },        /* Acre Daylight */
       +    { "cst",        tZONE,     HOUR( 5) },        /* Cuba Standard */
       +    { "cdt",        tDAYZONE,  HOUR( 5) },        /* Cuba Daylight */
       +    { "est",        tZONE,     HOUR( 6) },        /* Easter Island Standard */
       +    { "edt",        tDAYZONE,  HOUR( 6) },        /* Easter Island Daylight */
       +    { "sst",        tZONE,     HOUR(11) },        /* Samoa Standard */
       +    { "ist",        tZONE,     -HOUR(2) },        /* Israel Standard */
       +    { "idt",        tDAYZONE,  -HOUR(2) },        /* Israel Daylight */
       +    { "idt",        tDAYZONE,  -(HOUR(3)+30) }, /* Iran Daylight */
       +    { "ist",        tZONE,     -(HOUR(3)+30) }, /* Iran Standard */
       +    { "cst",         tZONE,     -HOUR(8) },        /* China Standard */
       +    { "cdt",         tDAYZONE,  -HOUR(8) },        /* China Daylight */
       +    { "sst",         tZONE,     -HOUR(8) },        /* Singapore Standard */
       +
       +    /* Dubious (e.g., not in Olson's TIMEZONE package) or obsolete. */
       +    { "gst",        tZONE,     HOUR( 3) },        /* Greenland Standard */
       +    { "wat",        tZONE,     -HOUR(1) },        /* West Africa */
       +    { "at",        tZONE,     HOUR( 2) },        /* Azores */
       +    { "gst",        tZONE,     -HOUR(10) },        /* Guam Standard */
       +    { "nft",        tZONE,     HOUR(3)+30 }, /* Newfoundland */
       +    { "idlw",        tZONE,     HOUR(12) },        /* International Date Line West */
       +    { "mewt",        tZONE,     -HOUR(1) },        /* Middle European Winter */
       +    { "mest",        tDAYZONE,  -HOUR(1) },        /* Middle European Summer */
       +    { "swt",        tZONE,     -HOUR(1) },        /* Swedish Winter */
       +    { "sst",        tDAYZONE,  -HOUR(1) },        /* Swedish Summer */
       +    { "fwt",        tZONE,     -HOUR(1) },        /* French Winter */
       +    { "fst",        tDAYZONE,  -HOUR(1) },        /* French Summer */
       +    { "bt",        tZONE,     -HOUR(3) },        /* Baghdad */
       +    { "it",        tZONE,     -(HOUR(3)+30) }, /* Iran */
       +    { "zp4",        tZONE,     -HOUR(4) },        /* USSR Zone 3 */
       +    { "zp5",        tZONE,     -HOUR(5) },        /* USSR Zone 4 */
       +    { "ist",        tZONE,     -(HOUR(5)+30) }, /* Indian Standard */
       +    { "zp6",        tZONE,     -HOUR(6) },        /* USSR Zone 5 */
       +    { "nst",        tZONE,     -HOUR(7) },        /* North Sumatra */
       +    { "sst",        tZONE,     -HOUR(7) },        /* South Sumatra */
       +    { "jt",        tZONE,     -(HOUR(7)+30) }, /* Java (3pm in Cronusland!) */
       +    { "nzt",        tZONE,     -HOUR(12) },        /* New Zealand */
       +    { "idle",        tZONE,     -HOUR(12) },        /* International Date Line East */
       +    { "cat",        tZONE,     HOUR(10) },        /* -- expired 1967 */
       +    { "nt",        tZONE,     HOUR(11) },        /* -- expired 1967 */
       +    { "ahst",        tZONE,     HOUR(10) },        /* -- expired 1983 */
       +    { "hdt",        tDAYZONE,  HOUR(10) },        /* -- expired 1986 */
       +#endif        /* 0 */
       +};
       +
       +
       +
       +static void
       +date_error(const char *s)
       +{
       +    s = s;                        /* ARGSUSED */
       +    /* NOTREACHED */
       +}
       +
       +
       +static time_t
       +ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
       +{
       +    if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
       +        return -1;
       +    if (Meridian == MER24) {
       +        if (Hours < 0 || Hours > 23)
       +            return -1;
       +    }
       +    else {
       +        if (Hours < 1 || Hours > 12)
       +            return -1;
       +        if (Hours == 12)
       +            Hours = 0;
       +        if (Meridian == MERpm)
       +            Hours += 12;
       +    }
       +    return (Hours * 60L + Minutes) * 60L + Seconds;
       +}
       +
       +
       +static time_t
       +Convert(time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes,
       +        time_t Seconds, MERIDIAN Meridian, DSTMODE dst)
       +{
       +    static int        DaysNormal[13] = {
       +        0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
       +    };
       +    static int        DaysLeap[13] = {
       +        0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
       +    };
       +    static int        LeapYears[] = {
       +        1972, 1976, 1980, 1984, 1988, 1992, 1996,
       +        2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036
       +    };
       +    int                        *yp;
       +    int                        *mp;
       +    time_t                Julian;
       +    int                        i;
       +    time_t                tod;
       +
       +    /* Year should not be passed as a relative value, but absolute one.
       +       so this should not happen, but just ensure it */
       +    if (Year < 0)
       +        Year = -Year;
       +    if (Year < 100) {
       +        Year += 1900;
       +        if (Year < EPOCH)
       +            Year += 100;
       +    }
       +    for (mp = DaysNormal, yp = LeapYears; yp < ARRAY_END(LeapYears); yp++)
       +        if (Year == *yp) {
       +            mp = DaysLeap;
       +            break;
       +        }
       +    if (Year < EPOCH || Year > END_OF_TIME
       +     || Month < 1 || Month > 12
       +     /* NOSTRICT *//* conversion from long may lose accuracy */
       +     || Day < 1 || Day > mp[(int)Month])
       +        return -1;
       +
       +    Julian = Day - 1 + (Year - EPOCH) * 365;
       +    for (yp = LeapYears; yp < ARRAY_END(LeapYears); yp++, Julian++)
       +        if (Year <= *yp)
       +            break;
       +    for (i = 1; i < Month; i++)
       +        Julian += *++mp;
       +    Julian *= SECSPERDAY;
       +    Julian += yyTimezone * 60L;
       +    if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
       +        return -1;
       +    Julian += tod;
       +    tod = Julian;
       +    if (dst == DSTon || (dst == DSTmaybe && localtime(&tod)->tm_isdst))
       +        Julian -= DST_OFFSET * 60 * 60;
       +    return Julian;
       +}
       +
       +
       +static time_t
       +DSTcorrect(time_t Start, time_t Future)
       +{
       +    time_t        StartDay;
       +    time_t        FutureDay;
       +
       +    StartDay = (localtime(&Start)->tm_hour + 1) % 24;
       +    FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
       +    return (Future - Start) + (StartDay - FutureDay) * DST_OFFSET * 60 * 60;
       +}
       +
       +
       +static time_t
       +RelativeMonth(time_t Start, time_t RelMonth)
       +{
       +    struct tm        *tm;
       +    time_t        Month;
       +    time_t        Year;
       +
       +    tm = localtime(&Start);
       +    Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
       +    Year = Month / 12;
       +    Year += 1900;
       +    Month = Month % 12 + 1;
       +    return DSTcorrect(Start,
       +            Convert(Month, (time_t)tm->tm_mday, Year,
       +                (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
       +                MER24, DSTmaybe));
       +}
       +
       +
       +static int
       +LookupWord(char *buff, int length)
       +{
       +    char *p;
       +    const char *q;
       +    TABLE *tp;
       +    int        c;
       +
       +    p = buff;
       +    c = p[0];
       +
       +    /* See if we have an abbreviation for a month. */
       +    if (length == 3 || (length == 4 && p[3] == '.'))
       +        for (tp = MonthDayTable; tp < ARRAY_END(MonthDayTable); tp++) {
       +            q = tp->name;
       +            if (c == q[0] && p[1] == q[1] && p[2] == q[2]) {
       +                yylval.Number = tp->value;
       +                return tp->type;
       +            }
       +        }
       +    else
       +        for (tp = MonthDayTable; tp < ARRAY_END(MonthDayTable); tp++)
       +            if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
       +                yylval.Number = tp->value;
       +                return tp->type;
       +            }
       +
       +    /* Try for a timezone. */
       +    for (tp = TimezoneTable; tp < ARRAY_END(TimezoneTable); tp++)
       +        if (c == tp->name[0] && p[1] == tp->name[1]
       +         && strcmp(p, tp->name) == 0) {
       +            yylval.Number = tp->value;
       +            return tp->type;
       +        }
       +
       +    /* Try the units table. */
       +    for (tp = UnitsTable; tp < ARRAY_END(UnitsTable); tp++)
       +        if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
       +            yylval.Number = tp->value;
       +            return tp->type;
       +        }
       +
       +    /* Strip off any plural and try the units table again. */
       +    if (--length > 0 && p[length] == 's') {
       +        p[length] = '\0';
       +        for (tp = UnitsTable; tp < ARRAY_END(UnitsTable); tp++)
       +            if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
       +                p[length] = 's';
       +                yylval.Number = tp->value;
       +                return tp->type;
       +            }
       +        p[length] = 's';
       +    }
       +    length++;
       +
       +    /* Drop out any periods. */
       +    for (p = buff, q = buff; *q; q++)
       +        if (*q != '.')
       +            *p++ = *q;
       +    *p = '\0';
       +
       +    /* Try the meridians. */
       +    if (buff[1] == 'm' && buff[2] == '\0') {
       +        if (buff[0] == 'a') {
       +            yylval.Meridian = MERam;
       +            return tMERIDIAN;
       +        }
       +        if (buff[0] == 'p') {
       +            yylval.Meridian = MERpm;
       +            return tMERIDIAN;
       +        }
       +    }
       +
       +    /* If we saw any periods, try the timezones again. */
       +    if (p - buff != length) {
       +        c = buff[0];
       +        for (p = buff, tp = TimezoneTable; tp < ARRAY_END(TimezoneTable); tp++)
       +            if (c == tp->name[0] && p[1] == tp->name[1]
       +            && strcmp(p, tp->name) == 0) {
       +                yylval.Number = tp->value;
       +                return tp->type;
       +            }
       +    }
       +
       +    /* Unknown word -- assume GMT timezone. */
       +    yylval.Number = 0;
       +    return tZONE;
       +}
       +
       +
       +static int
       +date_lex(void)
       +{
       +    char                c;
       +    char                *p;
       +    char                buff[20];
       +    int                        sign;
       +    int                        i;
       +    int                        nesting;
       +
       +    for ( ; ; ) {
       +        /* Get first character after the whitespace. */
       +        for ( ; ; ) {
       +            while (CTYPE(isspace, (int)*yyInput))
       +                yyInput++;
       +            c = *yyInput;
       +
       +            /* Ignore RFC 822 comments, typically time zone names. */
       +            if (c != LPAREN)
       +                break;
       +            for (nesting = 1; (c = *++yyInput) != RPAREN || --nesting; )
       +                if (c == LPAREN)
       +                    nesting++;
       +                else if (!IS7BIT(c) || c == '\0' || c == '\r'
       +                     || (c == '\\' && ((c = *++yyInput) == '\0' || !IS7BIT(c))))
       +                    /* Lexical error: bad comment. */
       +                    return '?';
       +            yyInput++;
       +        }
       +
       +        /* A number? */
       +        if (CTYPE(isdigit, (int)c) || c == '-' || c == '+') {
       +            if (c == '-' || c == '+') {
       +                sign = c == '-' ? -1 : 1;
       +                yyInput++;
       +                if (!CTYPE(isdigit, (int)*yyInput))
       +                    /* Skip the plus or minus sign. */
       +                    continue;
       +            }
       +            else
       +                sign = 0;
       +            for (i = 0; (c = *yyInput++) != '\0' && CTYPE(isdigit, (int)c); )
       +                i = 10 * i + c - '0';
       +            yyInput--;
       +            yylval.Number = sign < 0 ? -i : i;
       +            return sign ? tSNUMBER : tUNUMBER;
       +        }
       +
       +        /* A word? */
       +        if (CTYPE(isalpha, (int)c)) {
       +            for (p = buff; (c = *yyInput++) == '.' || CTYPE(isalpha, (int)c); )
       +                if (p < &buff[sizeof buff - 1])
       +                    *p++ = CTYPE(isupper, (int)c) ? tolower(c) : c;
       +            *p = '\0';
       +            yyInput--;
       +            return LookupWord(buff, p - buff);
       +        }
       +
       +        return *yyInput++;
       +    }
       +}
       +
       +
       +time_t
       +parsedate(char *p)
       +{
       +    time_t                now;
       +    struct tm                *tm;
       +    time_t                Start;
       +
       +    now = time(NULL);
       +    yyInput = p;
       +
       +    tm = gmtime(&now);
       +    yyYear = tm->tm_year + 1900;
       +    yyMonth = tm->tm_mon + 1;
       +    yyDay = tm->tm_mday;
       +    yyTimezone = 0;
       +    yyDSTmode = DSTmaybe;
       +    yyHour = 0;
       +    yyMinutes = 0;
       +    yySeconds = 0;
       +    yyMeridian = MER24;
       +    yyRelSeconds = 0;
       +    yyRelMonth = 0;
       +    yyHaveDate = 0;
       +    yyHaveRel = 0;
       +    yyHaveTime = 0;
       +
       +    if (date_parse() || yyHaveTime > 1 || yyHaveDate > 1)
       +        return -1;
       +
       +    if (yyHaveDate || yyHaveTime) {
       +        Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
       +                    yyMeridian, yyDSTmode);
       +        if (Start < 0)
       +            return -1;
       +    }
       +    else {
       +        Start = now;
       +        if (!yyHaveRel)
       +            Start -= (tm->tm_hour * 60L + tm->tm_min) * 60L + tm->tm_sec;
       +    }
       +
       +    Start += yyRelSeconds;
       +    if (yyRelMonth)
       +        Start += RelativeMonth(Start, yyRelMonth);
       +
       +    /* Have to do *something* with a legitimate -1 so it's distinguishable
       +     * from the error return value.  (Alternately could set errno on error.) */
       +    return Start == -1 ? 0 : Start;
       +}
       +
       +
       +#if        defined(TEST)
       +
       +#if        YYDEBUG
       +extern int        yydebug;
       +#endif        /* YYDEBUG */
       +
       +/* ARGSUSED */
       +int
       +main(int ac, char *av[])
       +{
       +    char        buff[128];
       +    time_t        d;
       +
       +#if        YYDEBUG
       +    yydebug = 1;
       +#endif        /* YYDEBUG */
       +
       +    printf("Enter date, or blank line to exit.\n\t> ");
       +    for ( ; ; ) {
       +        printf("\t> ");
       +        fflush(stdout);
       +        if (gets(buff) == NULL || buff[0] == '\n')
       +            break;
       +#if        YYDEBUG
       +        if (strcmp(buff, "yydebug") == 0) {
       +            yydebug = !yydebug;
       +            printf("yydebug = %s\n", yydebug ? "on" : "off");
       +            continue;
       +        }
       +#endif        /* YYDEBUG */
       +        d = parsedate(buff);
       +        if (d == -1)
       +            printf("Bad format - couldn't convert.\n");
       +        else
       +            printf("%s", ctime(&d));
       +    }
       +
       +    exit(0);
       +    /* NOTREACHED */
       +}
       +#endif        /* defined(TEST) */
   DIR diff --git a/Src/pgp.c b/Src/pgp.c
       t@@ -0,0 +1,494 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   OpenPGP messages
       +   $Id: pgp.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#ifdef USE_PGP
       +#include "pgp.h"
       +#include <ctype.h>
       +#include <string.h>
       +
       +int pgp_decrypt(BUFFER *in, BUFFER *pass, BUFFER *sig, char *pubring,
       +                char *secring)
       +{
       +  BUFFER *key;
       +  int err;
       +
       +  key = buf_new();
       +  if (pass)
       +    buf_set(key, pass);
       +  if (!pgp_ispacket(in))
       +    pgp_dearmor(in, in);
       +  err = pgp_getmsg(in, key, sig, pubring, secring);
       +  buf_free(key);
       +  return (err);
       +}
       +
       +static void appendaddr(BUFFER *to, BUFFER *addr)
       +{
       +  if (bufifind(addr, "<")) {
       +    for (addr->ptr = 0; addr->ptr < addr->length; addr->ptr++)
       +      if (addr->data[addr->ptr] == '<') {
       +        buf_rest(to, addr);
       +        break;
       +      }
       +  } else {
       +    buf_appendc(to, '<');
       +    buf_cat(to, addr);
       +    buf_appendc(to, '>');
       +  }
       +  buf_nl(to);
       +  buf_clear(addr);
       +}
       +
       +int pgp_mailenc(int mode, BUFFER *msg, char *sigid,
       +                BUFFER *pass, char *pubring, char *secring)
       +{
       +  BUFFER *hdr, *body, *line, *uid, *field, *content;
       +  int err = -1;
       +
       +  hdr = buf_new();
       +  body = buf_new();
       +  line = buf_new();
       +  uid = buf_new();
       +  field = buf_new();
       +  content = buf_new();
       +
       +  buf_appendc(uid, '<');
       +  buf_appends(uid, sigid);
       +  if (sigid[strlen(sigid) - 1] != '@')
       +    buf_appendc(uid, '>');
       +
       +  while (buf_getline(msg, line) == 0)
       +    buf_cat(hdr, line), buf_nl(hdr);
       +
       +  if ((mode & PGP_SIGN) && !(mode & PGP_ENCRYPT))
       +    while (buf_getheader(hdr, field, content) == 0)
       +      if (bufileft(field, "content-") || bufieq(field, "mime-version")) {
       +        /* Is MIME message */
       +        err = pgpmime_sign(msg, uid, pass, secring);
       +        goto end;
       +      }
       +
       +  buf_rest(body, msg);
       +
       +  if ((mode & PGP_SIGN) && !(mode & PGP_ENCRYPT)) {
       +    err = pgp_signtxt(body, uid, pass, secring, mode & PGP_REMAIL);
       +  }
       +
       +  if (mode & PGP_ENCRYPT) {
       +    BUFFER *plainhdr, *encrhdr, *to, *addr;
       +    int encapsulate = 0;
       +
       +    plainhdr = buf_new();
       +    encrhdr = buf_new();
       +    to = buf_new();
       +    addr = buf_new();
       +    while (buf_getheader(hdr, field, content) == 0) {
       +      if (bufieq(field, "to") || bufieq(field, "cc") || bufieq(field, "bcc")) {
       +        buf_appendheader(plainhdr, field, content);
       +        rfc822_addr(content, addr);
       +        while (buf_getline(addr, content) != -1)
       +          appendaddr(to, content);
       +      } else
       +        buf_appendheader(encrhdr, field, content);
       +    }
       +#if 1
       +    /* encrypt the headers */
       +    buf_appends(plainhdr, "Subject: PGP encrypted message\n");
       +    if (encrhdr->length) {
       +      buf_nl(encrhdr);
       +      buf_cat(encrhdr, body);
       +      buf_move(body, encrhdr);
       +      encapsulate = 1;
       +    }
       +#else /* end of 1 */
       +    /* send headers as plain text */
       +    buf_cat(plainhdr, encrhdr);
       +#endif /* not 1 */
       +    buf_move(hdr, plainhdr);
       +
       +    buf_clear(line);
       +    if (encapsulate)
       +      buf_sets(line, "Content-Type: message/rfc822\n");
       +    else if (strlen(DEFLTENTITY))
       +      buf_setf(line, "Content-Type: %s\n", DEFLTENTITY);
       +    buf_nl(line);
       +    buf_cat(line, body);
       +    buf_move(body, line);
       +
       +    /* Use the user keyring if pubring == NULL */
       +    err = pgp_encrypt(mode, body, to, uid, pass,
       +                      pubring ? pubring : PGPPUBRING, secring);
       +    buf_free(plainhdr);
       +    buf_free(encrhdr);
       +    buf_free(to);
       +    buf_free(addr);
       +  }
       +  if (err == 0) {
       +    if (mode & PGP_ENCRYPT) {
       +#if 1
       +      buf_sets(field, "+--");
       +#else /* end of 1 */
       +    buf_setrnd(mboundary, 18);
       +    encode(mboundary, 0);
       +#endif /* else if not 1 */
       +
       +      buf_appendf(hdr,
       +                  "Content-Type: multipart/encrypted; boundary=\"%b\"; "
       +                  "protocol=\"application/pgp-encrypted\"\n\n"
       +                  "--%b\n"
       +                  "Content-Type: application/pgp-encrypted\n\n"
       +                  "Version: 1\n\n"
       +                  "--%b\n"
       +                  "Content-Type: application/octet-stream\n",
       +                  field, field, field);
       +      buf_appendf(body, "\n--%b--\n", field);
       +    }
       +    buf_move(msg, hdr);
       +    buf_nl(msg);
       +    buf_cat(msg, body);
       +  }
       + end:
       +  buf_free(hdr);
       +  buf_free(body);
       +  buf_free(line);
       +  buf_free(uid);
       +  buf_free(field);
       +  buf_free(content);
       +  return (err);
       +}
       +
       +static void pgp_setkey(BUFFER *key, int algo)
       +{
       +  buf_setc(key, algo);
       +  buf_appendrnd(key, pgp_keylen(algo));
       +}
       +
       +int pgp_encrypt(int mode, BUFFER *in, BUFFER *to, BUFFER *sigid,
       +                BUFFER *pass, char *pubring, char *secring)
       +{
       +  BUFFER *dek, *out, *sig, *dest, *tmp;
       +  int err = 0, sym = PGP_K_ANY, mdc = 0;
       +  int text;
       +
       +  out = buf_new();
       +  tmp = buf_new();
       +  dek = buf_new();
       +  sig = buf_new();
       +  dest = buf_new();
       +
       +  text = mode & PGP_TEXT ? 1 : 0;
       +
       +  if (mode & (PGP_CONV3DES | PGP_CONVCAST))
       +    mode |= PGP_NCONVENTIONAL;
       +
       +  if (mode & PGP_SIGN) {
       +    err = pgp_sign(in, NULL, sig, sigid, pass, text, 0, 0,
       +                   mode & PGP_REMAIL ? 1 : 0, NULL, secring);
       +    if (err < 0)
       +      goto end;
       +    if (mode & PGP_DETACHEDSIG) {
       +      buf_move(in, sig);
       +      if (!(mode & PGP_NOARMOR))
       +        pgp_armor(in, PGP_ARMOR_NYMSIG);
       +      goto end;
       +    }
       +  }
       +  if (mode & PGP_ENCRYPT) {
       +    err = buf_getline(to, dest);
       +    if (err == -1)
       +      goto end;
       +    if (to->ptr == to->length) {
       +      if ((err = pgpdb_getkey(PK_ENCRYPT, PGP_ANY, &sym, &mdc, NULL, NULL, dest, NULL,
       +                              NULL, pubring, NULL)) < 0)
       +        goto end;
       +      pgp_setkey(dek, sym);
       +      err = pgp_sessionkey(out, dest, NULL, dek, pubring);
       +#ifdef USE_IDEA
       +      if (err < 0 && dek->data[0] == PGP_K_IDEA) {
       +        pgp_setkey(dek, PGP_K_3DES);
       +        err = pgp_sessionkey(out, dest, NULL, dek, pubring);
       +      }
       +#endif /* USE_IDEA */
       +    } else {
       +      /* multiple recipients */
       +      pgp_setkey(dek, PGP_K_3DES);
       +      buf_rewind(to);
       +      while (buf_getline(to, dest) != -1)
       +        if (dest->length) {
       +          err = pgp_sessionkey(tmp, dest, NULL, dek, pubring);
       +#ifdef USE_IDEA
       +          if (err < 0 && dek->data[0] != PGP_K_IDEA) {
       +            buf_rewind(to);
       +            buf_clear(out);
       +            pgp_setkey(dek, PGP_K_IDEA);
       +            continue;
       +          }
       +#endif /* USE_IDEA */
       +          if (err < 0)
       +            goto end;
       +          buf_cat(out, tmp);
       +        }
       +    }
       +  } else if (mode & PGP_NCONVENTIONAL) {
       +    /* genereate DEK in pgp_symsessionkey */
       +    buf_setc(dek, mode & PGP_CONVCAST ? PGP_K_CAST5 : PGP_K_3DES);
       +    pgp_marker(out);
       +    err = pgp_symsessionkey(tmp, dek, to);
       +    buf_cat(out, tmp);
       +  } else if (mode & PGP_CONVENTIONAL) {
       +    digest_md5(to, tmp);
       +    buf_setc(dek, PGP_K_IDEA);
       +    buf_cat(dek, tmp);
       +  }
       +
       +  pgp_literal(in, NULL, text);
       +  if (sig->length) {
       +    buf_cat(sig, in);
       +    buf_move(in, sig);
       +  }
       +  pgp_compress(in);
       +  if (mode & (PGP_ENCRYPT | PGP_CONVENTIONAL | PGP_NCONVENTIONAL))
       +    pgp_symmetric(in, dek, mdc);
       +  if (mode & (PGP_ENCRYPT | PGP_NCONVENTIONAL)) {
       +    buf_cat(out, in);
       +    buf_move(in, out);
       +  }
       +  if (!(mode & PGP_NOARMOR))
       +    pgp_armor(in, (mode & PGP_REMAIL) ? PGP_ARMOR_REM : PGP_ARMOR_NORMAL);
       +
       +end:
       +  buf_free(out);
       +  buf_free(tmp);
       +  buf_free(dek);
       +  buf_free(sig);
       +  buf_free(dest);
       +  return (err);
       +}
       +
       +#define POLY 0X1864CFB
       +
       +unsigned long crc24(BUFFER * in)
       +{
       +  unsigned long crc = 0xB704CE;
       +  long p;
       +  int i;
       +
       +#if 0
       +  /* CRC algorithm from RFC 2440 */
       +  for (p = 0; p < in->length; p++) {
       +    crc ^= in->data[p] << 16;
       +    for (i = 0; i < 8; i++) {
       +      crc <<= 1;
       +      if (crc & 0x1000000)
       +        crc ^= POLY;
       +    }
       +  }
       +#else
       +  /* pre-computed CRC table -- much faster */
       +  unsigned long table[256];
       +  unsigned long t;
       +  int q = 0;
       +
       +  table[0] = 0;
       +  for (i = 0; i < 128; i++) {
       +    t = table[i] << 1;
       +    if (t & 0x1000000) {
       +      table[q++] = t ^ POLY;
       +      table[q++] = t;
       +    } else {
       +      table[q++] = t;
       +      table[q++] = t ^ POLY;
       +    }
       +  }
       +  for (p = 0; p < in->length; p++)
       +    crc = crc << 8 ^ table[(in->data[p] ^ crc >> 16) & 255];
       +#endif
       +  return crc & ((1<<24)-1);
       +}
       +
       +/* ASCII armor */
       +
       +int pgp_dearmor(BUFFER *in, BUFFER *out)
       +{
       +  BUFFER *line, *temp;
       +  int err = 0;
       +  int tempbuf = 0;
       +  unsigned long crc1, crc2;
       +
       +  line = buf_new();
       +  temp = buf_new();
       +
       +  if (in == out) {
       +    out = buf_new();
       +    tempbuf = 1;
       +  }
       +  do
       +    if (buf_getline(in, line) == -1) {
       +      err = -1;
       +      goto end;
       +    }
       +  while (!bufleft(line, begin_pgp)) ;
       +
       +  while (buf_getheader(in, temp, line) == 0) ;        /* scan for empty line */
       +
       +  err = decode(in, out);
       +  crc1 = crc24(out);
       +  err = buf_getline(in, line);
       +  if (line->length == 5 && line->data[0] == '=') {        /* CRC */
       +    line->ptr = 1;
       +    err = decode(line, temp);
       +    crc2 = (((unsigned long)temp->data[0])<<16) | (((unsigned long)temp->data[1])<<8) | temp->data[2];
       +    if (crc1 == crc2)
       +      err = buf_getline(in, line);
       +    else {
       +      errlog(NOTICE, "Message CRC does not match.\n");
       +      err = -1;
       +    }
       +  } else
       +    err = -1;
       +  if (err == 0 && bufleft(line, end_pgp))
       +    err = 0;
       +  else
       +    err = -1;
       +
       +end:
       +  buf_free(temp);
       +  buf_free(line);
       +
       +  if (tempbuf) {
       +    buf_move(in, out);
       +    buf_free(out);
       +  }
       +  return (err);
       +}
       +
       +int pgp_armor(BUFFER *in, int mode)
       +
       +/* mode = 1: remailer message    (PGP_ARMOR_REM)
       + *        0: normal message,     (PGP_ARMOR_NORMAL)
       + *        2: key                 (PGP_ARMOR_KEY)
       + *        3: nym key             (PGP_ARMOR_NYMKEY)
       + *        4: nym signature       (PGP_ARMOR_NYMSIG)
       + *        5: secret key          (PGP_ARMOR_SECKEY)
       + */
       +
       +{
       +  BUFFER *out;
       +  unsigned long crc;
       +
       +  crc = crc24(in);
       +  encode(in, 64);
       +
       +  out = buf_new();
       +  if (mode == PGP_ARMOR_KEY || mode == PGP_ARMOR_NYMKEY)
       +    buf_sets(out, begin_pgpkey);
       +  else if (mode == PGP_ARMOR_NYMSIG)
       +    buf_sets(out, begin_pgpsig);
       +  else if (mode == PGP_ARMOR_SECKEY)
       +    buf_sets(out, begin_pgpseckey);
       +  else
       +    buf_sets(out, begin_pgpmsg);
       +  buf_nl(out);
       +#ifdef CLOAK
       +  if (mode == PGP_ARMOR_REM || mode == PGP_ARMOR_NYMKEY || mode == PGP_ARMOR_NYMSIG)
       +    buf_appends(out, "Version: N/A\n");
       +  else
       +#elif MIMIC /* end of CLOAK */
       +  if (mode == PGP_ARMOR_REM || mode == PGP_ARMOR_NYMKEY || mode == PGP_ARMOR_NYMSIG)
       +    buf_appends(out, "Version: 2.6.3i\n");
       +  else
       +#endif /* MIMIC */
       +  {
       +    buf_appends(out, "Version: Mixmaster ");
       +    buf_appends(out, VERSION);
       +    buf_appends(out, " (OpenPGP module)\n");
       +  }
       +  buf_nl(out);
       +  buf_cat(out, in);
       +  buf_reset(in);
       +  buf_appendc(in, (crc >> 16) & 255);
       +  buf_appendc(in, (crc >> 8) & 255);
       +  buf_appendc(in, crc & 255);
       +  encode(in, 0);
       +  buf_appendc(out, '=');
       +  buf_cat(out, in);
       +  buf_nl(out);
       +  if (mode == PGP_ARMOR_KEY || mode == PGP_ARMOR_NYMKEY)
       +    buf_appends(out, end_pgpkey);
       +  else if (mode == PGP_ARMOR_NYMSIG)
       +    buf_appends(out, end_pgpsig);
       +  else if (mode == PGP_ARMOR_SECKEY)
       +    buf_appends(out, end_pgpseckey);
       +  else
       +    buf_appends(out, end_pgpmsg);
       +  buf_nl(out);
       +
       +  buf_move(in, out);
       +  buf_free(out);
       +  return (0);
       +}
       +
       +int pgp_keygen(int algo, int bits, BUFFER *userid, BUFFER *pass, char *pubring,
       +               char *secring, int remail)
       +{
       +  switch (algo) {
       +  case PGP_ES_RSA:
       +#ifndef USE_IDEA
       +    errlog(WARNING, "IDEA disabled: OpenPGP RSA key cannot be used for decryption!\n");
       +#endif
       +    return (pgp_rsakeygen(bits, userid, pass, pubring, secring, remail));
       +  case PGP_E_ELG:
       +    return (pgp_dhkeygen(bits, userid, pass, pubring, secring, remail));
       +  default:
       +    return -1;
       +  }
       +}
       +
       +int pgp_signtxt(BUFFER *msg, BUFFER *uid, BUFFER *pass,
       +                char *secring, int remail)
       +{
       +  int err;
       +  BUFFER *line, *sig, *out;
       +
       +  sig = buf_new();
       +  out = buf_new();
       +  line = buf_new();
       +
       +  buf_appends(out, begin_pgpsigned);
       +  buf_nl(out);
       +  if (pgpdb_getkey(PK_SIGN, PGP_ANY, NULL, NULL, NULL, NULL, uid, NULL, NULL, secring, pass) == PGP_S_DSA)
       +    buf_appends(out, "Hash: SHA1\n");
       +  buf_nl(out);
       +  while (buf_getline(msg, line) != -1) {
       +    if (line->data[0] == '-')
       +      buf_appends(out, "- ");
       +    buf_cat(out, line);
       +    buf_nl(out);
       +  }
       +  buf_nl(out);
       +
       +  buf_rewind(msg);
       +  err = pgp_encrypt(PGP_SIGN | PGP_DETACHEDSIG | PGP_TEXT |
       +                    (remail ? PGP_REMAIL : 0),
       +                    msg, NULL, uid, pass, NULL, secring);
       +  if (err == -1)
       +    goto end;
       +  buf_cat(out, msg);
       +  buf_move(msg, out);
       +end:
       +  buf_free(line);
       +  buf_free(sig);
       +  buf_free(out);
       +  return (err);
       +}
       +
       +#endif /* USE_PGP */
   DIR diff --git a/Src/pgp.h b/Src/pgp.h
       t@@ -0,0 +1,189 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   OpenPGP messages
       +   $Id: pgp.h 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#ifdef USE_PGP
       +#ifndef _PGP_H
       +#include "mix3.h"
       +#ifdef USE_OPENSSL
       +#include <openssl/opensslv.h>
       +#endif /* USE_OPENSSL */
       +
       +/* in the PGP Version header, list the same information as all other
       +   versions of Mixmaster to prevent anonymity set division. */
       +#define CLOAK
       +
       +/* try to make the messages look similar to PGP 2.6.3i output
       +   (compression is not always the same though). */
       +#define MIMIC
       +
       +/* packet types */
       +#define PGP_SESKEY 1
       +#define PGP_SIG 2
       +#define PGP_SYMSESKEY 3
       +#define PGP_OSIG 4
       +#define PGP_SECKEY 5
       +#define PGP_PUBKEY 6
       +#define PGP_SECSUBKEY 7
       +#define PGP_COMPRESSED 8
       +#define PGP_ENCRYPTED 9
       +#define PGP_MARKER 10
       +#define PGP_LITERAL 11
       +#define PGP_TRUST 12
       +#define PGP_USERID 13
       +#define PGP_PUBSUBKEY 14
       +#define PGP_ENCRYPTEDMDC 18
       +#define PGP_MDC 19
       +
       +/* symmetric algorithms */
       +#define PGP_K_ANY 0
       +#define PGP_K_IDEA 1
       +#define PGP_K_3DES 2
       +#define PGP_K_CAST5 3
       +#define PGP_K_BF 4
       +#define PGP_K_AES128 7
       +#define PGP_K_AES192 8
       +#define PGP_K_AES256 9
       +
       +/* hash algorithms */
       +#define PGP_H_MD5 1
       +#define PGP_H_SHA1 2
       +#define PGP_H_RIPEMD 3
       +
       +/* signature types */
       +#define PGP_SIG_BINARY 0
       +#define PGP_SIG_CANONIC 1
       +#define PGP_SIG_CERT 0x10
       +#define PGP_SIG_CERT1 0x11
       +#define PGP_SIG_CERT2 0x12
       +#define PGP_SIG_CERT3 0x13
       +#define isPGP_SIG_CERT(x) (x >= PGP_SIG_CERT && x <= PGP_SIG_CERT3)
       +#define PGP_SIG_BINDSUBKEY 0x18
       +#define PGP_SIG_KEYREVOKE 0x20
       +#define PGP_SIG_SUBKEYREVOKE 0x28
       +#define PGP_SIG_CERTREVOKE 0x30
       +
       +/* signature subpacket types */
       +#define PGP_SUB_CREATIME 2
       +#define PGP_SUB_CERTEXPIRETIME 3
       +#define PGP_SUB_KEYEXPIRETIME 9
       +#define PGP_SUB_PSYMMETRIC 11
       +#define PGP_SUB_ISSUER 16
       +#define PGP_SUB_PRIMARY 25
       +#define PGP_SUB_FEATURES 30
       +
       +#define ARMORED 1
       +
       +/* publick key algorithm operation modes */
       +
       +#define PK_ENCRYPT 1
       +#define PK_DECRYPT 2
       +#define PK_SIGN 3
       +#define PK_VERIFY 4
       +
       +#define MD5PREFIX "\x30\x20\x30\x0C\x06\x08\x2A\x86\x48\x86\xF7\x0D\x02\x05\x05\x00\x04\x10"
       +#define SHA1PREFIX "\x30\x21\x30\x09\x06\x05\x2b\x0E\x03\x02\x1A\x05\x00\x04\x14"
       +
       +typedef struct {
       +  int ok;
       +  BUFFER *userid;
       +  byte sigtype;
       +  long sigtime;
       +  byte hash[16];
       +} pgpsig;
       +
       +/* internal error codes */
       +#define PGP_SIGVRFY 99                /* valid signature packet to be verified */
       +
       +/* pgpdata.c */
       +int pgp_getsk(BUFFER *p, BUFFER *pass, BUFFER *key);
       +int pgp_makesk(BUFFER *out, BUFFER *key, int sym, int type, int hash,
       +               BUFFER *pass);
       +void pgp_iteratedsk(BUFFER *salted, BUFFER *salt, BUFFER *pass, byte c);
       +int pgp_expandsk(BUFFER *key, int skalgo, int hashalgo, BUFFER *data);
       +int skcrypt(BUFFER *data, int skalgo, BUFFER *key, BUFFER *iv, int enc);
       +int mpi_get(BUFFER *buf, BUFFER *mpi);
       +int mpi_put(BUFFER *buf, BUFFER *mpi);
       +int pgp_rsa(BUFFER *buf, BUFFER *key, int mode);
       +void pgp_sigcanonic(BUFFER *msg);
       +int pgp_makepubkey(BUFFER *seckey, BUFFER *outtxt, BUFFER *pubkey,
       +                   BUFFER *pass, int keyalgo);
       +int pgp_makekeyheader(int type, BUFFER *keypacket, BUFFER *outtxt,
       +                   BUFFER *pass, int keyalgo);
       +int pgp_getkey(int mode, int algo, int *sym, int *mdc, long *expires, BUFFER *keypacket, BUFFER *key,
       +               BUFFER *keyid, BUFFER *userid, BUFFER *pass);
       +int pgp_rsakeygen(int bits, BUFFER *userid, BUFFER *pass, char *pubring,
       +                  char *secring, int remail);
       +int pgp_dhkeygen(int bits, BUFFER *userid, BUFFER *pass, char *pubring,
       +                 char *secring, int remail);
       +int pgp_dosign(int algo, BUFFER *data, BUFFER *key);
       +int pgp_elgencrypt(BUFFER *b, BUFFER *key);
       +int pgp_elgdecrypt(BUFFER *b, BUFFER *key);
       +int pgp_keyid(BUFFER *key, BUFFER *id);
       +int pgp_keylen(int symalgo);
       +int pgp_blocklen(int symalgo);
       +
       +/* pgpget.c */
       +int pgp_getmsg(BUFFER *in, BUFFER *key, BUFFER *sig, char *pubring,
       +               char *secring);
       +int pgp_ispacket(BUFFER *buf);
       +int pgp_isconventional(BUFFER *buf);
       +int pgp_packettype(BUFFER *buf, long *len, int *partial);
       +int pgp_packetpartial(BUFFER *buf, long *len, int *partial);
       +int pgp_getpacket(BUFFER *buf, BUFFER *p);
       +int pgp_getsig(BUFFER *p, pgpsig *sig, char *pubring);
       +void pgp_verify(BUFFER *msg, BUFFER *detached, pgpsig *sig);
       +int pgp_getsymmetric(BUFFER *buf, BUFFER *key, int algo, int type);
       +int pgp_getliteral(BUFFER *buf);
       +int pgp_uncompress(BUFFER *buf);
       +int pgp_getsessionkey(BUFFER *buf, BUFFER *pass, char *secring);
       +int pgp_getsymsessionkey(BUFFER *buf, BUFFER *pass);
       +
       +/* pgpcreat.c */
       +int pgp_packet(BUFFER *buf, int type);
       +int pgp_packet3(BUFFER *buf, int type);
       +int pgp_symmetric(BUFFER *buf, BUFFER *key, int mdc);
       +int pgp_literal(BUFFER *buf, char *filename, int text);
       +int pgp_compress(BUFFER *buf);
       +int pgp_sessionkey(BUFFER *buf, BUFFER *user, BUFFER *keyid, BUFFER *seskey,
       +                   char *pubring);
       +void pgp_marker(BUFFER *buf);
       +int pgp_symsessionkey(BUFFER *buf, BUFFER *seskey, BUFFER *pass);
       +int pgp_sign(BUFFER *msg, BUFFER *msg2, BUFFER *sig, BUFFER *userid,
       +             BUFFER *pass, int type, int self, long now, int remail,
       +             BUFFER *seckey, char *secring);
       +int pgp_digest(int hashalgo, BUFFER *in, BUFFER *d);
       +
       +/* pgpdb.c */
       +
       +int pgpdb_getkey(int mode, int algo, int *sym, int *mdc, long *expires, BUFFER *key, BUFFER *user,
       +                 BUFFER *founduid, BUFFER *keyid, char *keyring, BUFFER *pass);
       +
       +typedef struct {
       +  int filetype;
       +  BUFFER *db;
       +  LOCK *lock;
       +  int modified;
       +  int type; /* undefined, public, private */
       +  char filename[LINELEN];
       +  BUFFER *encryptkey;
       +#ifndef NDEBUG
       +  int writer;
       +#endif
       +} KEYRING;
       +
       +KEYRING *pgpdb_new(char *keyring, int filetype, BUFFER *encryptkey, int type);
       +KEYRING *pgpdb_open(char *keyring, BUFFER *encryptkey, int writer, int type);
       +int pgpdb_append(KEYRING *keydb, BUFFER *p);
       +int pgpdb_getnext(KEYRING *keydb, BUFFER *p, BUFFER *keyid, BUFFER *userid);
       +int pgpdb_close(KEYRING *keydb);
       +
       +#endif /* not _PGP_H */
       +#endif /* USE_PGP */
   DIR diff --git a/Src/pgpcreat.c b/Src/pgpcreat.c
       t@@ -0,0 +1,848 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Create OpenPGP packets
       +   $Id: pgpcreat.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#ifdef USE_PGP
       +#include "pgp.h"
       +#include "crypto.h"
       +#include <assert.h>
       +#include <time.h>
       +#include <string.h>
       +
       +int pgp_packet(BUFFER *in, int type)
       +{
       +  int ctb;
       +  BUFFER *out;
       +
       +  out = buf_new();
       + if (type > 15) {
       +    ctb = 0xC0 | type; /* make v4 packet */
       +    buf_setc(out, ctb);
       +    if (in->length > 8383) {
       +      buf_appendc(out, 0xFF);
       +      buf_appendl(out, in->length);
       +    } else if (in->length > 191) {
       +#if 0
       +      buf_appendc(out, ((in->length-192) >> 8) + 192);
       +      buf_appendc(out,  (in->length-192) & 0xFF);
       +#else /* end of 0 */
       +      buf_appendi(out, in->length - 0xC0 + 0xC000);
       +#endif /* else if not 0 */
       +    } else {
       +      buf_appendc(out, in->length);
       +    }
       + } else {
       +  ctb = 128 + (type << 2);
       +  if (in->length < 256 && type != PGP_PUBKEY && type != PGP_SECKEY &&
       +      type != PGP_SIG && type != PGP_PUBSUBKEY && type != PGP_SECSUBKEY
       +#ifdef MIMIC
       +      && type != PGP_ENCRYPTED
       +#endif /* MIMIC */
       +    ) {
       +    buf_setc(out, ctb);
       +    buf_appendc(out, in->length);
       +  }
       +#ifndef MIMIC
       +  else if (in->length < 65536)
       +#else /* end of not MIMIC */
       +  else if ((type == PGP_PUBKEY || type == PGP_SECKEY || type == PGP_SIG
       +           || type == PGP_SESKEY || type == PGP_PUBSUBKEY ||
       +           type == PGP_SECSUBKEY) && in->length < 65536)
       +#endif /* else if MIMIC */
       +  {
       +    buf_appendc(out, ctb | 1);
       +    buf_appendi(out, in->length);
       +  } else {
       +    buf_appendc(out, ctb | 2);
       +    buf_appendl(out, in->length);
       +  }
       + }
       +  buf_cat(out, in);
       +  buf_move(in, out);
       +  buf_free(out);
       +  return (0);
       +}
       +
       +int pgp_subpacket(BUFFER *in, int type)
       +{
       +  BUFFER *out;
       +  int len;
       +
       +  out = buf_new();
       +  len = in->length + 1;
       +  if (len < 192)
       +    buf_setc(out, len);
       +  else {
       +    buf_setc(out, 255);
       +    buf_appendl(out, len);
       +  }
       +  buf_appendc(out, type);
       +  buf_cat(out, in);
       +  buf_move(in, out);
       +  buf_free(out);
       +  return (0);
       +}
       +
       +int pgp_packet3(BUFFER *in, int type)
       +{
       +#ifdef MIMIC
       +  int ctb;
       +  BUFFER *out;
       +
       +  out = buf_new();
       +  ctb = 128 + (type << 2);
       +  buf_setc(out, ctb | 3);
       +  buf_cat(out, in);
       +  buf_move(in, out);
       +  buf_free(out);
       +  return (0);
       +#else /* end of MIMIC */
       +  return pgp_packet(in, type);
       +#endif /* else if not MIMIC */
       +}
       +
       +#ifdef USE_IDEA
       +static int pgp_ideaencrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
       +{
       +  byte iv[8];
       +  int i, n = 0;
       +  IDEA_KEY_SCHEDULE ks;
       +  SHA_CTX c;
       +
       +  assert(key->length == 17);
       +
       +  for (i = 0; i < 8; i++)
       +    iv[i] = 0;
       +
       +  idea_set_encrypt_key(key->data + 1, &ks);
       +
       +  if (mdc) {
       +    mdc = 1;
       +    out->data[0] = 1;
       +  }
       +  rnd_bytes(out->data + mdc, 8);
       +  out->data[8 + mdc] = out->data[6 + mdc], out->data[9 + mdc] = out->data[7 + mdc];
       +  if (mdc) {
       +    SHA1_Init(&c);
       +    SHA1_Update(&c, out->data + 1, 10);
       +    SHA1_Update(&c, in->data, in->length);
       +  }
       +  n = 0;
       +  idea_cfb64_encrypt(out->data + mdc, out->data + mdc, 10, &ks, iv, &n, IDEA_ENCRYPT);
       +  if (!mdc) {
       +    iv[6] = iv[0], iv[7] = iv[1];
       +    memcpy(iv, out->data + 2, 6);
       +    n = 0;
       +  }
       +  idea_cfb64_encrypt(in->data, out->data + 10 + mdc, in->length, &ks, iv, &n,
       +                     IDEA_ENCRYPT);
       +  if (mdc) {
       +    SHA1_Update(&c, "\xD3\x14", 2); /* 0xD3 = 0xC0 | PGP_MDC */
       +    idea_cfb64_encrypt("\xD3\x14", out->data + 11 + in->length, 2, &ks, iv, &n,
       +                       IDEA_ENCRYPT);
       +    SHA1_Final(out->data + 13 + in->length, &c);
       +    idea_cfb64_encrypt(out->data + 13 + in->length, out->data + 13 + in->length, 20, &ks, iv, &n,
       +                       IDEA_ENCRYPT);
       +  }
       +  return (0);
       +}
       +#endif /* USE_IDEA */
       +
       +static int pgp_3desencrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
       +{
       +  des_cblock iv;
       +  int i, n = 0;
       +  des_key_schedule ks1;
       +  des_key_schedule ks2;
       +  des_key_schedule ks3;
       +  SHA_CTX c;
       +
       +  assert(key->length == 25);
       +
       +  for (i = 0; i < 8; i++)
       +    iv[i] = 0;
       +
       +  des_set_key((const_des_cblock *) (key->data + 1), ks1);
       +  des_set_key((const_des_cblock *) (key->data + 9), ks2);
       +  des_set_key((const_des_cblock *) (key->data+ 17), ks3);
       +
       +  if (mdc) {
       +    mdc = 1;
       +    out->data[0] = 1;
       +  }
       +  rnd_bytes(out->data + mdc, 8);
       +  out->data[8 + mdc] = out->data[6 + mdc], out->data[9 + mdc] = out->data[7 + mdc];
       +  if (mdc) {
       +    SHA1_Init(&c);
       +    SHA1_Update(&c, out->data + 1, 10);
       +    SHA1_Update(&c, in->data, in->length);
       +  }
       +  n = 0;
       +  des_ede3_cfb64_encrypt(out->data + mdc, out->data + mdc, 10, ks1, ks2, ks3, &iv, &n,
       +                         ENCRYPT);
       +  if (!mdc) {
       +    iv[6] = iv[0], iv[7] = iv[1];
       +    memcpy(iv, out->data + 2, 6);
       +    n = 0;
       +  }
       +  des_ede3_cfb64_encrypt(in->data, out->data + 10 + mdc, in->length, ks1, ks2, ks3,
       +                         &iv, &n, ENCRYPT);
       +  if (mdc) {
       +    SHA1_Update(&c, "\xD3\x14", 2); /* 0xD3 = 0xC0 | PGP_MDC */
       +    des_ede3_cfb64_encrypt("\xD3\x14", out->data + 11 + in->length, 2, ks1, ks2, ks3,
       +                       &iv, &n, ENCRYPT);
       +    SHA1_Final(out->data + 13 + in->length, &c);
       +    des_ede3_cfb64_encrypt(out->data + 13 + in->length, out->data + 13 + in->length, 20, ks1, ks2, ks3,
       +                       &iv, &n, ENCRYPT);
       +  }
       +  return (0);
       +}
       +
       +static int pgp_castencrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
       +{
       +  byte iv[8];
       +  int i, n = 0;
       +  CAST_KEY ks;
       +  SHA_CTX c;
       +
       +  assert(key->length == 17);
       +
       +  for (i = 0; i < 8; i++)
       +    iv[i] = 0;
       +
       +  CAST_set_key(&ks, 16, key->data + 1);
       +
       +  if (mdc) {
       +    mdc = 1;
       +    out->data[0] = 1;
       +  }
       +  rnd_bytes(out->data + mdc, 8);
       +  out->data[8 + mdc] = out->data[6 + mdc], out->data[9 + mdc] = out->data[7 + mdc];
       +  if (mdc) {
       +    SHA1_Init(&c);
       +    SHA1_Update(&c, out->data + 1, 10);
       +    SHA1_Update(&c, in->data, in->length);
       +  }
       +  n = 0;
       +  CAST_cfb64_encrypt(out->data + mdc, out->data + mdc, 10, &ks, iv, &n, CAST_ENCRYPT);
       +  if (!mdc) {
       +    iv[6] = iv[0], iv[7] = iv[1];
       +    memcpy(iv, out->data + 2, 6);
       +    n = 0;
       +  }
       +  CAST_cfb64_encrypt(in->data, out->data + 10 + mdc, in->length, &ks, iv, &n,
       +                     CAST_ENCRYPT);
       +  if (mdc) {
       +    SHA1_Update(&c, "\xD3\x14", 2); /* 0xD3 = 0xC0 | PGP_MDC */
       +    CAST_cfb64_encrypt("\xD3\x14", out->data + 11 + in->length, 2, &ks, iv, &n,
       +                       CAST_ENCRYPT);
       +    SHA1_Final(out->data + 13 + in->length, &c);
       +    CAST_cfb64_encrypt(out->data + 13 + in->length, out->data + 13 + in->length, 20, &ks, iv, &n,
       +                       CAST_ENCRYPT);
       +  }
       +  return (0);
       +}
       +
       +static int pgp_bfencrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
       +{
       +  byte iv[8];
       +  int i, n = 0;
       +  BF_KEY ks;
       +  SHA_CTX c;
       +
       +  assert(key->length == 17);
       +
       +  for (i = 0; i < 8; i++)
       +    iv[i] = 0;
       +
       +  BF_set_key(&ks, 16, key->data + 1);
       +
       +  if (mdc) {
       +    mdc = 1;
       +    out->data[0] = 1;
       +  }
       +  rnd_bytes(out->data + mdc, 8);
       +  out->data[8 + mdc] = out->data[6 + mdc], out->data[9 + mdc] = out->data[7 + mdc];
       +  if (mdc) {
       +    SHA1_Init(&c);
       +    SHA1_Update(&c, out->data + 1, 10);
       +    SHA1_Update(&c, in->data, in->length);
       +  }
       +  n = 0;
       +  BF_cfb64_encrypt(out->data + mdc, out->data + mdc, 10, &ks, iv, &n, BF_ENCRYPT);
       +  if (!mdc) {
       +    iv[6] = iv[0], iv[7] = iv[1];
       +    memcpy(iv, out->data + 2, 6);
       +    n = 0;
       +  }
       +  BF_cfb64_encrypt(in->data, out->data + 10 + mdc, in->length, &ks, iv, &n,
       +                     BF_ENCRYPT);
       +  if (mdc) {
       +    SHA1_Update(&c, "\xD3\x14", 2); /* 0xD3 = 0xC0 | PGP_MDC */
       +    BF_cfb64_encrypt("\xD3\x14", out->data + 11 + in->length, 2, &ks, iv, &n,
       +                       BF_ENCRYPT);
       +    SHA1_Final(out->data + 13 + in->length, &c);
       +    BF_cfb64_encrypt(out->data + 13 + in->length, out->data + 13 + in->length, 20, &ks, iv, &n,
       +                       BF_ENCRYPT);
       +  }
       +  return (0);
       +}
       +
       +#ifdef USE_AES
       +static int pgp_aesencrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
       +{
       +  byte iv[16];
       +  int i, n = 0;
       +  AES_KEY ks;
       +  SHA_CTX c;
       +
       +  assert(key->length == 17 || key->length == 25 || key->length == 33);
       +
       +  for (i = 0; i < 16; i++)
       +    iv[i] = 0;
       +
       +  AES_set_encrypt_key(key->data + 1, (key->length-1)<<3, &ks);
       +
       +  if (mdc) {
       +    mdc = 1;
       +    out->data[0] = 1;
       +  }
       +  rnd_bytes(out->data + mdc, 16);
       +  out->data[16 + mdc] = out->data[14 + mdc], out->data[17 + mdc] = out->data[15 + mdc];
       +  if (mdc) {
       +    SHA1_Init(&c);
       +    SHA1_Update(&c, out->data + 1, 18);
       +    SHA1_Update(&c, in->data, in->length);
       +  }
       +  n = 0;
       +  AES_cfb128_encrypt(out->data + mdc, out->data + mdc, 18, &ks, iv, &n, AES_ENCRYPT);
       +  if (!mdc) {
       +    iv[14] = iv[0], iv[15] = iv[1];
       +    memcpy(iv, out->data + 2, 14);
       +    n = 0;
       +  }
       +  AES_cfb128_encrypt(in->data, out->data + 18 + mdc, in->length, &ks, iv, &n,
       +                     AES_ENCRYPT);
       +  if (mdc) {
       +    SHA1_Update(&c, "\xD3\x14", 2); /* 0xD3 = 0xC0 | PGP_MDC */
       +    AES_cfb128_encrypt("\xD3\x14", out->data + 19 + in->length, 2, &ks, iv, &n,
       +                       AES_ENCRYPT);
       +    SHA1_Final(out->data + 21 + in->length, &c);
       +    AES_cfb128_encrypt(out->data + 21 + in->length, out->data + 21 + in->length, 20, &ks, iv, &n,
       +                       AES_ENCRYPT);
       +  }
       +  return (0);
       +}
       +#endif /* USE_AES */
       +
       +int pgp_symmetric(BUFFER *in, BUFFER *key, int mdc)
       +{
       +  BUFFER *out;
       +  int sym;
       +
       +  out = buf_new();
       +  if (pgp_blocklen(sym = buf_getc(key)) > 8)
       +    mdc = 1; /* force MDC for AES */
       +  buf_prepare(out, in->length + (mdc?(1+2+22):2) + pgp_blocklen(sym));
       +  switch (sym) {
       +#ifdef USE_IDEA
       +   case PGP_K_IDEA:
       +    pgp_ideaencrypt(in, out, key, mdc);
       +    break;
       +#endif /* USE_IDEA */
       +#ifdef USE_AES
       +   case PGP_K_AES128:
       +   case PGP_K_AES192:
       +   case PGP_K_AES256:
       +    pgp_aesencrypt(in, out, key, mdc);
       +    break;
       +#endif /* USE_AES */
       +   case PGP_K_3DES:
       +    pgp_3desencrypt(in, out, key, mdc);
       +    break;
       +  case PGP_K_CAST5:
       +    pgp_castencrypt(in, out, key, mdc);
       +    break;
       +  case PGP_K_BF:
       +    pgp_bfencrypt(in, out, key, mdc);
       +    break;
       +   default:
       +    errlog(ERRORMSG, "Unknown symmetric algorithm.\n");
       +  }
       +  pgp_packet(out, mdc?PGP_ENCRYPTEDMDC:PGP_ENCRYPTED);
       +
       +  buf_move(in, out);
       +  buf_free(out);
       +  return (0);
       +}
       +
       +int pgp_literal(BUFFER *b, char *filename, int text)
       +{
       +  BUFFER *out;
       +  BUFFER *line;
       +
       +  if (filename == NULL)
       +    filename = "stdin";
       +
       +  if (strlen(filename) > 255)
       +    return (-1);
       +
       +  out = buf_new();
       +  line = buf_new();
       +
       +  if (text)
       +    buf_setc(out, 't');
       +  else
       +    buf_setc(out, 'b');
       +  buf_appendc(out, strlen(filename));
       +  buf_appends(out, filename);
       +  buf_appendl(out, 0);                /* timestamp */
       +
       +  if (b->length > 0) {
       +    if (text)
       +      while (buf_getline(b, line) != -1) {
       +        buf_cat(out, line);
       +        buf_appends(out, "\r\n");
       +      } else
       +        buf_cat(out, b);
       +  }
       +  pgp_packet(out, PGP_LITERAL);
       +  buf_move(b, out);
       +  buf_free(out);
       +  buf_free(line);
       +
       +  return (0);
       +}
       +
       +int pgp_compress(BUFFER *in)
       +{
       +  int err;
       +  BUFFER *out;
       +
       +  out = buf_new();
       +  buf_setc(out, 1);
       +  err = buf_zip(out, in, 13);
       +  if (err == 0) {
       +    pgp_packet3(out, PGP_COMPRESSED);
       +    buf_move(in, out);
       +  }
       +  buf_free(out);
       +  return (err);
       +}
       +
       +int pgp_sessionkey(BUFFER *out, BUFFER *user, BUFFER *keyid, BUFFER *seskey,
       +                   char *pubring)
       +{
       +  BUFFER *encrypt, *key, *id;
       +  int algo, sym, err = -1;
       +  int i, csum = 0;
       +  int tempbuf = 0;
       +
       +  encrypt = buf_new();
       +  key = buf_new();
       +  id = buf_new();
       +  if (keyid == NULL) {
       +    keyid = buf_new();
       +    tempbuf = 1;
       +  }
       +  sym = seskey->data[0];
       +  if ((algo = pgpdb_getkey(PK_ENCRYPT, PGP_ANY, &sym, NULL, NULL, key, user, NULL, keyid,
       +                           pubring, NULL)) == -1)
       +    goto end;
       +
       +  buf_setc(out, 3);                /* type */
       +  buf_cat(out, keyid);
       +  buf_appendc(out, algo);        /* algorithm */
       +
       +  buf_set(encrypt, seskey);
       +
       +  for (i = 1; i < encrypt->length; i++)
       +    csum = (csum + encrypt->data[i]) % 65536;
       +  buf_appendi(encrypt, csum);
       +
       +  switch (algo) {
       +  case PGP_ES_RSA:
       +    err = pgp_rsa(encrypt, key, PK_ENCRYPT);
       +    mpi_put(out, encrypt);
       +    break;
       +   case PGP_E_ELG:
       +    err = pgp_elgencrypt(encrypt, key);
       +    buf_cat(out, encrypt);
       +    break;
       +  default:
       +    errlog(NOTICE, "Unknown encryption algorithm.\n");
       +    err = -1;
       +    goto end;
       +  }
       +  if (err == -1) {
       +    errlog(ERRORMSG, "Encryption failed!\n");
       +    goto end;
       +  }
       +  pgp_packet(out, PGP_SESKEY);
       +end:
       +  if (tempbuf)
       +    buf_free(keyid);
       +  buf_free(id);
       +  buf_free(encrypt);
       +  buf_free(key);
       +  return (err);
       +}
       +
       +void pgp_marker(BUFFER *out)
       +{
       +  buf_clear(out);
       +  buf_append(out, "PGP", 3);
       +  pgp_packet(out, PGP_MARKER);
       +}
       +
       +int pgp_symsessionkey(BUFFER *out, BUFFER *seskey, BUFFER *pass)
       +{
       +  BUFFER *key;
       +  int sym;
       +  key = buf_new();
       +
       +  sym = seskey->data[0];
       +  buf_setc(out, 4); /* version */
       +#ifdef MIMICPGP5
       +  pgp_makesk(out, key, sym, 1, PGP_H_MD5, pass);
       +#else /* end of MIMICPGP5 */
       +  pgp_makesk(out, key, sym, 3, PGP_H_SHA1, pass);
       +#endif /* else if not MIMICPGP5 */
       +  if (seskey->length > 1)
       +    buf_cat(out, seskey);
       +  else {
       +    buf_setc(seskey, sym);
       +    buf_cat(seskey, key);
       +  }
       +  pgp_packet(out, PGP_SYMSESKEY);
       +  buf_free(key);
       +  return (0);
       +}
       +
       +int pgp_digest(int hashalgo, BUFFER *in, BUFFER *d)
       +{
       +  switch (hashalgo) {
       +   case PGP_H_MD5:
       +    digest_md5(in, d);
       +    return (0);
       +   case PGP_H_SHA1:
       +    digest_sha1(in, d);
       +    return (0);
       +  case PGP_H_RIPEMD:
       +    digest_rmd160(in, d);
       +    return (0);
       +   default:
       +    return (-1);
       +  }
       +}
       +
       +int asnprefix(BUFFER *b, int hashalgo)
       +{
       +  switch (hashalgo) {
       +  case PGP_H_MD5:
       +    buf_append(b, MD5PREFIX, sizeof(MD5PREFIX) - 1);
       +    return (0);
       +  case PGP_H_SHA1:
       +    buf_append(b, SHA1PREFIX, sizeof(SHA1PREFIX) - 1);
       +    return (0);
       +  default:
       +    return (-1);
       +  }
       +}
       +
       +int pgp_expandsk(BUFFER *key, int skalgo, int hashalgo, BUFFER *data)
       +{
       +  BUFFER *temp;
       +  int keylen;
       +  int err = 0;
       +  temp = buf_new();
       +
       +  keylen = pgp_keylen(skalgo);
       +  buf_clear(key);
       +  while (key->length < keylen) {
       +    if (pgp_digest(hashalgo, data, temp) == -1) {
       +      err = -1;
       +      goto end;
       +    }
       +    buf_cat(key, temp);
       +
       +    buf_setc(temp, 0);
       +    buf_cat(temp, data);
       +    buf_move(data, temp);
       +  }
       +
       +  if (key->length > keylen) {
       +    buf_set(temp, key);
       +    buf_get(temp, key, keylen);
       +  }
       + end:
       +  buf_free(temp);
       +  return(err);
       +}
       +
       +int pgp_makesk(BUFFER *out, BUFFER *key, int sym, int type, int hash,
       +               BUFFER *pass)
       +{
       +  int err = 0;
       +  BUFFER *salted;
       +  salted = buf_new();
       +
       +  buf_appendc(out, sym);
       +  buf_appendc(out, type);
       +  buf_appendc(out, hash);
       +  switch (type) {
       +  case 0:
       +    buf_set(salted, pass);
       +    break;
       +  case 1:
       +    buf_appendrnd(salted, 8); /* salt */
       +    buf_cat(out, salted);
       +    buf_cat(salted, pass);
       +    break;
       +  case 3:
       +    buf_appendrnd(salted, 8); /* salt */
       +    buf_cat(out, salted);
       +    buf_appendc(out, 96); /* encoded count value 65536 */
       +    pgp_iteratedsk(salted, salted, pass, 96);
       +    break;
       +  default:
       +    err = -1;
       +  }
       +  pgp_expandsk(key, sym, hash, salted);
       +  buf_free(salted);
       +  return (err);
       +}
       +
       +/* PGP/MIME needs to know the hash algorithm */
       +int pgp_signhashalgo(BUFFER *algo, BUFFER *userid, char *secring, BUFFER *pass)
       +{
       +  int pkalgo;
       +
       +  pkalgo = pgpdb_getkey(PK_SIGN, PGP_ANY, NULL, NULL, NULL, NULL, userid, NULL, NULL,
       +                        secring, pass);
       +  if (pkalgo == PGP_S_DSA)
       +    buf_sets(algo, "sha1");
       +  if (pkalgo == PGP_ES_RSA)
       +    buf_sets(algo, "md5");
       +  return (pkalgo > 0 ? 0 : -1);
       +}
       +
       +int pgp_sign(BUFFER *msg, BUFFER *msg2, BUFFER *sig, BUFFER *userid,
       +             BUFFER *pass, int type, int self, long now, int remail,
       +             BUFFER *keypacket, char *secring)
       +/*  msg:      data to be signed (buffer is modified)
       +    msg2:     additional data to be signed for certain sig types
       +    sig:      signature is placed here
       +    userid:   select signing key
       +    pass:     pass phrase for signing key
       +    type:     PGP signature type
       +    self:     is this a self-signature?
       +    now:      time of signature creation
       +    remail:   is this an anonymous message?
       +    keypacket: signature key
       +    secring:   key ring with signature key */
       +{
       +  BUFFER *key, *id, *d, *sub, *enc;
       +  int algo, err = -1;
       +  int version = 3, hashalgo;
       +  int type1;
       +
       +  id = buf_new();
       +  d = buf_new();
       +  sub = buf_new();
       +  enc = buf_new();
       +  key = buf_new();
       +
       +  if (now == 0) {
       +    now = time(NULL);
       +    if (remail)
       +      now -= rnd_number(4 * 24 * 60 * 60);
       +  }
       +  if (keypacket) {
       +    buf_rewind(keypacket);
       +    algo = pgp_getkey(PK_SIGN, PGP_ANY, NULL, NULL, NULL, keypacket, key, id, NULL, pass);
       +  } else
       +    algo = pgpdb_getkey(PK_SIGN, PGP_ANY, NULL, NULL, NULL, key, userid, NULL, id, secring,
       +                        pass);
       +  if (algo <= -1) {
       +    err = algo;
       +    goto end;
       +  }
       +  if (algo == PGP_S_DSA || algo == PGP_E_ELG)
       +    version = 4;
       +  if (version == 3)
       +    hashalgo = PGP_H_MD5;
       +  else
       +    hashalgo = PGP_H_SHA1;
       +
       +  if (!self && type != PGP_SIG_BINDSUBKEY)
       +    version = 3;
       +
       +  switch (type) {
       +   case PGP_SIG_CERT:
       +   case PGP_SIG_CERT1:
       +   case PGP_SIG_CERT2:
       +   case PGP_SIG_CERT3:
       +     type1 = pgp_getpacket(msg, d) == PGP_PUBKEY;
       +     assert (type1);
       +     buf_setc(msg, 0x99);
       +     buf_appendi(msg, d->length);
       +     buf_cat(msg, d);
       +
       +     pgp_getpacket(msg2, d);
       +     switch (version) {
       +     case 3:
       +       buf_cat(msg, d);
       +       break;
       +     case 4:
       +       buf_appendc(msg, 0xb4);
       +       buf_appendl(msg, d->length);
       +       buf_cat(msg, d);
       +       break;
       +     }
       +     break;
       +   case PGP_SIG_BINDSUBKEY:
       +     type1 = pgp_getpacket(msg, d) == PGP_PUBKEY;
       +     assert (type1);
       +     buf_clear(msg);
       +     buf_appendc(msg, 0x99);
       +     buf_appendi(msg, d->length);
       +     buf_cat(msg, d);
       +
       +     type1 = pgp_getpacket(msg2, d) == PGP_PUBSUBKEY;
       +     assert (type1);
       +     buf_appendc(msg, 0x99);
       +     buf_appendi(msg, d->length);
       +     buf_cat(msg, d);
       +     break;
       +   case PGP_SIG_BINARY:
       +     break;
       +   case PGP_SIG_CANONIC:
       +    pgp_sigcanonic(msg);
       +    break;
       +   default:
       +    NOT_IMPLEMENTED;
       +  }
       +  switch (version) {
       +   case 3:
       +    buf_set(d, msg);
       +    buf_appendc(d, type);
       +    buf_appendl(d, now);
       +    pgp_digest(hashalgo, d, d);
       +    if (algo == PGP_ES_RSA)
       +      asnprefix(enc, hashalgo);
       +    buf_cat(enc, d);
       +    err = pgp_dosign(algo, enc, key);
       +
       +    buf_setc(sig, version);
       +    buf_appendc(sig, 5);
       +    buf_appendc(sig, type);
       +    buf_appendl(sig, now);
       +    buf_cat(sig, id);
       +    buf_appendc(sig, algo);
       +    buf_appendc(sig, hashalgo);
       +    buf_append(sig, d->data, 2);
       +    buf_cat(sig, enc);
       +    break;
       +
       +   case 4:
       +    buf_setc(sig, version);
       +    buf_appendc(sig, type);
       +    buf_appendc(sig, algo);
       +    buf_appendc(sig, hashalgo);
       +
       +    buf_clear(d);
       +    buf_appendl(d, now);
       +    pgp_subpacket(d, PGP_SUB_CREATIME);
       +    buf_cat(sub, d);
       +
       +    if (self || type == PGP_SIG_BINDSUBKEY) {
       +      /* until we can handle the case where our pgp keys expire, don't create keys that expire */
       +      if (0 && KEYLIFETIME) { /* add key expirtaion time */
       +        buf_clear(d);
       +        buf_appendl(d, KEYLIFETIME);
       +        pgp_subpacket(d, PGP_SUB_KEYEXPIRETIME);
       +        buf_cat(sub, d);
       +      }
       +    }
       +
       +    if (self) {
       +      buf_setc(d, PGP_K_CAST5);
       +#ifdef USE_AES
       +      buf_appendc(d, PGP_K_AES128);
       +#endif /* USE_AES */
       +      buf_appendc(d, PGP_K_3DES);
       +      pgp_subpacket(d, PGP_SUB_PSYMMETRIC);
       +      buf_cat(sub, d);
       +
       +      buf_setc(d, 0x01); /* now we support MDC, so we can add MDC flag */
       +      pgp_subpacket(d, PGP_SUB_FEATURES);
       +      buf_cat(sub, d);
       +    }
       +
       +    buf_appendi(sig, sub->length); /* hashed subpacket length */
       +    buf_cat(sig, sub);
       +
       +    /* compute message digest */
       +    buf_set(d, msg);
       +    buf_cat(d, sig);
       +    buf_appendc(d, version);
       +    buf_appendc(d, 0xff);
       +    buf_appendl(d, sig->length);
       +    pgp_digest(hashalgo, d, d);
       +
       +    pgp_subpacket(id, PGP_SUB_ISSUER);
       +    buf_appendi(sig, id->length); /* unhashed subpacket length */
       +    buf_cat(sig, id);
       +
       +    buf_append(sig, d->data, 2);
       +
       +    if (algo == PGP_ES_RSA)
       +      asnprefix(enc, hashalgo);
       +    buf_cat(enc, d);
       +    err = pgp_dosign(algo, enc, key);
       +    buf_cat(sig, enc);
       +    break;
       +  }
       +  pgp_packet(sig, PGP_SIG);
       +
       +end:
       +  buf_free(key);
       +  buf_free(id);
       +  buf_free(d);
       +  buf_free(sub);
       +  buf_free(enc);
       +  return (err);
       +}
       +
       +int pgp_pubkeycert(BUFFER *userid, char *keyring, BUFFER *pass,
       +                   BUFFER *out, int remail)
       +{
       +  BUFFER *key;
       +  KEYRING *r;
       +  int err = -1;
       +
       +  key = buf_new();
       +  r = pgpdb_open(keyring, pass, 0, PGP_TYPE_UNDEFINED);
       +  if (r != NULL)
       +    while (pgpdb_getnext(r, key, NULL, userid) != -1) {
       +      if (pgp_makepubkey(key, NULL, out, pass, 0) != -1)
       +        err = 0;
       +    }
       +  if (err == 0)
       +    pgp_armor(out, remail);
       +  else
       +    buf_clear(out);
       +  buf_free(key);
       +  return (err);
       +}
       +
       +#endif /* USE_PGP */
   DIR diff --git a/Src/pgpdata.c b/Src/pgpdata.c
       t@@ -0,0 +1,1539 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   OpenPGP data
       +   $Id: pgpdata.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#ifdef USE_PGP
       +#include "pgp.h"
       +#include "crypto.h"
       +#include <assert.h>
       +#include <time.h>
       +#include <string.h>
       +
       +int pgp_keylen(int symalgo)
       +{
       +  switch (symalgo) {
       +#ifdef USE_AES
       +  case PGP_K_AES256:
       +    return (32);
       +  case PGP_K_AES192:
       +    return (24);
       +  case PGP_K_AES128:
       +#endif /* USE_AES */
       +  case PGP_K_IDEA:
       +  case PGP_K_CAST5:
       +  case PGP_K_BF:
       +    return (16);
       +  case PGP_K_3DES:
       +    return (24);
       +  default:
       +    return (0);
       +  }
       +}
       +
       +int pgp_blocklen(int symalgo)
       +{
       +  switch (symalgo) {
       +#ifdef USE_AES
       +  case PGP_K_AES256:
       +  case PGP_K_AES192:
       +  case PGP_K_AES128:
       +    return (16);
       +#endif /* USE_AES */
       +  case PGP_K_IDEA:
       +  case PGP_K_CAST5:
       +  case PGP_K_BF:
       +  case PGP_K_3DES:
       +    return (8);
       +  default:
       +    return (16);
       +  }
       +}
       +
       +int mpi_get(BUFFER *b, BUFFER *mpi)
       +{
       +  int l;
       +
       +  l = buf_geti(b);
       +  buf_clear(mpi);
       +
       +  if (l <= 0 || b->ptr + (l + 7) / 8 > b->length)
       +    return (-1);
       +  buf_get(b, mpi, (l + 7) / 8);
       +  return (l);
       +}
       +
       +
       +int mpi_bitcount(BUFFER *mpi)
       +{
       +  int i, l;
       +  while (!mpi->data[0] && mpi->length) /* remove leading zeros from mpi */
       +    memmove(mpi->data, mpi->data+1, --mpi->length);
       +  l = mpi->length * 8;
       +  for (i = 7; i >= 0; i--)
       +    if (((mpi->data[0] >> i) & 1) == 1) {
       +      l -= 7 - i;
       +      break;
       +    }
       +  return l;
       +}
       +
       +int mpi_put(BUFFER *b, BUFFER *mpi)
       +{
       +  buf_appendi(b, mpi_bitcount(mpi));
       +  buf_cat(b, mpi);
       +  return (0);
       +}
       +
       +int skcrypt(BUFFER *data, int skalgo, BUFFER *key, BUFFER *iv, int enc)
       +{
       +  switch (skalgo) {
       +  case 0:
       +    return (0);
       +#ifdef USE_IDEA
       +  case PGP_K_IDEA:
       +    return (buf_ideacrypt(data, key, iv, enc));
       +#endif /* USE_IDEA */
       +#ifdef USE_AES
       +  case PGP_K_AES128:
       +  case PGP_K_AES192:
       +  case PGP_K_AES256:
       +    return (buf_aescrypt(data, key, iv, enc));
       +#endif /* USE_AES */
       +  case PGP_K_3DES:
       +    return (buf_3descrypt(data, key, iv, enc));
       +  case PGP_K_BF:
       +    return (buf_bfcrypt(data, key, iv, enc));
       +  case PGP_K_CAST5:
       +    return (buf_castcrypt(data, key, iv, enc));
       +  default:
       +    return (-1);
       +  }
       +}
       +
       +int pgp_csum(BUFFER *key, int start)
       +{
       +  int i, csum = 0;
       +  for (i = start; i < key->length; i++)
       +    csum = (csum + key->data[i]) % 65536;
       +  return (csum);
       +}
       +
       +int pgp_rsa(BUFFER *in, BUFFER *k, int mode)
       +{
       +  BUFFER *mpi, *out;
       +  int err = -1;
       +  RSA *key;
       +
       +  assert(mode == PK_ENCRYPT || mode == PK_VERIFY || mode == PK_DECRYPT
       +         || mode == PK_SIGN);
       +  key = RSA_new();
       +  out = buf_new();
       +  mpi = buf_new();
       +
       +  mpi_get(k, mpi);
       +  key->n = BN_bin2bn(mpi->data, mpi->length, NULL);
       +
       +  if (mpi_get(k, mpi) < 0)
       +    goto end;
       +  key->e = BN_bin2bn(mpi->data, mpi->length, NULL);
       +
       +  if (mode == PK_DECRYPT || mode == PK_SIGN) {
       +    if (mpi_get(k, mpi) < 0)
       +      goto end;
       +    key->d = BN_bin2bn(mpi->data, mpi->length, NULL);
       +
       +#if 1
       +    /* compute auxiluary parameters */
       +    mpi_get(k, mpi);                /* PGP'p is SSLeay's q */
       +    key->q = BN_bin2bn(mpi->data, mpi->length, NULL);
       +
       +    mpi_get(k, mpi);
       +    key->p = BN_bin2bn(mpi->data, mpi->length, NULL);
       +
       +    if (mpi_get(k, mpi) < 0)
       +      goto end;
       +    key->iqmp = BN_bin2bn(mpi->data, mpi->length, NULL);
       +
       +    {
       +      BIGNUM *i;
       +      BN_CTX *ctx;
       +
       +      ctx = BN_CTX_new();
       +      i = BN_new();
       +      key->dmp1 = BN_new();
       +      key->dmq1 = BN_new();
       +
       +      BN_sub(i, key->p, BN_value_one());
       +      BN_mod(key->dmp1, key->d, i, ctx);
       +
       +      BN_sub(i, key->q, BN_value_one());
       +      BN_mod(key->dmq1, key->d, i, ctx);
       +
       +      BN_free(i);
       +    }
       +#endif /* 1 */
       +  }
       +  buf_prepare(out, RSA_size(key));
       +
       +  switch (mode) {
       +  case PK_ENCRYPT:
       +    out->length = RSA_public_encrypt(in->length, in->data, out->data, key,
       +                                     RSA_PKCS1_PADDING);
       +    break;
       +  case PK_VERIFY:
       +    out->length = RSA_public_decrypt(in->length, in->data, out->data, key,
       +                                     RSA_PKCS1_PADDING);
       +    break;
       +  case PK_SIGN:
       +    out->length = RSA_private_encrypt(in->length, in->data, out->data, key,
       +                                      RSA_PKCS1_PADDING);
       +    break;
       +  case PK_DECRYPT:
       +    out->length = RSA_private_decrypt(in->length, in->data, out->data, key,
       +                                      RSA_PKCS1_PADDING);
       +    break;
       +  }
       +  if (out->length == -1)
       +    err = -1, out->length = 0;
       +  else
       +    err = 0;
       +
       +  buf_move(in, out);
       +end:
       +  RSA_free(key);
       +  buf_free(out);
       +  buf_free(mpi);
       +  return (err);
       +}
       +
       +/* Contrary to RFC 2440, old PGP versions use this for clearsign only.
       + * If the text is included in the OpenPGP message, the application will
       + * typically provide the text in the proper format (whatever that is);
       + * we use "canonic" format so everybody will be able to read our messages.
       + * In clearsigned messages, trailing whitespace is always ignored.
       + * Detached signatures are the problematic case. For PGP/MIME, we always
       + * escape trailing whitespace as quoted-printable.
       + */
       +void pgp_sigcanonic(BUFFER *msg)
       +{
       +  BUFFER *line, *out;
       +
       +  out = buf_new();
       +  line = buf_new();
       +
       +  while (buf_getline(msg, line) != -1) {
       +    while (line->length > 0 && (line->data[line->length - 1] == ' '
       +#if 0
       +                                || line->data[line->length - 1] == '\t'
       +#endif /* 0 */
       +        ))
       +      line->length--;
       +    line->data[line->length] = '\0';
       +    buf_cat(out, line);
       +    buf_appends(out, "\r\n");
       +  }
       +  buf_move(msg, out);
       +  buf_free(out);
       +  buf_free(line);
       +}
       +
       +static void mpi_bnput(BUFFER *o, BIGNUM *i)
       +{
       +  BUFFER *b;
       +
       +  b = buf_new();
       +  buf_prepare(b, BN_num_bytes(i));
       +  b->length = BN_bn2bin(i, b->data);
       +  mpi_put(o, b);
       +  buf_free(b);
       +}
       +
       +static void mpi_bnputenc(BUFFER *o, BIGNUM *i, int ska, BUFFER *key,
       +                         BUFFER *iv)
       +{
       +  BUFFER *b;
       +  int ivlen = iv->length;
       +
       +  b = buf_new();
       +  buf_prepare(b, BN_num_bytes(i));
       +  b->length = BN_bn2bin(i, b->data);
       +  buf_appendi(o, mpi_bitcount(b));
       +  if (key && key->length) {
       +    skcrypt(b, ska, key, iv, ENCRYPT);
       +    buf_clear(iv);
       +    buf_append(iv, b->data+b->length-ivlen, ivlen);
       +  }
       +  buf_cat(o, b);
       +  buf_free(b);
       +}
       +
       +static int getski(BUFFER *p, BUFFER *pass, BUFFER *key, BUFFER *iv)
       +{
       +  int skalgo;
       +  BUFFER *salt, *temp;
       +
       +  if (!pass)
       +    return(-1);
       +
       +  salt = buf_new();
       +  temp = buf_new();
       +
       +  skalgo = buf_getc(p);
       +  switch (skalgo) {
       +  case 0:
       +    /* none */
       +    goto end;
       +  case 255:
       +    /* S2K specifier */
       +    skalgo = pgp_getsk(p, pass, key);
       +    break;
       +  default:
       +    /* simple */
       +    digest_md5(pass, key);
       +    break;
       +  }
       +
       +  buf_get(p, iv, pgp_blocklen(skalgo));
       +
       + end:
       +  buf_free(salt);
       +  buf_free(temp);
       +  return (skalgo);
       +}
       +
       +static void makeski(BUFFER *secret, BUFFER *pass, int remail)
       +{
       +  BUFFER *out, *key, *iv;
       +  out = buf_new();
       +  key = buf_new();
       +  iv = buf_new();
       +  if (pass == NULL || pass->length == 0 || remail == 2) {
       +    buf_appendc(out, 0);
       +    buf_cat(out, secret);
       +  } else {
       +    buf_appendc(out, 255);
       +    pgp_makesk(out, key, PGP_K_CAST5, 3, PGP_H_SHA1, pass);
       +    buf_setrnd(iv, pgp_blocklen(PGP_K_CAST5));
       +    buf_cat(out, iv);
       +    skcrypt(secret, PGP_K_CAST5, key, iv, 1);
       +    buf_cat(out, secret);
       +  }
       +  buf_move(secret, out);
       +  buf_free(out);
       +  buf_free(key);
       +  buf_free(iv);
       +}
       +
       +int pgp_nummpi(int algo)
       +{
       +  switch (algo) {
       +   case PGP_ES_RSA:
       +    return (2);
       +   case PGP_S_DSA:
       +    return (4);
       +   case PGP_E_ELG:
       +    return (3);
       +   default:
       +    return (0);
       +  }
       +}
       +
       +int pgp_numsecmpi(int algo)
       +{
       +  switch (algo) {
       +   case PGP_ES_RSA:
       +    return (4);
       +   case PGP_S_DSA:
       +    return (1);
       +   case PGP_E_ELG:
       +    return (1);
       +   default:
       +    return (0);
       +  }
       +}
       +
       +/* store key's ID in keyid */
       +int pgp_keyid(BUFFER *key, BUFFER *keyid)
       +{
       +  BUFFER *i, *k;
       +  int version, algo, j, ptr;
       +
       +  i = buf_new();
       +  k = buf_new();
       +
       +  ptr = key->ptr;
       +  key->ptr = 0;
       +  switch (version = buf_getc(key)) {
       +  case 2:
       +  case 3:
       +    buf_getl(key);
       +    buf_geti(key);
       +    buf_getc(key);
       +    mpi_get(key, i);
       +    break;
       +  case 4:
       +    buf_appendc(k, version);
       +    buf_appendl(k, buf_getl(key));
       +    algo = buf_getc(key);
       +    buf_appendc(k, algo);
       +    if (pgp_nummpi(algo) == 0)
       +      buf_rest(k, key); /* works for public keys only */
       +    else
       +      for (j = 0; j < pgp_nummpi(algo); j++) {
       +        mpi_get(key, i);
       +        mpi_put(k, i);
       +      }
       +    buf_clear(i);
       +    buf_appendc(i, 0x99);
       +    buf_appendi(i, k->length);
       +    buf_cat(i, k);
       +    digest_sha1(i, i);
       +    break;
       +  }
       +  buf_clear(keyid);
       +  buf_append(keyid, i->data + i->length - 8, 8);
       +  buf_free(i);
       +  buf_free(k);
       +  key->ptr = ptr;
       +  return(0);
       +}
       +
       +static int pgp_iskeyid(BUFFER *key, BUFFER *keyid)
       +{
       +  BUFFER *thisid;
       +  int ret;
       +
       +  thisid = buf_new();
       +  pgp_keyid(key, thisid);
       +  ret = buf_eq(keyid, thisid);
       +  buf_free(thisid);
       +  return(ret);
       +}
       +
       +static int pgp_get_sig_subpacket(BUFFER * p1, BUFFER *out)
       +{
       +  int suptype, len = buf_getc(p1);
       +  if (len > 192 && len < 255)
       +    len = (len - 192) * 256 + buf_getc(p1) + 192;
       +  else if (len == 255)
       +    len = buf_getl(p1);
       +  suptype = buf_getc(p1);
       +  if (len)
       +    buf_get(p1, out, len-1); /* len-1 - exclude type */
       +  else
       +    buf_clear(out);
       +  return suptype;
       +}
       +
       +typedef struct _UIDD {
       +  struct _UIDD * next;
       +  long created, expires;
       +  int revoked, sym, mdc, uid, primary;
       +  BUFFER *uidstr;
       +} UIDD;
       +
       +static UIDD * new_uidd_c(UIDD *uidd_c, int uidno)
       +{
       +  UIDD * tmp;
       +
       +  if (!uidd_c || uidd_c->uid < uidno) {
       +    tmp = (UIDD *)malloc(sizeof(UIDD));
       +    if (!tmp)
       +        return uidd_c;
       +    if (uidd_c) {
       +      uidd_c->next = tmp;
       +      uidd_c = uidd_c->next;
       +    } else
       +      uidd_c = tmp;
       +    if (uidd_c) {
       +      memset(uidd_c, 0, sizeof(UIDD));
       +      uidd_c->uid = uidno;
       +    }
       +  }
       +  return uidd_c;
       +}
       +
       +int pgp_getkey(int mode, int algo, int *psym, int *pmdc, long *pexpires, BUFFER *keypacket, BUFFER *key,
       +               BUFFER *keyid, BUFFER *userid, BUFFER *pass)
       +/* IN:  mode   - PK_SIGN, PK_VERIFY, PK_DECRYPT, PK_ENCRYPT
       + *        algo   - PGP_ANY, PGP_ES_RSA, PGP_E_ELG, PGP_S_DSA
       + *        psym   - reyested sym PGP_K_ANY, PGP_K_IDEA, PGP_K_3DES, ... or NULL
       + *        pass   - passprase or NULL
       + *        keypacket - key, with key uid sig subkey packets, possibly encrypted
       + *        keyid  - reyested (sub)keyid or empty buffer or NULL
       + * OUT: psym   - found sym algo (or NULL)
       + *        pmdc   - found mdc flag (or NULL)
       + *        key    - found key, only key packet, decrypted
       + *                   may be the same buffer as keypacket (or NULL)
       + *        keyid  - found (sub)keyid (or NULL)
       + *        userid - found userid (or NULL)
       + *        pexpires - expiry time, or 0 if don't expire (or NULL)
       + */
       +{
       +  int tempbuf = 0, dummykey = 0;
       +  int keytype = -1, type, j;
       +  int thisalgo = 0, version, skalgo;
       +  int needsym = 0, symfound = 0, mdcfound = 0;
       +  BUFFER *p1, *iv, *sk, *i, *thiskeyid, *mainkeyid;
       +  int ivlen;
       +  int csstart;
       +  long now = time(NULL);
       +  long created = 0, expires = 0, subexpires = 0;
       +  int uidno = 0, primary = 0, subkeyno = 0, subkeyok = 0;
       +  UIDD * uidd_1 = NULL, * uidd_c = NULL;
       +
       +  p1 = buf_new();
       +  i = buf_new();
       +  iv = buf_new();
       +  sk = buf_new();
       +  thiskeyid = buf_new();
       +  mainkeyid = buf_new();
       +  if (psym)
       +    needsym = *psym;
       +  if (keypacket == key) {
       +    key = buf_new();
       +    tempbuf = 1;
       +  }
       +  if (! key) {
       +    key = buf_new();
       +    dummykey = 1;
       +  };
       +  if (userid)
       +    buf_clear(userid);
       +
       +  while ((type = pgp_getpacket(keypacket, p1)) > 0) {
       +    switch (type) {
       +    case PGP_SIG:
       +    {
       +      /* it is assumed that only valid keys have been imported */
       +      long a;
       +      int self = 0, certexpires = 0, suptype;
       +      int sigtype = 0, sigver = buf_getc(p1);
       +      created = 0, expires = 0, primary = 0;
       +      if (sigver == 4) {
       +         sigtype = buf_getc(p1);
       +        if (isPGP_SIG_CERT(sigtype) || sigtype == PGP_SIG_BINDSUBKEY || sigtype == PGP_SIG_CERTREVOKE) {
       +          int revoked = (sigtype == PGP_SIG_CERTREVOKE), sym = PGP_K_3DES, mdc = 0;
       +          buf_getc(p1); /* pk algo */
       +          buf_getc(p1); /* hash algo */
       +          j = buf_geti(p1); /* length of hashed signature subpackets */
       +          j += p1->ptr;
       +          while (p1->ptr < j) {
       +            suptype = pgp_get_sig_subpacket(p1, i);
       +            switch (suptype & 0x7F) {
       +            case PGP_SUB_PSYMMETRIC:
       +              while ((a = buf_getc(i)) != -1)
       +                if ((a == PGP_K_3DES || a == PGP_K_CAST5 || a == PGP_K_BF
       +#ifdef USE_IDEA
       +                     || a == PGP_K_IDEA
       +#endif /* USE_IDEA */
       +#ifdef USE_AES
       +                     || a ==  PGP_K_AES128 || a ==  PGP_K_AES192 || a ==  PGP_K_AES256
       +#endif /* USE_AES */
       +                     ) && (a == needsym || needsym == PGP_K_ANY)) {
       +                  sym = a;
       +                  break; /* while ((a = buf_getc(i)) != -1) */
       +                } /* if ((a == PGP_K_3DES)... */
       +              break;
       +            case PGP_SUB_FEATURES:
       +              if ((a = buf_getc(i)) != -1)
       +                if (a & 0x01)
       +                  mdc = 1;
       +              break;
       +            case PGP_SUB_CREATIME:
       +              if ((a = buf_getl(i)) != -1)
       +                created = a;
       +              break;
       +            case PGP_SUB_KEYEXPIRETIME:
       +              if ((a = buf_getl(i)) != -1)
       +                expires = a;
       +              break;
       +            case PGP_SUB_CERTEXPIRETIME:
       +              if ((a = buf_getl(i)) != -1)
       +                certexpires = a;
       +              break;
       +            case PGP_SUB_ISSUER: /* ISSUER normaly is in unhashed data, but check anyway */
       +              if (i->length == 8)
       +                self = buf_eq(i, mainkeyid);
       +              break;
       +            case PGP_SUB_PRIMARY:
       +              if ((a = buf_getl(i)) != -1)
       +                primary = a;
       +              break;
       +            default:
       +              if (suptype & 0x80) {
       +                ; /* "critical" bit set! now what? */
       +              }
       +            } /* switch (suptype) */
       +          } /* while (p1->ptr < j) */
       +          if (p1->ptr == j) {
       +              j = buf_geti(p1); /* length of unhashed signature subpackets */
       +              j += p1->ptr;
       +              while (p1->ptr < j) {
       +                suptype = pgp_get_sig_subpacket(p1, i);
       +                if (suptype == PGP_SUB_ISSUER) {
       +                  if (i->length == 8)
       +                    self = buf_eq(i, mainkeyid);
       +                } /* if (suptype == PGP_SUB_ISSUER) */
       +              } /* while (p1->ptr < j) #2 */
       +          } /* if (p1->ptr == j) */
       +          if (p1->ptr != j) /* sig damaged ? */
       +            break; /* switch (type) */
       +          if (self) {
       +            if (certexpires)
       +                certexpires = ((created + certexpires < now) || (created + certexpires < 0));
       +            if ((isPGP_SIG_CERT(sigtype) && !certexpires) || sigtype == PGP_SIG_CERTREVOKE) {
       +              uidd_c = new_uidd_c(uidd_c, uidno);
       +              if (!uidd_1)
       +                uidd_1 = uidd_c;
       +              if (uidd_c && uidd_c->uid == uidno) {
       +                if (uidd_c->created <= created) {
       +                  /* if there is several selfsigs on that uid, find the newest one */
       +                  uidd_c->created = created;
       +                  uidd_c->expires = expires;
       +                  uidd_c->revoked = revoked;
       +                  uidd_c->primary = primary;
       +                  uidd_c->sym = sym;
       +                  uidd_c->mdc = mdc;
       +                }
       +              }
       +            } /* if ((isPGP_SIG_CERT(sigtype) && !certexpires) || sigtype == PGP_SIG_CERTREVOKE) */
       +            else if (sigtype == PGP_SIG_BINDSUBKEY) {
       +              if (!subkeyok) {
       +                subexpires = expires ? created + expires : 0;
       +                if (expires && ((created + expires < now) || (created + expires < 0))) {
       +                  if (mode == PK_ENCRYPT) { /* allow decrypt with expired subkeys, but not encrypt */
       +                    keytype = -1;
       +                  }
       +                }
       +                if (keytype != -1)
       +                  subkeyok = subkeyno;
       +              }
       +            } /* if (sigtype == PGP_SIG_BINDSUBKEY) */
       +          } /* if (self) */
       +        } /* if (isPGP_SIG_CERT(sigtype) || sigtype == PGP_SIG_BINDSUBKEY || sigtype == PGP_SIG_CERTREVOKE) */
       +      } /* if (sigver == 4) */
       +      else if (sigver == 2 || sigver == 3) {
       +        buf_getc(p1); /* One-octet length of following hashed material.  MUST be 5 */
       +        sigtype = buf_getc(p1);
       +      } /* if (sigver == 2 || sigver == 3) */
       +      if (sigtype == PGP_SIG_KEYREVOKE) {
       +        /* revocation can be either v3 or v4. if v4 we could check issuer, but we don't do it... */
       +        if (mode == PK_SIGN || mode == PK_ENCRYPT) { /* allow verify and decrypt with revokeded keys, but not sign and encrypt */
       +          keytype = -1;
       +        }
       +      } /* if (sigtype == PGP_SIG_KEYREVOKE) */
       +      else if (sigtype == PGP_SIG_SUBKEYREVOKE) {
       +      if (!subkeyok || subkeyok == subkeyno)
       +          if (mode == PK_ENCRYPT) { /* allow decrypt with revokeded subkeys, but not encrypt */
       +            keytype = -1;
       +          }
       +      } /* if (sigtype == PGP_SIG_SUBKEYREVOKE) */
       +      break; /* switch (type) */
       +    } /* case PGP_SIG: */
       +    case PGP_USERID:
       +      uidno++;
       +      uidd_c = new_uidd_c(uidd_c, uidno);
       +      if (!uidd_1)
       +        uidd_1 = uidd_c;
       +      if (uidd_c && uidd_c->uid == uidno) {
       +        uidd_c->uidstr = buf_new();
       +        buf_set(uidd_c->uidstr, p1);
       +      }
       +      if (userid)
       +        buf_move(userid, p1);
       +      break;
       +    case PGP_PUBSUBKEY:
       +    case PGP_SECSUBKEY:
       +      subkeyno++;
       +      if (keytype != -1 && subkeyno > 1) {
       +        /* usable subkey already found, don't bother to check other */
       +        continue;
       +      }
       +      if (keytype != -1 && (mode == PK_SIGN || mode == PK_VERIFY))
       +        continue;
       +    case PGP_PUBKEY:
       +      if ((type == PGP_PUBKEY || type == PGP_PUBSUBKEY) &&
       +          (mode == PK_DECRYPT || mode == PK_SIGN))
       +        continue;
       +    case PGP_SECKEY:
       +      if (type == PGP_PUBKEY || type == PGP_SECKEY)
       +        pgp_keyid(p1, mainkeyid);
       +      keytype = type;
       +      version = buf_getc(p1);
       +      switch (version) {
       +      case 2:
       +      case 3:
       +        created = buf_getl(p1);                        /* created */
       +        expires = buf_geti(p1) * (24*60*60);        /* valid */
       +        if (uidno == 0) {
       +          uidd_c = new_uidd_c(uidd_c, uidno);
       +          if (!uidd_1)
       +            uidd_1 = uidd_c;
       +          if (uidd_c && uidd_c->uid == uidno) {
       +            uidd_c->created = created;
       +            uidd_c->expires = expires;
       +            uidd_c->sym = PGP_K_IDEA;
       +          }
       +        }
       +        thisalgo = buf_getc(p1);
       +        if (thisalgo != PGP_ES_RSA) {
       +          keytype = -1;
       +          goto end;
       +        }
       +        symfound = PGP_K_IDEA;
       +        mdcfound = 0;
       +        break;
       +      case 4:
       +        buf_appendc(key, version);
       +        buf_appendl(key, buf_getl(p1));
       +        thisalgo = buf_getc(p1);
       +        buf_appendc(key, thisalgo);
       +        if (symfound == 0)
       +          symfound = PGP_K_3DES; /* default algorithm */
       +        break;
       +      default:
       +        keytype = -1;
       +        goto end;
       +      } /* switch (version) */
       +      if (algo != PGP_ANY && thisalgo != algo) {
       +        keytype = -1;
       +        continue;
       +      }
       +      if (keyid && keyid->length && !pgp_iskeyid(p1, keyid))
       +        continue;
       +      pgp_keyid(p1, thiskeyid);
       +      if (key) {
       +        buf_clear(key);
       +        for (j = 0; j < pgp_nummpi(thisalgo); j++) {
       +          if (mpi_get(p1, i) == -1)
       +            goto end;
       +          mpi_put(key, i);
       +        }
       +        if (keytype == PGP_SECKEY || keytype == PGP_SECSUBKEY) {
       +          csstart = key->length;
       +          skalgo = getski(p1, pass, sk, iv);
       +          switch (version) {
       +           case 2:
       +           case 3:
       +            ivlen = pgp_blocklen(skalgo);
       +            for (j = 0; j < pgp_numsecmpi(thisalgo); j++) {
       +              unsigned char lastb[16];
       +              if (mpi_get(p1, i) == -1) {
       +                keytype = -1;
       +                goto end;
       +              }
       +              assert(ivlen <= 16);
       +              memcpy(lastb, i->data+i->length-ivlen, ivlen);
       +              skcrypt(i, skalgo, sk, iv, DECRYPT);
       +              buf_clear(iv);
       +              buf_append(iv, lastb, ivlen);
       +              mpi_put(key, i);
       +            } /* for */
       +            break; /* switch (version) */
       +           case 4:
       +            buf_clear(i);
       +            buf_rest(i, p1);
       +            skcrypt(i, skalgo, sk, iv, DECRYPT);
       +            buf_move(p1, i);
       +            for (j = 0; j < pgp_numsecmpi(thisalgo); j++) {
       +              if (mpi_get(p1, i) == -1) {
       +                keytype = PGP_PASS;
       +                goto end;
       +              }
       +              mpi_put(key, i);
       +            }
       +            break;
       +          } /* switch (version) */
       +          if (pgp_csum(key, csstart) != buf_geti(p1)) {
       +            keytype = PGP_PASS;
       +            goto end;
       +          }
       +        }
       +      } /* if (key) */
       +      break; /* switch (type) */
       +     default:
       +      /* ignore trust packets etc */
       +      break;
       +    } /* switch (type) */
       +  } /* while ((type = pgp_getpacket(keypacket, p1)) > 0) */
       + end:
       +  if (keyid) buf_set(keyid, thiskeyid);
       +  if (tempbuf) {
       +    buf_move(keypacket, key);
       +    buf_free(key);
       +  }
       +  if (dummykey) {
       +    buf_free(key);
       +  }
       +  buf_free(p1);
       +  buf_free(i);
       +  buf_free(iv);
       +  buf_free(sk);
       +  buf_free(thiskeyid);
       +  buf_free(mainkeyid);
       +
       +  if (uidd_1) {
       +    primary = 0;
       +    created = expires = 0;
       +    while (uidd_1) {
       +      /* find newest uid which is not revoked or expired */
       +      if (primary <= uidd_1->primary && created <= uidd_1->created && !uidd_1->revoked) {
       +        created = uidd_1->created;
       +        expires = uidd_1->expires;
       +        primary = uidd_1->primary;
       +        symfound = uidd_1->sym;
       +        mdcfound = uidd_1->mdc;
       +        if (userid && uidd_1->uidstr)
       +          buf_set(userid, uidd_1->uidstr);
       +      }
       +      uidd_c = uidd_1;
       +      uidd_1 = uidd_1->next;
       +      if (uidd_c->uidstr)
       +        buf_free(uidd_c->uidstr);
       +      free(uidd_c);
       +    }
       +    if (expires && ((created + expires < now) || (created + expires < 0))) {
       +      if (mode == PK_SIGN || mode == PK_ENCRYPT) { /* allow verify and decrypt with expired keys, but not sign and encrypt */
       +        keytype = -1;
       +      }
       +    }
       +  } /* if (uidd_1) */
       +  expires = expires ? created + expires : 0;
       +  if (subexpires > 0 && expires > 0 && subexpires < expires)
       +    expires = subexpires;
       +  if (pexpires)
       +    *pexpires = expires;
       +
       +  if (!subkeyok && keytype == PGP_E_ELG && (mode == PK_DECRYPT || mode == PK_ENCRYPT))
       +    keytype = -1; /* no usable subkey found, one with valid binding */
       +
       +  if (needsym != PGP_K_ANY && needsym != symfound)
       +    keytype = -1;
       +  else if (psym && *psym == PGP_K_ANY)
       +    *psym = symfound;
       +  if (pmdc)
       +    *pmdc = mdcfound;
       +
       +  return (keytype <= 0 ? keytype : thisalgo);
       +}
       +
       +int pgp_makepkpacket(int type, BUFFER *p, BUFFER *outtxt, BUFFER *out,
       +                     BUFFER *key, BUFFER *pass, time_t *created)
       +{
       +  BUFFER *i, *id;
       +  char txt[LINELEN], algoid;
       +  int version, algo, valid = 0, err = 0;
       +  int len, j;
       +  struct tm *tc;
       +
       +  i = buf_new();
       +  id = buf_new();
       +
       +  version = buf_getc(p);
       +  buf_clear(key);
       +  switch (version) {
       +  case 2:
       +  case 3:
       +    *created = buf_getl(p);
       +    valid = buf_geti(p);
       +    algo = buf_getc(p);
       +    if (algo != PGP_ES_RSA)
       +      return(-1);
       +    break;
       +  case 4:
       +    *created = buf_getl(p);
       +    algo = buf_getc(p);
       +    break;
       +  default:
       +    return(-1);
       +  }
       +
       +  switch (version) {
       +  case 2:
       +  case 3:
       +    buf_appendc(key, version);
       +    buf_appendl(key, *created);
       +    buf_appendi(key, valid);
       +    buf_appendc(key, algo);
       +    break;
       +  case 4:
       +    buf_appendc(key, version);
       +    buf_appendl(key, *created);
       +    buf_appendc(key, algo);
       +    break;
       +  }
       +
       +  pgp_keyid(p, id);
       +  len = mpi_get(p, i);
       +  mpi_put(key, i);
       +  for (j = 1; j < pgp_nummpi(algo); j++) {
       +    if (mpi_get(p, i) == -1) {
       +      err = -1;
       +      goto end;
       +    }
       +    mpi_put(key, i);
       +  }
       +  pgp_packet(key, type);
       +  buf_cat(out, key);
       +
       +  if (outtxt != NULL) {
       +    switch(algo) {
       +     case PGP_ES_RSA:
       +      algoid = 'R';
       +      break;
       +     case PGP_S_DSA:
       +      algoid = 'D';
       +      break;
       +     case PGP_E_ELG:
       +      algoid = 'g';
       +      break;
       +     default:
       +      algoid = '?';
       +    }
       +    buf_appendf(outtxt, "%s %5d%c/%02X%02X%02X%02X ",
       +                type == PGP_PUBSUBKEY ?  "sub" :
       +                type == PGP_PUBKEY ? "pub" :
       +                type == PGP_SECKEY ? "sec" :
       +                type == PGP_SECSUBKEY ? "ssb" :
       +                "???", len, algoid,
       +                id->data[4], id->data[5], id->data[6], id->data[7]);
       +    tc = localtime(created);
       +    strftime(txt, LINELEN, "%Y-%m-%d ", tc);
       +    buf_appends(outtxt, txt);
       +  }
       + end:
       +  buf_free(i);
       +  buf_free(id);
       +  return(err == 0 ? algo : err);
       +}
       +
       +int pgp_makepubkey(BUFFER *keypacket, BUFFER *outtxt, BUFFER *out,
       +                   BUFFER *pass, int keyalgo)
       +{
       +  BUFFER *p, *pubkey, *seckey, *subkey, *sig, *tmp;
       +  int err = -1, type, thisalgo;
       +  time_t created;
       +
       +  p = buf_new();
       +  seckey = buf_new();
       +  pubkey = buf_new();
       +  subkey = buf_new();
       +  sig = buf_new();
       +  tmp = buf_new();
       +
       +  buf_set(seckey, keypacket);
       +  type = pgp_getpacket(keypacket, p);
       +  if (type != PGP_SECKEY)
       +    goto end;
       +
       +  thisalgo = pgp_makepkpacket(PGP_PUBKEY, p, outtxt, tmp, pubkey, pass,
       +                              &created);
       +  if (thisalgo == -1 || (keyalgo != 0 && keyalgo != thisalgo))
       +    goto end;
       +  buf_cat(out, tmp);
       +
       +  while ((type = pgp_getpacket(keypacket, p)) > 0) {
       +    if (type == PGP_SECSUBKEY) {
       +      if (pgp_makepkpacket(PGP_PUBSUBKEY, p, outtxt, out, subkey, pass,
       +                           &created) == -1)
       +        goto end;
       +      if (pgp_sign(pubkey, subkey, sig, NULL, pass, PGP_SIG_BINDSUBKEY, 0,
       +                   created, 0, seckey, NULL) != -1)
       +        buf_cat(out, sig);
       +      if (outtxt)
       +        buf_nl(outtxt);
       +    } else if (type == PGP_USERID) {
       +      if (outtxt != NULL) {
       +        buf_cat(outtxt, p);
       +        buf_nl(outtxt);
       +      }
       +      pgp_packet(p, PGP_USERID);
       +      err = pgp_sign(pubkey, p, sig, NULL, pass, PGP_SIG_CERT, 1, created, 0,
       +                     seckey, NULL);     /* maybe PGP_SIG_CERT3 ? */
       +      buf_cat(out, p);
       +      if (err == 0)
       +        buf_cat(out, sig);
       +    } else if (type == PGP_PUBKEY || type == PGP_SECKEY)
       +      break;
       +  }
       +end:
       +  buf_free(pubkey);
       +  buf_free(seckey);
       +  buf_free(subkey);
       +  buf_free(sig);
       +  buf_free(p);
       +  buf_free(tmp);
       +  return (err);
       +}
       +
       +int pgp_makekeyheader(int type, BUFFER *keypacket, BUFFER *outtxt,
       +                   BUFFER *pass, int keyalgo)
       +{
       +  BUFFER *p, *pubkey, *seckey, *subkey, *sig, *tmp, *dummy;
       +  int thisalgo, err = -1;
       +  time_t created;
       +
       +  assert(type == PGP_SECKEY || type == PGP_PUBKEY);
       +
       +  p = buf_new();
       +  seckey = buf_new();
       +  pubkey = buf_new();
       +  subkey = buf_new();
       +  sig = buf_new();
       +  tmp = buf_new();
       +  dummy = buf_new();
       +
       +  buf_set(seckey, keypacket);
       +  if (type != pgp_getpacket(keypacket, p))
       +    goto end;
       +
       +  thisalgo = pgp_makepkpacket(type, p, outtxt, tmp, pubkey, pass,
       +                              &created);
       +  if (thisalgo == -1 || (keyalgo != 0 && keyalgo != thisalgo))
       +    goto end;
       +
       +  while ((type = pgp_getpacket(keypacket, p)) > 0) {
       +    if (type == PGP_SECSUBKEY || type == PGP_PUBSUBKEY) {
       +      if (pgp_makepkpacket(type, p, outtxt, dummy, subkey, pass,
       +                           &created) == -1)
       +        goto end;
       +      buf_nl(outtxt);
       +    } else if (type == PGP_USERID) {
       +      buf_cat(outtxt, p);
       +      buf_nl(outtxt);
       +      pgp_packet(p, PGP_USERID);
       +    } else if (type == PGP_PUBKEY || type == PGP_SECKEY)
       +      break;
       +  }
       +  err = 0;
       +end:
       +  buf_free(pubkey);
       +  buf_free(seckey);
       +  buf_free(subkey);
       +  buf_free(sig);
       +  buf_free(p);
       +  buf_free(dummy);
       +  buf_free(tmp);
       +  return (err);
       +}
       +
       +int pgp_rsakeygen(int bits, BUFFER *userid, BUFFER *pass, char *pubring,
       +               char *secring, int remail)
       +     /* remail==2: encrypt the secring */
       +{
       +  RSA *k;
       +  KEYRING *keydb;
       +  BUFFER *pkey, *skey;
       +  BUFFER *dk, *sig, *iv, *p;
       +  long now;
       +  int skalgo = 0;
       +  int err = 0;
       +
       +  pkey = buf_new();
       +  skey = buf_new();
       +  iv = buf_new();
       +  dk = buf_new();
       +  p = buf_new();
       +  sig = buf_new();
       +
       +  errlog(NOTICE, "Generating OpenPGP RSA key.\n");
       +  k = RSA_generate_key(bits == 0 ? 1024 : bits, 17, NULL, NULL);
       +  if (k == NULL) {
       +    err = -1;
       +    goto end;
       +  }
       +  now = time(NULL);
       +  if (remail)                        /* fake time in nym keys */
       +    now -= rnd_number(4 * 24 * 60 * 60);
       +
       +  buf_appendc(skey, 3);
       +  buf_appendl(skey, now);
       +  /* until we can handle the case, where our key expires, don't create keys with expiration dates */
       +  buf_appendi(skey, 0);
       +  /* buf_appendi(skey, KEYLIFETIME/(24*60*60)); */
       +  buf_appendc(skey, PGP_ES_RSA);
       +  mpi_bnput(skey, k->n);
       +  mpi_bnput(skey, k->e);
       +
       +#ifdef USE_IDEA
       +  if (pass != NULL && pass->length > 0 && remail != 2) {
       +    skalgo = PGP_K_IDEA;
       +    digest_md5(pass, dk);
       +    buf_setrnd(iv, pgp_blocklen(skalgo));
       +    buf_appendc(skey, skalgo);
       +    buf_cat(skey, iv);
       +  }
       +  else
       +#endif /* USE_IDEA */
       +    buf_appendc(skey, 0);
       +
       +  mpi_bnputenc(skey, k->d, skalgo, dk, iv);
       +  mpi_bnputenc(skey, k->q, skalgo, dk, iv);
       +  mpi_bnputenc(skey, k->p, skalgo, dk, iv);
       +  mpi_bnputenc(skey, k->iqmp, skalgo, dk, iv);
       +
       +  buf_clear(p);
       +  mpi_bnput(p, k->d);
       +  mpi_bnput(p, k->q);
       +  mpi_bnput(p, k->p);
       +  mpi_bnput(p, k->iqmp);
       +  buf_appendi(skey, pgp_csum(p, 0));
       +
       +  pgp_packet(skey, PGP_SECKEY);
       +  buf_set(p, userid);
       +  pgp_packet(p, PGP_USERID);
       +  buf_cat(skey, p);
       +
       +  if (secring == NULL)
       +    secring = PGPREMSECRING;
       +  keydb = pgpdb_open(secring, remail == 2 ? pass : NULL, 1, PGP_TYPE_PRIVATE);
       +  if (keydb == NULL) {
       +    err = -1;
       +    goto end;
       +  }
       +  if (keydb->filetype == -1)
       +    keydb->filetype = ARMORED;
       +  pgpdb_append(keydb, skey);
       +  pgpdb_close(keydb);
       +
       +  if (pubring != NULL) {
       +    if (pgp_makepubkey(skey, NULL, pkey, pass, 0) == -1)
       +      goto end;
       +    keydb = pgpdb_open(pubring, NULL, 1, PGP_TYPE_PUBLIC);
       +    if (keydb == NULL)
       +      goto end;
       +    if (keydb->filetype == -1)
       +      keydb->filetype = ARMORED;
       +    pgpdb_append(keydb, pkey);
       +    pgpdb_close(keydb);
       +  }
       +end:
       +  RSA_free(k);
       +  buf_free(pkey);
       +  buf_free(skey);
       +  buf_free(iv);
       +  buf_free(dk);
       +  buf_free(p);
       +  buf_free(sig);
       +  return (err);
       +}
       +
       +#define begin_param "-----BEGIN PUBLIC PARAMETER BLOCK-----"
       +#define end_param "-----END PUBLIC PARAMETER BLOCK-----"
       +
       +static void *params(int dsa, int bits)
       +{
       +  DSA *k = NULL;
       +  DH *d = NULL;
       +  FILE *f;
       +  BUFFER *p, *n;
       +  char line[LINELEN];
       +  byte b[1024];
       +  int m, l;
       +
       +  if (bits == 0)
       +    bits = 1024;
       +  if (dsa && bits > 1024)
       +    bits = 1024;
       +
       +  p = buf_new();
       +  n = buf_new();
       +  f = mix_openfile(dsa ? DSAPARAMS : DHPARAMS, "r");
       +  if (f != NULL) {
       +    for (;;) {
       +      if (fgets(line, sizeof(line), f) == NULL)
       +        break;
       +      if (strleft(line, begin_param)) {
       +        if (fgets(line, sizeof(line), f) == NULL)
       +          break;
       +        m = 0;
       +        sscanf(line, "%d", &m);
       +        if (bits == m) {
       +          buf_clear(p);
       +          while (fgets(line, sizeof(line), f) != NULL) {
       +            if (strleft(line, end_param)) {
       +              decode(p, p);
       +              if (dsa) {
       +                k = DSA_new();
       +                l = buf_geti(p);
       +                buf_get(p, n, l);
       +                k->p = BN_bin2bn(n->data, n->length, NULL);
       +                l = buf_geti(p);
       +                buf_get(p, n, l);
       +                k->q = BN_bin2bn(n->data, n->length, NULL);
       +                l = buf_geti(p);
       +                buf_get(p, n, l);
       +                k->g = BN_bin2bn(n->data, n->length, NULL);
       +              } else {
       +                d = DH_new();
       +                l = buf_geti(p);
       +                buf_get(p, n, l);
       +                d->p = BN_bin2bn(n->data, n->length, NULL);
       +                l = buf_geti(p);
       +                buf_get(p, n, l);
       +                d->g = BN_bin2bn(n->data, n->length, NULL);
       +              }
       +              break;
       +            }
       +            buf_appends(p, line);
       +          }
       +        }
       +      }
       +    }
       +    fclose(f);
       +  }
       +
       +  buf_free(p);
       +  buf_free(n);
       +
       +  if (dsa) {
       +    if (k == NULL) {
       +      errlog(NOTICE, "Generating DSA parameters.\n");
       +      k = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
       +      p = buf_new();
       +      l = BN_bn2bin(k->p, b);
       +      buf_appendi(p, l);
       +      buf_append(p, b, l);
       +      l = BN_bn2bin(k->q, b);
       +      buf_appendi(p, l);
       +      buf_append(p, b, l);
       +      l = BN_bn2bin(k->g, b);
       +      buf_appendi(p, l);
       +      buf_append(p, b, l);
       +      encode(p, 64);
       +      f = mix_openfile(DSAPARAMS, "a");
       +      if (f != NULL) {
       +        fprintf(f, "%s\n%d\n", begin_param, bits);
       +        buf_write(p, f);
       +        fprintf(f, "%s\n", end_param);
       +        fclose(f);
       +      } else
       +        errlog(ERRORMSG, "Cannot open %s!\n", DSAPARAMS);
       +      buf_free(p);
       +    }
       +    return (k);
       +  } else {
       +    if (d == NULL) {
       +      errlog(NOTICE, "Generating DH parameters. (This may take a long time!)\n");
       +      d = DH_generate_parameters(bits, DH_GENERATOR_5, NULL, NULL);
       +      p = buf_new();
       +      l = BN_bn2bin(d->p, b);
       +      buf_appendi(p, l);
       +      buf_append(p, b, l);
       +      l = BN_bn2bin(d->g, b);
       +      buf_appendi(p, l);
       +      buf_append(p, b, l);
       +      encode(p, 64);
       +      f = mix_openfile(DHPARAMS, "a");
       +      if (f != NULL) {
       +        fprintf(f, "%s\n%d\n", begin_param, bits);
       +        buf_write(p, f);
       +        fprintf(f, "%s\n", end_param);
       +        fclose(f);
       +      } else
       +        errlog(ERRORMSG, "Cannot open %s!\n", DHPARAMS);
       +      buf_free(p);
       +    }
       +    return (d);
       +  }
       +}
       +
       +int pgp_dhkeygen(int bits, BUFFER *userid, BUFFER *pass, char *pubring,
       +               char *secring, int remail)
       +     /* remail==2: encrypt the secring */
       +{
       +  DSA *s;
       +  DH *e;
       +  KEYRING *keydb;
       +  BUFFER *pkey, *skey, *subkey, *secret;
       +  BUFFER *dk, *sig, *iv, *p;
       +  long now;
       +  int err = 0;
       +
       +  pkey = buf_new();
       +  skey = buf_new();
       +  subkey = buf_new();
       +  iv = buf_new();
       +  dk = buf_new();
       +  p = buf_new();
       +  sig = buf_new();
       +  secret = buf_new();
       +
       +  s = params(1, bits);
       +  errlog(NOTICE, "Generating OpenPGP DSA key.\n");
       +  if (s == NULL || DSA_generate_key(s) != 1) {
       +    err = -1;
       +    goto end;
       +  }
       +  e = params(0, bits);
       +  errlog(NOTICE, "Generating OpenPGP ElGamal key.\n");
       +  if (e == NULL || DH_generate_key(e) != 1) {
       +    err = -1;
       +    goto end;
       +  }
       +
       +  now = time(NULL);
       +  if (remail)                        /* fake time in nym keys */
       +    now -= rnd_number(4 * 24 * 60 * 60);
       +
       +  /* DSA key */
       +  buf_setc(skey, 4);
       +  buf_appendl(skey, now);
       +  buf_appendc(skey, PGP_S_DSA);
       +  mpi_bnput(skey, s->p);
       +  mpi_bnput(skey, s->q);
       +  mpi_bnput(skey, s->g);
       +  mpi_bnput(skey, s->pub_key);
       +
       +  mpi_bnput(secret, s->priv_key);
       +  buf_appendi(secret, pgp_csum(secret, 0));
       +  makeski(secret, pass, remail);
       +  buf_cat(skey, secret);
       +  pgp_packet(skey, PGP_SECKEY);
       +
       +  /* ElGamal key */
       +  buf_setc(subkey, 4);
       +  buf_appendl(subkey, now);
       +  buf_appendc(subkey, PGP_E_ELG);
       +  mpi_bnput(subkey, e->p);
       +  mpi_bnput(subkey, e->g);
       +  mpi_bnput(subkey, e->pub_key);
       +
       +  buf_clear(secret);
       +  mpi_bnput(secret, e->priv_key);
       +  buf_appendi(secret, pgp_csum(secret, 0));
       +  makeski(secret, pass, remail);
       +  buf_cat(subkey, secret);
       +
       +  buf_set(p, userid);
       +  pgp_packet(p, PGP_USERID);
       +  buf_cat(skey, p);
       +
       +  pgp_packet(subkey, PGP_SECSUBKEY);
       +  buf_cat(skey, subkey);
       +
       +  if (secring == NULL)
       +    secring = PGPREMSECRING;
       +  keydb = pgpdb_open(secring, remail == 2 ? pass : NULL, 1, PGP_TYPE_PRIVATE);
       +  if (keydb == NULL) {
       +    err = -1;
       +    goto end;
       +  }
       +  if (keydb->filetype == -1)
       +    keydb->filetype = ARMORED;
       +  pgpdb_append(keydb, skey);
       +  pgpdb_close(keydb);
       +
       +  if (pubring != NULL) {
       +    pgp_makepubkey(skey, NULL, pkey, pass, 0);
       +    keydb = pgpdb_open(pubring, NULL, 1, PGP_TYPE_PUBLIC);
       +    if (keydb == NULL)
       +      goto end;
       +    if (keydb->filetype == -1)
       +      keydb->filetype = ARMORED;
       +    pgpdb_append(keydb, pkey);
       +    pgpdb_close(keydb);
       +  }
       +end:
       +  buf_free(pkey);
       +  buf_free(skey);
       +  buf_free(subkey);
       +  buf_free(iv);
       +  buf_free(dk);
       +  buf_free(p);
       +  buf_free(sig);
       +  buf_free(secret);
       +  return (err);
       +}
       +
       +int pgp_dsasign(BUFFER *data, BUFFER *key, BUFFER *out)
       +{
       +  BUFFER *mpi, *b;
       +  DSA *d;
       +  DSA_SIG *sig = NULL;
       +
       +  d = DSA_new();
       +  b = buf_new();
       +  mpi = buf_new();
       +  mpi_get(key, mpi);
       +  d->p = BN_bin2bn(mpi->data, mpi->length, NULL);
       +  mpi_get(key, mpi);
       +  d->q = BN_bin2bn(mpi->data, mpi->length, NULL);
       +  mpi_get(key, mpi);
       +  d->g = BN_bin2bn(mpi->data, mpi->length, NULL);
       +  mpi_get(key, mpi);
       +  d->pub_key = BN_bin2bn(mpi->data, mpi->length, NULL);
       +  if (mpi_get(key, mpi) == -1) {
       +    goto end;
       +  }
       +  d->priv_key = BN_bin2bn(mpi->data, mpi->length, NULL);
       +
       +  sig = DSA_do_sign(data->data, data->length, d);
       +  if (sig) {
       +    buf_prepare(b, BN_num_bytes(sig->r));
       +    b->length = BN_bn2bin(sig->r, b->data);
       +    mpi_put(out, b);
       +    b->length = BN_bn2bin(sig->s, b->data);
       +    mpi_put(out, b);
       +  }
       + end:
       +  buf_free(mpi);
       +  buf_free(b);
       +  DSA_SIG_free(sig);
       +  DSA_free(d);
       +  return(sig ? 0 : -1);
       +}
       +
       +int pgp_dosign(int algo, BUFFER *data, BUFFER *key)
       +{
       +  int err;
       +  BUFFER *out, *r, *s;
       +
       +  out = buf_new();
       +  r = buf_new();
       +  s = buf_new();
       +  switch (algo) {
       +   case PGP_ES_RSA:
       +    err = pgp_rsa(data, key, PK_SIGN);
       +    if (err == 0)
       +      mpi_put(out, data);
       +    break;
       +   case PGP_S_DSA:
       +    err = pgp_dsasign(data, key, out);
       +    break;
       +   default:
       +    errlog(NOTICE, "Unknown encryption algorithm!\n");
       +    return (-1);
       +  }
       +  if (err == -1)
       +    errlog(ERRORMSG, "Signing operation failed!\n");
       +
       +  buf_move(data, out);
       +  buf_free(out);
       +  buf_free(r);
       +  buf_free(s);
       +  return (err);
       +}
       +
       +int pgp_elgdecrypt(BUFFER *in, BUFFER *key)
       +{
       +  BIGNUM *a = NULL, *b = NULL, *c = NULL,
       +         *p = NULL, *g = NULL, *x = NULL;
       +  BN_CTX *ctx;
       +  BUFFER *i;
       +  int err = -1;
       +
       +  i = buf_new();
       +  ctx = BN_CTX_new();
       +  if (ctx == NULL) goto end;
       +  mpi_get(key, i);
       +  p = BN_bin2bn(i->data, i->length, NULL);
       +  mpi_get(key, i);
       +  g = BN_bin2bn(i->data, i->length, NULL);
       +  mpi_get(key, i); /* y */
       +  mpi_get(key, i);
       +  x = BN_bin2bn(i->data, i->length, NULL);
       +  mpi_get(in, i);
       +  a = BN_bin2bn(i->data, i->length, NULL);
       +  if (mpi_get(in, i) == -1)
       +    goto e1;
       +  b = BN_bin2bn(i->data, i->length, NULL);
       +  c = BN_new();
       +
       +  if (BN_mod_exp(c, a, x, p, ctx) == 0) goto end;
       +  if (BN_mod_inverse(a, c, p, ctx) == 0) goto end;
       +  if (BN_mod_mul(c, a, b, p, ctx) == 0) goto end;
       +
       +  buf_prepare(i, BN_num_bytes(c));
       +  i->length = BN_bn2bin(c, i->data);
       +
       +  buf_prepare(in, BN_num_bytes(c));
       +  in->length = RSA_padding_check_PKCS1_type_2(in->data, in->length, i->data,
       +                                               i->length, i->length + 1);
       +  if (in->length <= 0)
       +    in->length = 0;
       +  else
       +    err = 0;
       +
       + end:
       +  BN_free(b);
       +  BN_free(c);
       + e1:
       +  buf_free(i);
       +  BN_free(a);
       +  BN_free(p);
       +  BN_free(g);
       +  BN_clear_free(x);
       +  BN_CTX_free(ctx);
       +
       +  return (err);
       +}
       +
       +int pgp_elgencrypt(BUFFER *in, BUFFER *key)
       +{
       +  BIGNUM *m, *k, *a, *b, *c, *p, *g, *y = NULL;
       +  BN_CTX *ctx;
       +  BUFFER *i;
       +  int err = -1;
       +
       +  i = buf_new();
       +  ctx = BN_CTX_new();
       +  if (ctx == NULL) goto end;
       +  mpi_get(key, i);
       +  p = BN_bin2bn(i->data, i->length, NULL);
       +  mpi_get(key, i);
       +  g = BN_bin2bn(i->data, i->length, NULL);
       +  if (mpi_get(key, i) == -1)
       +    goto e1;
       +  y = BN_bin2bn(i->data, i->length, NULL);
       +
       +  buf_prepare(i, BN_num_bytes(p));
       +  if (RSA_padding_add_PKCS1_type_2(i->data, i->length, in->data, in->length)
       +      != 1)
       +    goto end;
       +  m = BN_bin2bn(i->data, i->length, NULL);
       +
       +  k = BN_new();
       +  BN_rand(k, BN_num_bits(p), 0, 0);
       +
       +  a = BN_new();
       +  b = BN_new();
       +  c = BN_new();
       +
       +  if (BN_mod_exp(a, g, k, p, ctx) == 0) goto end;
       +  if (BN_mod_exp(c, y, k, p, ctx) == 0) goto end;
       +  if (BN_mod_mul(b, m, c, p, ctx) == 0) goto end;
       +
       +  buf_clear(in);
       +  i->length = BN_bn2bin(a, i->data);
       +  mpi_put(in, i);
       +  i->length = BN_bn2bin(b, i->data);
       +  mpi_put(in, i);
       +
       +  err = 0;
       +
       +  BN_free(a);
       +  BN_free(b);
       +  BN_free(c);
       +  BN_free(m);
       +e1:
       +  buf_free(i);
       +  BN_free(p);
       +  BN_free(g);
       +  BN_free(y);
       +  BN_CTX_free(ctx);
       + end:
       +
       +  return (err);
       +}
       +
       +#endif /* USE_PGP */
   DIR diff --git a/Src/pgpdb.c b/Src/pgpdb.c
       t@@ -0,0 +1,583 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   OpenPGP key database
       +   $Id: pgpdb.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#ifdef USE_PGP
       +#include "pgp.h"
       +#include <assert.h>
       +#include <stdlib.h>
       +#include <string.h>
       +#include <time.h>
       +
       +static int pgp_readkeyring(BUFFER *keys, char *filename)
       +{
       +  FILE *keyfile;
       +  BUFFER *armored, *line, *tmp;
       +  int err = -1;
       +
       +  if ((keyfile = mix_openfile(filename, "rb")) == NULL)
       +    return (err);
       +
       +  armored = buf_new();
       +  buf_read(armored, keyfile);
       +  fclose(keyfile);
       +  if (pgp_ispacket(armored)) {
       +    err = 0;
       +    buf_move(keys, armored);
       +  } else {
       +    line = buf_new();
       +    tmp = buf_new();
       +
       +    while (1) {
       +      do
       +        if (buf_getline(armored, line) == -1) {
       +          goto end_greedy_dearmor;
       +        }
       +      while (!bufleft(line, begin_pgp)) ;
       +      buf_clear(tmp);
       +      buf_cat(tmp, line);
       +      buf_appends(tmp, "\n");
       +      do {
       +        if (buf_getline(armored, line) == -1) {
       +          goto end_greedy_dearmor;
       +        }
       +              buf_cat(tmp, line);
       +              buf_appends(tmp, "\n");
       +      } while (!bufleft(line, end_pgp)) ;
       +
       +      if (pgp_dearmor(tmp, tmp) == 0) {
       +        err = ARMORED;
       +        buf_cat(keys, tmp);
       +      }
       +    }
       +end_greedy_dearmor:
       +    buf_free(line);
       +    buf_free(tmp);
       +
       +  }
       +  buf_free(armored);
       +  return (err);
       +}
       +
       +KEYRING *pgpdb_open(char *keyring, BUFFER *encryptkey, int writer, int type)
       +{
       +  KEYRING *keydb;
       +
       +  assert(! ((writer) && (type == PGP_TYPE_UNDEFINED)));
       +  keydb = pgpdb_new(keyring, -1, encryptkey, type);
       +#ifndef NDEBUG
       +  keydb->writer = writer;
       +#endif
       +  if (writer)
       +    keydb->lock = lockfile(keyring);
       +  keydb->filetype = pgp_readkeyring(keydb->db, keyring);
       +#if 0
       +  if (keydb->filetype == -1) {
       +    pgpdb_close(keydb);
       +    return (NULL);
       +  }
       +#endif /* if 0 */
       +  if (encryptkey && encryptkey->length && pgp_isconventional(keydb->db) &&
       +      pgp_decrypt(keydb->db, encryptkey, NULL, NULL, NULL) < 0) {
       +    user_delpass();
       +    return (NULL);
       +  }
       +  return (keydb);
       +}
       +
       +KEYRING *pgpdb_new(char *keyring, int filetype, BUFFER *encryptkey, int type)
       +{
       +  KEYRING *keydb;
       +
       +  keydb = malloc(sizeof(KEYRING));
       +
       +  if (keydb == NULL)
       +    return NULL;
       +  keydb->db = buf_new();
       +  keydb->modified = 0;
       +  keydb->lock = NULL;
       +  keydb->type = type;
       +  strncpy(keydb->filename, keyring, sizeof(keydb->filename));
       +  keydb->filetype = filetype;
       +  if (encryptkey == NULL)
       +    keydb->encryptkey = NULL;
       +  else {
       +    keydb->encryptkey = buf_new();
       +    buf_set(keydb->encryptkey, encryptkey);
       +  }
       +  return (keydb);
       +}
       +
       +int pgpdb_close(KEYRING *keydb)
       +{
       +  int err = 0;
       +
       +  if (keydb->modified) {
       +    FILE *f;
       +#ifndef ndebug
       +    assert(keydb->writer);
       +#endif
       +    if (keydb->encryptkey && keydb->encryptkey->length)
       +      pgp_encrypt(PGP_NCONVENTIONAL | PGP_NOARMOR, keydb->db,
       +                  keydb->encryptkey, NULL, NULL, NULL, NULL);
       +    assert(keydb->type == PGP_TYPE_PRIVATE || keydb->type == PGP_TYPE_PUBLIC);
       +    if (keydb->filetype == ARMORED)
       +      pgp_armor(keydb->db, keydb->type == PGP_TYPE_PUBLIC ? PGP_ARMOR_KEY : PGP_ARMOR_SECKEY);
       +    if (keydb->filetype == -1 || (f = mix_openfile(keydb->filename,
       +                                                   keydb->filetype ==
       +                                                   ARMORED ? "w" : "wb"))
       +        == NULL)
       +      err = -1;
       +    else {
       +      err = buf_write(keydb->db, f);
       +      fclose(f);
       +    }
       +  }
       +  if (keydb->lock)
       +    unlockfile(keydb->lock);
       +  if (keydb->encryptkey)
       +    buf_free(keydb->encryptkey);
       +  buf_free(keydb->db);
       +  free(keydb);
       +  return (err);
       +}
       +
       +int pgpdb_getnext(KEYRING *keydb, BUFFER *key, BUFFER *keyid, BUFFER *userid)
       +     /* store next key from keydb with specified keyid/userid in key. */
       +{
       +  int found = 0;
       +  int type;
       +  long ptr;
       +  int tempbuf = 0;
       +  BUFFER *p, *i, *thisid;
       +
       +  p = buf_new();
       +  i = buf_new();
       +  thisid = buf_new();
       +
       +  if (key == NULL) {
       +    tempbuf = 1;
       +    key = buf_new();
       +  }
       +  assert(key != keyid);
       +  while (!found) {
       +    buf_clear(key);
       +    type = pgp_getpacket(keydb->db, key);
       +    if (type == -1)
       +      break;
       +    if (type != PGP_PUBKEY && type != PGP_SECKEY)
       +      continue;
       +    if ((keyid == NULL || keyid->length == 0) &&
       +        (userid == NULL || userid->length == 0))
       +      found = 1;
       +
       +    if (keyid && keyid->length > 0) {
       +      pgp_keyid(key, thisid);
       +      if (buf_eq(keyid, thisid))
       +        found = 1;
       +    }
       +
       +    pgp_packet(key, type);
       +
       +    while ((ptr = keydb->db->ptr, type = pgp_getpacket(keydb->db, p)) > 0) {
       +      switch (type) {
       +      case PGP_SECKEY:
       +      case PGP_PUBKEY:
       +        keydb->db->ptr = ptr;
       +        goto nextkey;
       +      case PGP_PUBSUBKEY:
       +      case PGP_SECSUBKEY:
       +        if (keyid && keyid->length > 0) {
       +          pgp_keyid(p, thisid);
       +          if (buf_eq(keyid, thisid))
       +            found = 1;
       +        }
       +        break;
       +      case PGP_USERID:
       +#ifdef DEBUG
       +        printf("%s\n", p->data);
       +#endif /* DEBUG */
       +        if (userid && userid->length > 0 && bufifind(p, userid->data))
       +          found = 1;
       +        break;
       +      }
       +      pgp_packet(p, type);
       +      buf_cat(key, p);
       +    }
       +  nextkey:
       +    ;
       +  }
       +  if (tempbuf)
       +    buf_free(key);
       +  buf_free(p);
       +  buf_free(i);
       +  buf_free(thisid);
       +  return (found ? 0 : -1);
       +}
       +
       +int pgpdb_append(KEYRING *keydb, BUFFER *p)
       +{
       +  assert(keydb->lock);
       +#ifndef ndebug
       +  assert(keydb->writer);
       +#endif
       +  buf_cat(keydb->db, p);
       +  keydb->modified = 1;
       +  return (0);
       +}
       +
       +#define pgp_preferredalgo PGP_ES_RSA
       +
       +int pgpdb_getkey(int mode, int algo, int *sym, int *mdc, long *expires, BUFFER *key, BUFFER *userid,
       +                 BUFFER *founduid, BUFFER *keyid, char *keyring, BUFFER *pass)
       +/* FIXME: This could be changed to return the key with the latest expiration date if
       + *        a key is not unique */
       +{
       +  KEYRING *r;
       +  BUFFER *id, *thisid, *thiskey;
       +  int thisalgo, algofound = -1, needpass = 0;
       +  int found = 0;
       +
       +  id = buf_new();
       +  thisid = buf_new();
       +  thiskey = buf_new();
       +  if (keyring)
       +    r = pgpdb_open(keyring, pass, 0, PGP_TYPE_UNDEFINED);
       +  else
       +    switch (mode) {
       +    case PK_DECRYPT:
       +    case PK_SIGN:
       +      r = pgpdb_open(PGPREMSECRING, NULL, 0, PGP_TYPE_PRIVATE);
       +      break;
       +    case PK_ENCRYPT:
       +    case PK_VERIFY:
       +      r = pgpdb_open(PGPREMPUBASC, NULL, 0, PGP_TYPE_PUBLIC);
       +      if (r != NULL && r->filetype == -1) {
       +        pgpdb_close(r);
       +        r = pgpdb_open(PGPREMPUBRING, NULL, 0, PGP_TYPE_PUBLIC);
       +      }
       +      break;
       +    default:
       +      r = NULL;
       +    }
       +  if (r == NULL)
       +    goto end;
       +
       +  for (;;) {
       +    /* repeat until success or end of key ring */
       +    if (pgpdb_getnext(r, thiskey, keyid, userid) == -1)
       +      break;
       +    if (keyid) /* pgp_getkey has to chose subkey with given keyid */
       +      buf_set(thisid, keyid);
       +    thisalgo = pgp_getkey(mode, algo, sym, mdc, expires, thiskey, thiskey, thisid, founduid,
       +                          pass);
       +    if (thisalgo == PGP_PASS)
       +      needpass = 1;
       +    if (thisalgo > 0) {
       +      found++;
       +      if ((thisalgo == pgp_preferredalgo && algofound != pgp_preferredalgo
       +           && algofound > 0)
       +          || (thisalgo != pgp_preferredalgo && algofound == pgp_preferredalgo))
       +        found--; /* ignore the non-preferred algorithm */
       +      if (found <= 1 || (thisalgo == pgp_preferredalgo &&
       +                         algofound != pgp_preferredalgo && algofound > 0)) {
       +        algofound = thisalgo;
       +        if (key)
       +          buf_move(key, thiskey);
       +        buf_set(id, thisid);
       +      }
       +    }
       +  }
       +  pgpdb_close(r);
       +end:
       +  if (found < 1) {
       +    if (needpass)
       +      errlog(DEBUGINFO, "Need passphrase!\n");
       +    else if (!sym || *sym != PGP_K_IDEA) { /* kludge: try again with 3DES */
       +      if (userid)
       +        errlog(NOTICE, "Key %b not found!\n", userid);
       +      else if (keyid && keyid->length > 7)
       +        errlog(NOTICE, "Key %02X%02X%02X%02X not found!\n", keyid->data[4],
       +               keyid->data[5], keyid->data[6], keyid->data[7]);
       +    }
       +  }
       +  if (found > 1) {
       +    if (userid)
       +      errlog(WARNING, "Key %b not unique!\n", userid);
       +    else if (keyid && keyid->length > 7)
       +      errlog(ERRORMSG, "Key %02X%02X%02X%02X not unique!\n", keyid->data[4],
       +             keyid->data[5], keyid->data[6], keyid->data[7]);
       +    else
       +      errlog(WARNING, "Key not unique!\n");
       +  }
       +  if (found && keyid) /* return ID of found key */
       +    buf_set(keyid, id);
       +
       +  buf_free(thiskey);
       +  buf_free(thisid);
       +  buf_free(id);
       +  return (algofound);
       +}
       +
       +int pgp_keymgt(int force)
       +{
       +  FILE *f = NULL;
       +  BUFFER *key, *keybak, *userid, *out, *outkey, *outtxt, *pass, *secout;
       +  KEYRING *keys;
       +  int err = 0, res, recreate_pubring = 0, dsa_ok = 0;
       +#ifdef USE_IDEA
       +  int rsa_ok = 0;
       +#endif /* USE_IDEA */
       +  long expires;
       +  LOCK *seclock;
       +
       +  key = buf_new();
       +  out = buf_new();
       +  keybak = buf_new();
       +  secout = buf_new();
       +
       +  userid = buf_new();
       +  buf_sets(userid, REMAILERNAME);
       +  pass = buf_new();
       +  buf_sets(pass, PASSPHRASE);
       +  outtxt = buf_new();
       +  outkey = buf_new();
       +
       +  /* We only want to build RSA keys if we also can do IDEA
       +   * This is to not lose any mail should users try our RSA key
       +   * with IDEA.
       +   */
       +#ifdef USE_IDEA
       +  /* FIXME: pgpdb_getky returns the expiration date from the last key in the keyring
       +   *        which probably works most of the time if the keys are in the correct order
       +   *        it doesn't return the latest expiration date (or 0) if the key in question
       +   *        is before another matching key in the keyring tho
       +   */
       +  res = pgpdb_getkey(PK_DECRYPT, PGP_ES_RSA, NULL, NULL, &expires, NULL, NULL,
       +                                  NULL, NULL, NULL, pass);
       +  if (force == 2 || res < 0 || (expires > 0 && expires - KEYOVERLAPPERIOD < time(NULL))) {
       +    rsa_ok = -1;
       +    pgp_keygen(PGP_ES_RSA, 0, userid, pass, PGPKEY, PGPREMSECRING, 0);
       +  };
       +
       +  if (force == 0 && (pgpdb_getkey(PK_ENCRYPT, PGP_ES_RSA, NULL, NULL, NULL, NULL, NULL,
       +                                  NULL, NULL, PGPKEY, NULL) < 0) && rsa_ok == 0)
       +    rsa_ok = 1;
       +#endif /* USE_IDEA */
       +  /* FIXME: pgpdb_getky returns the expiration date from the last key in the keyring
       +   *        which probably works most of the time if the keys are in the correct order
       +   *        it doesn't return the latest expiration date (or 0) if the key in question
       +   *        is before another matching key in the keyring tho
       +   */
       +  res = pgpdb_getkey(PK_DECRYPT, PGP_E_ELG, NULL, NULL, &expires, NULL, NULL,
       +                                  NULL, NULL, NULL, pass);
       +  if (force == 2 || res < 0 || (expires > 0 && expires - KEYOVERLAPPERIOD < time(NULL))) {
       +    dsa_ok = -1;
       +    pgp_keygen(PGP_E_ELG, 0, userid, pass, PGPKEY, PGPREMSECRING, 0);
       +  }
       +
       +  if (force == 0 && (pgpdb_getkey(PK_ENCRYPT, PGP_E_ELG, NULL, NULL, NULL, NULL, NULL,
       +                                  NULL, NULL, PGPKEY, NULL) > 0) && dsa_ok == 0)
       +    dsa_ok = 1;
       +
       +  /* No need to rewrite the files - we didn't change a thing */
       +  if (
       +#ifdef USE_IDEA
       +      rsa_ok == 1 &&
       +#endif /* USE_IDEA */
       +      dsa_ok == 1)
       +    goto end;
       +
       +  /* write keys one key per armor to make hand editing easy and old PGP
       +   * versions happy */
       +  err = -1;
       +  keys = pgpdb_open(PGPKEY, NULL, 0, PGP_TYPE_PUBLIC);
       +  if (keys == NULL)
       +    recreate_pubring = 1;
       +  else {
       +    while (pgpdb_getnext(keys, key, NULL, userid) != -1) {
       +      buf_clear(outtxt);
       +      if (pgp_makekeyheader(PGP_PUBKEY, key, outtxt, NULL, PGP_ANY) == 0) {
       +        err = 0;
       +        buf_appends(out, "Type Bits/KeyID     Date       User ID\n");
       +        buf_cat(out, outtxt);
       +        buf_nl(out);
       +        pgp_armor(key, PGP_ARMOR_KEY);
       +        buf_cat(out, key);
       +        buf_nl(out);
       +      }
       +    }
       +    pgpdb_close(keys);
       +  }
       +  if (err != 0)
       +    recreate_pubring = 1;
       +  err = -1;
       +
       +  keys = pgpdb_open(PGPREMSECRING, NULL, 0, PGP_TYPE_PRIVATE);
       +  if (keys == NULL)
       +    goto end;
       +  while (pgpdb_getnext(keys, key, NULL, userid) != -1) {
       +    buf_clear(outtxt);
       +    buf_clear(outkey);
       +    buf_clear(keybak);
       +    buf_cat(keybak, key);
       +    if (pgp_makekeyheader(PGP_SECKEY, key, outtxt, pass, PGP_ANY) == 0) {
       +      err = 0;
       +      buf_appends(secout, "Type Bits/KeyID     Date       User ID\n");
       +      buf_cat(secout, outtxt);
       +      buf_nl(secout);
       +      pgp_armor(key, PGP_ARMOR_SECKEY);
       +      buf_cat(secout, key);
       +      buf_nl(secout);
       +    }
       +    buf_clear(outtxt);
       +    if (recreate_pubring &&
       +        pgp_makepubkey(keybak, outtxt, outkey, pass, PGP_ANY) == 0) {
       +      buf_appends(out, "Type Bits/KeyID     Date       User ID\n");
       +      buf_cat(out, outtxt);
       +      buf_nl(out);
       +      pgp_armor(outkey, PGP_ARMOR_KEY);
       +      buf_cat(out, outkey);
       +      buf_nl(out);
       +    }
       +  }
       +  pgpdb_close(keys);
       +
       +  seclock = lockfile(PGPREMSECRING);
       +  if (err == 0 && (f = mix_openfile(PGPREMSECRING, "w")) != NULL) {
       +    buf_write(secout, f);
       +    fclose(f);
       +  } else
       +    err = -1;
       +  unlockfile(seclock);
       +  if (err == 0 && (f = mix_openfile(PGPKEY, "w")) != NULL) {
       +    buf_write(out, f);
       +    fclose(f);
       +  } else
       +    err = -1;
       +end:
       +  buf_free(key);
       +  buf_free(keybak);
       +  buf_free(out);
       +  buf_free(userid);
       +  buf_free(pass);
       +  buf_free(outtxt);
       +  buf_free(outkey);
       +  buf_free(secout);
       +  return (err);
       +}
       +
       +int pgp_latestkeys(BUFFER* outtxt, int algo)
       +/* returns our latest key from pgpkey.txt in the buffer outtxt
       + * with pgp key header, ascii armored
       + *
       + * Can probably be extended to do this for all keys if we pass
       + * the keyring file and the userid
       + *
       + * IN:  algo: PGP_ANY, PGP_ES_RSA, PGP_E_ELG, PGP_S_DSA
       + * OUT: outtxt
       + */
       +{
       +  int err = -1;
       +  long expires_found = 0, expires;
       +  BUFFER *key, *userid, *tmptxt;
       +  KEYRING *keys;
       +
       +  key = buf_new();
       +  userid = buf_new();
       +  buf_sets(userid, REMAILERNAME);
       +  tmptxt = buf_new();
       +
       +  keys = pgpdb_open(PGPKEY, NULL, 0, PGP_TYPE_PUBLIC);
       +  if (keys != NULL) {
       +    while (pgpdb_getnext(keys, key, NULL, userid) != -1) {
       +      buf_clear(tmptxt);
       +      if (pgp_makekeyheader(PGP_PUBKEY, key, tmptxt, NULL, algo) == 0) {
       +        buf_rewind(key);
       +        pgp_getkey(PK_VERIFY, algo, NULL, NULL, &expires, key, NULL, NULL, NULL, NULL);
       +        if (expires == 0 || (expires_found <= expires)) {
       +          err = 0;
       +          buf_clear(outtxt);
       +          buf_appends(outtxt, "Type Bits/KeyID     Date       User ID\n");
       +          buf_cat(outtxt, tmptxt);
       +          buf_nl(outtxt);
       +          pgp_armor(key, PGP_ARMOR_KEY);
       +          buf_cat(outtxt, key);
       +          buf_nl(outtxt);
       +          expires_found = expires;
       +        }
       +      }
       +    }
       +    pgpdb_close(keys);
       +  }
       +
       +  buf_free(key);
       +  buf_free(userid);
       +  buf_free(tmptxt);
       +
       +  return (err);
       +}
       +
       +int pgp_rlist(REMAILER remailer[], int n)
       +     /* verify that keys are available */
       +{
       +  BUFFER *keyring, *p;
       +  int i, type, pgpkey[MAXREM];
       +
       +  keyring = buf_new();
       +  p = buf_new();
       +  for (i = 1; i < n; i++)
       +    pgpkey[i] = 0;
       +  if (pgp_readkeyring(keyring, PGPREMPUBASC) == -1)
       +    pgp_readkeyring(keyring, PGPREMPUBRING);
       +  while ((type = pgp_getpacket(keyring, p)) != -1)
       +    if (type == PGP_USERID)
       +      for (i = 1; i < n; i++)
       +        if (remailer[i].flags.pgp && bufifind(p, remailer[i].name))
       +          pgpkey[i] = 1;
       +  for (i = 1; i < n; i++)
       +    remailer[i].flags.pgp = pgpkey[i];
       +  buf_free(p);
       +  buf_free(keyring);
       +  return (0);
       +}
       +
       +int pgp_rkeylist(REMAILER remailer[], int keyid[], int n)
       +     /* Step through all remailers and get keyid */
       +{
       +  BUFFER *userid;
       +  BUFFER *id;
       +  int i, err;
       +
       +  userid = buf_new();
       +  id = buf_new();
       +
       +  for (i = 1; i < n; i++) {
       +    buf_clear(userid);
       +    buf_setf(userid, "<%s>", remailer[i].addr);
       +
       +    keyid[i]=0;
       +    if (remailer[i].flags.pgp) {
       +      buf_clear(id);
       +      err = pgpdb_getkey(PK_VERIFY, PGP_ANY, NULL, NULL, NULL, NULL, userid, NULL, id, NULL, NULL);
       +      if (id->length == 8) {
       +        /* printf("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n",
       +           id->data[0], id->data[1], id->data[2], id->data[3], id->data[4], id->data[5], id->data[6], id->data[7], id->data[8], remailer[i].addr); */
       +        keyid[i] = (((((id->data[4] << 8) + id->data[5]) << 8) + id->data[6]) << 8) + id->data[7];
       +      }
       +    }
       +  }
       +
       +  buf_free(userid);
       +  return (0);
       +}
       +
       +#endif /* USE_PGP */
   DIR diff --git a/Src/pgpget.c b/Src/pgpget.c
       t@@ -0,0 +1,870 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Read OpenPGP packets
       +   $Id: pgpget.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#ifdef USE_PGP
       +#include "pgp.h"
       +#include "crypto.h"
       +#include <time.h>
       +#include <assert.h>
       +#include <string.h>
       +
       +int pgp_getmsg(BUFFER *in, BUFFER *key, BUFFER *sig, char *pubring,
       +               char *secring)
       +{
       +  BUFFER *p;
       +  BUFFER *out;
       +  int type, algo = 0;
       +  int err = PGP_NOMSG;
       +  pgpsig signature = {0, NULL, 0, 0, {0,} };
       +
       +  p = buf_new();
       +  out = buf_new();
       +
       +  if (sig)
       +    signature.userid = buf_new();
       +
       +  while ((type = pgp_getpacket(in, p)) > 0)
       +    switch (type) {
       +    case PGP_LITERAL:
       +      pgp_getliteral(p);
       +      buf_move(out, p);
       +      err = 0;
       +      break;
       +    case PGP_COMPRESSED:
       +      err = pgp_uncompress(p);
       +      if (err == 0)
       +        err = pgp_getmsg(p, key, sig, pubring, secring);
       +      if (err != PGP_ERR && err != PGP_PASS)
       +        buf_move(out, p);
       +      break;
       +    case PGP_ENCRYPTED:
       +    case PGP_ENCRYPTEDMDC:
       +      if (!key) {
       +        err = -1;
       +        break;
       +      }
       +      if (/*key->length > 0 &&*/ algo == 0) {
       +        algo = PGP_K_IDEA;
       +        digest_md5(key, key);
       +      }
       +      if (key->length > 0)
       +        err = pgp_getsymmetric(p, key, algo, type==PGP_ENCRYPTEDMDC);
       +      else
       +        err = -1;
       +      if (err == 0)
       +        err = pgp_getmsg(p, NULL, sig, pubring, secring);
       +      if (err != PGP_ERR)
       +        buf_move(out, p);
       +      break;
       +    case PGP_SESKEY:
       +      if (!key) {
       +        err = -1;
       +        break;
       +      }
       +      err = pgp_getsessionkey(p, key, secring);
       +      if (err >= 0) {
       +        algo = err;
       +        err = 0;
       +        buf_set(key, p);
       +      }
       +      break;
       +    case PGP_SYMSESKEY:
       +      if (!key) {
       +        err = -1;
       +        break;
       +      }
       +      err = pgp_getsymsessionkey(p, key);
       +      if (err >= 0) {
       +        algo = err;
       +        err = 0;
       +        if (key) buf_set(key, p);
       +      }
       +      break;
       +    case PGP_MARKER:
       +        err = 0;
       +        break; /* ignore per RFC2440 */
       +    case PGP_SIG:
       +      pgp_getsig(p, &signature, pubring);
       +      /* fallthru */
       +    default:
       +      if (err == PGP_NOMSG)
       +        err = PGP_NODATA;
       +    }
       +
       +  if (signature.ok == PGP_SIGVRFY)
       +    pgp_verify(out, sig, &signature);
       +  if (signature.ok == PGP_SIGOK) {
       +    char line[LINELEN];
       +    time_t t;
       +    struct tm *tc;
       +
       +    t = signature.sigtime;
       +    tc = localtime(&t);
       +#if 0
       +    strftime(line, LINELEN, "[%Y-%m-%d %H:%M:%S]", tc);
       +#else /* end of 0 */
       +    strftime(line, LINELEN, "[%a %b %d %H:%M:%S %Y]", tc);
       +#endif /* else if not 0 */
       +    if (sig) {
       +      buf_cat(sig, signature.userid);
       +      buf_appendc(sig, ' ');
       +      buf_appends(sig, line);
       +    }
       +  }
       +  if (sig) {
       +    if (signature.ok == PGP_SIGNKEY)
       +      buf_appendf(sig, "%02X%02X%02X%02X", signature.userid->data[4],
       +                  signature.userid->data[5], signature.userid->data[6],
       +                  signature.userid->data[7]);
       +    buf_free(signature.userid);
       +  }
       +
       +  if ((err == 0 || err == PGP_NODATA) && signature.ok != 0)
       +    err = signature.ok;
       +
       +  buf_move(in, out);
       +  buf_free(out);
       +  buf_free(p);
       +
       +  return (err);
       +}
       +
       +int pgp_ispacket(BUFFER *b)
       +{
       +  return ((b->data[b->ptr] >> 6) == 2 || (b->data[b->ptr] >> 6) == 3);
       +}
       +
       +int pgp_packettype(BUFFER *b, long *len, int *partial)
       +{
       +  int ctb;
       +
       +  ctb = buf_getc(b);
       +  switch (ctb >> 6) {
       +  case 2:
       +    /* old packet type */
       +    switch (ctb & 3) {
       +    case 0:
       +      *len = buf_getc(b);
       +      break;
       +    case 1:
       +      *len = buf_geti(b);
       +      break;
       +    case 2:
       +      *len = buf_getl(b);
       +      break;
       +    case 3:
       +      *len = b->length - b->ptr;
       +      break;
       +    }
       +    *partial = 0;
       +    return (ctb >> 2) & 15;
       +  case 3:
       +  case 1: /* in GnuPG secret key ring */
       +    /* new packet type */
       +    *len = buf_getc(b);
       +    if (*len >= 192 && *len <= 223)
       +      *len = (*len - 192) * 256 + buf_getc(b) + 192;
       +    else if (*len == 255)
       +      *len = buf_getl(b);
       +    else if (*len > 223) {
       +      *len = 1 <<(*len & 0x1f);
       +      *partial = 1;
       +    }
       +    return (ctb & 63);
       +  }
       +  return (-1);
       +}
       +
       +int pgp_packetpartial(BUFFER *b, long *len, int *partial)
       +{
       +  *partial = 0;
       +  *len = buf_getc(b);
       +  if (*len >= 192 && *len <= 223)
       +    *len = (*len - 192) * 256 + buf_getc(b) + 192;
       +  else if (*len == 255)
       +    *len = buf_getl(b);
       +  else if (*len > 223) {
       +    *len = 1 <<(*len & 0x1f);
       +    *partial = 1;
       +  }
       +  return 1;
       +}
       +
       +int pgp_isconventional(BUFFER *b)
       +{
       +  int type;
       +  BUFFER *p;
       +  p = buf_new();
       +
       +  type = pgp_getpacket(b, p);
       +  if (type == PGP_MARKER)
       +    type = pgp_getpacket(b, p);
       +  buf_rewind(b);
       +  buf_free(p);
       +  return (type == PGP_ENCRYPTED || type == PGP_SYMSESKEY);
       +}
       +
       +int pgp_getpacket(BUFFER *in, BUFFER *p)
       +     /*  returns <0 = error, >0 = packet type */
       +{
       +  int type;
       +  long len;
       +  int partial = 0;
       +  BUFFER *tmp;
       +
       +  tmp = buf_new();
       +  type = pgp_packettype(in, &len, &partial);
       +  if (type > 0 && len > 0) {
       +    buf_clear(p);
       +    while(partial && len > 0) {
       +      buf_get(in, tmp, len);
       +      buf_cat(p, tmp);
       +      pgp_packetpartial(in, &len, &partial);
       +    }
       +    if (len > 0) {
       +      buf_get(in, tmp, len);
       +      buf_cat(p, tmp);
       +    }
       +  }
       +
       +  buf_free(tmp);
       +  return (type);
       +}
       +
       +int pgp_getsig(BUFFER *p, pgpsig *sig, char *pubring)
       +{
       +  BUFFER *sigkey, *id, *i;
       +  int algo, hashalgo;
       +  int hash;
       +
       +  sigkey = buf_new();
       +  id = buf_new();
       +  i = buf_new();
       +
       +  sig->ok = PGP_SIGBAD;
       +
       +  if (buf_getc(p) > 3)
       +    goto end;
       +  if (buf_getc(p) != 5)
       +    goto end;
       +  sig->sigtype = buf_getc(p);
       +  sig->sigtime = buf_getl(p);
       +  buf_get(p, id, 8);
       +  algo = buf_getc(p);
       +  hashalgo = buf_getc(p);
       +  if (hashalgo != PGP_H_MD5)
       +    goto end;
       +  hash = buf_geti(p);
       +  if (pgpdb_getkey(PK_VERIFY, algo, NULL, NULL, NULL, sigkey, NULL, sig->userid, id,
       +                   pubring, NULL) < 0) {
       +    sig->ok = PGP_SIGNKEY;
       +    if (sig->userid)
       +      buf_set(sig->userid, id);
       +    goto end;
       +  }
       +  switch (algo) {
       +  case PGP_ES_RSA:
       +    mpi_get(p, i);
       +    if (pgp_rsa(i, sigkey, PK_VERIFY) == -1 ||
       +        memcmp(i->data, MD5PREFIX, sizeof(MD5PREFIX) - 1) != 0)
       +      goto end;
       +    memcpy(sig->hash, i->data + sizeof(MD5PREFIX) - 1, 16);
       +    if (sig->hash[0] * 256 + sig->hash[1] != hash)
       +      goto end;
       +    sig->ok = PGP_SIGVRFY;
       +    break;
       +  default:
       +    break;
       +  }
       +end:
       +  buf_free(sigkey);
       +  buf_free(id);
       +  buf_free(i);
       +  return (sig->ok);
       +}
       +
       +void pgp_verify(BUFFER *msg, BUFFER *detached, pgpsig *sig)
       +{
       +  MD5_CTX c;
       +  BUFFER *t;
       +  byte md[16];
       +
       +  t = buf_new();
       +  sig->ok = PGP_SIGBAD;
       +
       +  if (msg->length == 0) {        /* detached signature */
       +    if (detached && detached->length) {
       +      buf_move(msg, detached);
       +      if (sig->sigtype == PGP_SIG_CANONIC)
       +        pgp_sigcanonic(msg); /* for cleartext signatures */
       +    } else
       +      sig->ok = PGP_NODATA;
       +  }
       +  MD5_Init(&c);
       +  switch (sig->sigtype) {
       +  case PGP_SIG_BINARY:
       +    MD5_Update(&c, msg->data, msg->length);
       +    break;
       +  case PGP_SIG_CANONIC:
       +    while (buf_getline(msg, t) != -1) {
       +#if 0
       +      pgp_sigcanonic(t); /* according to OpenPGP */
       +#else /* end of 0 */
       +      buf_appends(t, "\r\n");
       +#endif /* else if not 0 */
       +      MD5_Update(&c, t->data, t->length);
       +    }
       +    break;
       +  default:
       +    sig->ok = PGP_SIGBAD;
       +  }
       +  MD5_Update(&c, &(sig->sigtype), 1);
       +  buf_appendl(t, sig->sigtime);
       +  MD5_Update(&c, t->data, 4);
       +  MD5_Final(md, &c);
       +  if (memcmp(md, sig->hash, 16) == 0)
       +    sig->ok = PGP_SIGOK;
       +  buf_free(t);
       +}
       +
       +#ifdef USE_IDEA
       +static int pgp_ideadecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
       +{
       +  int err = 0;
       +  byte iv[8];
       +  byte hdr[10];
       +  int i, n;
       +  IDEA_KEY_SCHEDULE ks;
       +  SHA_CTX c;
       +  char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
       +
       +  if (key->length != 16 || in->length <= (mdc?(1+10+22):10))
       +    return (-1);
       +
       +  if (mdc) {
       +    mdc = 1;
       +    if (in->data[0] != 1)
       +      return (-1);
       +  }
       +
       +  buf_prepare(out, in->length - 10 - mdc);
       +
       +  for (i = 0; i < 8; i++)
       +    iv[i] = 0;
       +
       +  idea_set_encrypt_key(key->data, &ks);
       +
       +  n = 0;
       +  idea_cfb64_encrypt(in->data + mdc, hdr, 10, &ks, iv, &n, IDEA_DECRYPT);
       +  if (n != 2 || hdr[8] != hdr[6] || hdr[9] != hdr[7]) {
       +    err = -1;
       +    goto end;
       +  }
       +  if (mdc) {
       +    SHA1_Init(&c);
       +    SHA1_Update(&c, hdr, 10);
       +  } else {
       +    iv[6] = iv[0], iv[7] = iv[1];
       +    memcpy(iv, in->data + 2, 6);
       +    n = 0;
       +  }
       +  idea_cfb64_encrypt(in->data + 10 + mdc, out->data, in->length - 10 - mdc, &ks, iv, &n,
       +                     IDEA_DECRYPT);
       +  if (mdc) {
       +    if (out->length > 22) {
       +      out->length -= 22;
       +      if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
       +        SHA1_Update(&c, out->data, out->length + 2);
       +        SHA1_Final(md, &c);
       +        if (memcmp(out->data + out->length + 2, md, 20))
       +          err = -1;
       +      } else
       +        err = -1;
       +    } else
       +      err = -1;
       +  }
       +end:
       +  return (err);
       +}
       +#endif /* USE_IDEA */
       +
       +static int pgp_3desdecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
       +{
       +  int err = 0;
       +  des_cblock iv;
       +  byte hdr[10];
       +  int i, n;
       +  des_key_schedule ks1;
       +  des_key_schedule ks2;
       +  des_key_schedule ks3;
       +  SHA_CTX c;
       +  char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
       +
       +  if (key->length != 24 || in->length <= (mdc?(1+10+22):10))
       +    return (-1);
       +
       +  if (mdc) {
       +    mdc = 1;
       +    if (in->data[0] != 1)
       +      return (-1);
       +  }
       +
       +  buf_prepare(out, in->length - 10 - mdc);
       +
       +  for (i = 0; i < 8; i++)
       +    iv[i] = 0;
       +
       +  des_set_key((const_des_cblock *) key->data, ks1);
       +  des_set_key((const_des_cblock *) (key->data + 8), ks2);
       +  des_set_key((const_des_cblock *) (key->data+ 16), ks3);
       +
       +  n = 0;
       +  des_ede3_cfb64_encrypt(in->data + mdc, hdr, 10, ks1, ks2, ks3, &iv, &n, DECRYPT);
       +  if (n != 2 || hdr[8] != hdr[6] || hdr[9] != hdr[7]) {
       +    err = -1;
       +    goto end;
       +  }
       +  if (mdc) {
       +    SHA1_Init(&c);
       +    SHA1_Update(&c, hdr, 10);
       +  } else {
       +    iv[6] = iv[0], iv[7] = iv[1];
       +    memcpy(iv, in->data + 2, 6);
       +    n = 0;
       +  }
       +  des_ede3_cfb64_encrypt(in->data + 10 + mdc, out->data, in->length - 10 + mdc, ks1,
       +                         ks2, ks3, &iv, &n, DECRYPT);
       +  if (mdc) {
       +    if (out->length > 22) {
       +      out->length -= 22;
       +      if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
       +        SHA1_Update(&c, out->data, out->length + 2);
       +        SHA1_Final(md, &c);
       +        if (memcmp(out->data + out->length + 2, md, 20))
       +          err = -1;
       +      } else
       +        err = -1;
       +    } else
       +      err = -1;
       +  }
       +end:
       +  return (err);
       +}
       +
       +static int pgp_castdecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
       +{
       +  int err = 0;
       +  byte iv[8];
       +  byte hdr[10];
       +  int i, n;
       +  SHA_CTX c;
       +  char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
       +
       +  CAST_KEY ks;
       +
       +  if (key->length != 16 || in->length <= (mdc?(1+10+22):10))
       +    return (-1);
       +
       +  if (mdc) {
       +    mdc = 1;
       +    if (in->data[0] != 1)
       +      return (-1);
       +  }
       +
       +  buf_prepare(out, in->length - 10 - mdc);
       +
       +  for (i = 0; i < 8; i++)
       +    iv[i] = 0;
       +
       +  CAST_set_key(&ks, 16, key->data);
       +
       +  n = 0;
       +  CAST_cfb64_encrypt(in->data + mdc, hdr, 10, &ks, iv, &n, CAST_DECRYPT);
       +  if (n != 2 || hdr[8] != hdr[6] || hdr[9] != hdr[7]) {
       +    err = -1;
       +    goto end;
       +  }
       +  if (mdc) {
       +    SHA1_Init(&c);
       +    SHA1_Update(&c, hdr, 10);
       +  } else {
       +    iv[6] = iv[0], iv[7] = iv[1];
       +    memcpy(iv, in->data + 2, 6);
       +    n = 0;
       +  }
       +  CAST_cfb64_encrypt(in->data + 10 + mdc, out->data, in->length - 10 - mdc, &ks,
       +                     iv, &n, CAST_DECRYPT);
       +  if (mdc) {
       +    if (out->length > 22) {
       +      out->length -= 22;
       +      if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
       +        SHA1_Update(&c, out->data, out->length + 2);
       +        SHA1_Final(md, &c);
       +        if (memcmp(out->data + out->length + 2, md, 20))
       +          err = -1;
       +      } else
       +        err = -1;
       +    } else
       +      err = -1;
       +  }
       +end:
       +  return (err);
       +}
       +
       +static int pgp_bfdecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
       +{
       +  int err = 0;
       +  byte iv[8];
       +  byte hdr[10];
       +  int i, n;
       +  SHA_CTX c;
       +  char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
       +
       +  BF_KEY ks;
       +
       +  if (key->length != 16 || in->length <= (mdc?(1+10+22):10))
       +    return (-1);
       +
       +  if (mdc) {
       +    mdc = 1;
       +    if (in->data[0] != 1)
       +      return (-1);
       +  }
       +
       +  buf_prepare(out, in->length - 10 - mdc);
       +
       +  for (i = 0; i < 8; i++)
       +    iv[i] = 0;
       +
       +  BF_set_key(&ks, 16, key->data);
       +
       +  n = 0;
       +  BF_cfb64_encrypt(in->data + mdc, hdr, 10, &ks, iv, &n, BF_DECRYPT);
       +  if (n != 2 || hdr[8] != hdr[6] || hdr[9] != hdr[7]) {
       +    err = -1;
       +    goto end;
       +  }
       +  if (mdc) {
       +    SHA1_Init(&c);
       +    SHA1_Update(&c, hdr, 10);
       +  } else {
       +    iv[6] = iv[0], iv[7] = iv[1];
       +    memcpy(iv, in->data + 2, 6);
       +    n = 0;
       +  }
       +  BF_cfb64_encrypt(in->data + 10 + mdc, out->data, in->length - 10 - mdc, &ks,
       +                   iv, &n, BF_DECRYPT);
       +  if (mdc) {
       +    if (out->length > 22) {
       +      out->length -= 22;
       +      if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
       +        SHA1_Update(&c, out->data, out->length + 2);
       +        SHA1_Final(md, &c);
       +        if (memcmp(out->data + out->length + 2, md, 20))
       +          err = -1;
       +      } else
       +        err = -1;
       +    } else
       +      err = -1;
       +  }
       +end:
       +  return (err);
       +}
       +
       +#ifdef USE_AES
       +static int pgp_aesdecrypt(BUFFER *in, BUFFER *out, BUFFER *key, int mdc)
       +{
       +  int err = 0;
       +  byte iv[16];
       +  byte hdr[18];
       +  int i, n;
       +  SHA_CTX c;
       +  char md[20]; /* we could make hdr 20 bytes long and reuse it for md */
       +
       +  AES_KEY ks;
       +
       +  if ((key->length != 16 && key->length != 24 && key->length != 32) || in->length <= (mdc?(1+18+22):18))
       +    return (-1);
       +
       +  if (mdc) {
       +    mdc = 1;
       +    if (in->data[0] != 1)
       +      return (-1);
       +  }
       +
       +  buf_prepare(out, in->length - 18 - mdc);
       +
       +  for (i = 0; i < 16; i++)
       +    iv[i] = 0;
       +
       +  AES_set_encrypt_key(key->data, key->length<<3, &ks);
       +
       +  n = 0;
       +  AES_cfb128_encrypt(in->data + mdc, hdr, 18, &ks, iv, &n, AES_DECRYPT);
       +  if (n != 2 || hdr[16] != hdr[14] || hdr[17] != hdr[15]) {
       +    err = -1;
       +    goto end;
       +  }
       +  if (mdc) {
       +    SHA1_Init(&c);
       +    SHA1_Update(&c, hdr, 18);
       +  } else {
       +    iv[14] = iv[0], iv[15] = iv[1];
       +    memcpy(iv, in->data + 2, 14);
       +    n = 0;
       +  }
       +  AES_cfb128_encrypt(in->data + 18 + mdc, out->data, in->length - 18 - mdc, &ks,
       +                   iv, &n, AES_DECRYPT);
       +  if (mdc) {
       +    if (out->length > 22) {
       +      out->length -= 22;
       +      if (out->data[out->length] == 0xD3 && out->data[out->length + 1] == 0x14) {
       +        SHA1_Update(&c, out->data, out->length + 2);
       +        SHA1_Final(md, &c);
       +        if (memcmp(out->data + out->length + 2, md, 20))
       +          err = -1;
       +      } else
       +        err = -1;
       +    } else
       +      err = -1;
       +  }
       +end:
       +  return (err);
       +}
       +#endif /* USE_AES */
       +
       +int pgp_getsymmetric(BUFFER *in, BUFFER *key, int algo, int mdc)
       +{
       +  int err = -1;
       +  BUFFER *out;
       +
       +  out = buf_new();
       +
       +  switch (algo) {
       +#ifdef USE_AES
       +   case PGP_K_AES128:
       +   case PGP_K_AES192:
       +   case PGP_K_AES256:
       +    err = pgp_aesdecrypt(in, out, key, mdc);
       +    break;
       +#endif /* USE_AES */
       +#ifdef USE_IDEA
       +   case PGP_K_IDEA:
       +    err = pgp_ideadecrypt(in, out, key, mdc);
       +    break;
       +#endif /* USE_IDEA */
       +   case PGP_K_3DES:
       +    err = pgp_3desdecrypt(in, out, key, mdc);
       +    break;
       +   case PGP_K_CAST5:
       +    err = pgp_castdecrypt(in, out, key, mdc);
       +    break;
       +  case PGP_K_BF:
       +    err = pgp_bfdecrypt(in, out, key, mdc);
       +    break;
       +  }
       +
       +  if (err < 0)
       +    errlog(ERRORMSG, "PGP decryption failed.\n");
       +
       +  buf_move(in, out);
       +  buf_free(out);
       +  return (err);
       +}
       +
       +int pgp_getliteral(BUFFER *in)
       +{
       +  long fnlen;
       +  int err = 0;
       +  int mode;
       +  BUFFER *out;
       +  BUFFER *line;
       +
       +  out = buf_new();
       +  line = buf_new();
       +  mode = buf_getc(in);
       +  fnlen = buf_getc(in);
       +  in->ptr += fnlen;                /* skip filename */
       +  if (in->ptr + 4 > in->length)
       +    err = -1;
       +  else {
       +    buf_getl(in);                /* timestamp */
       +    if (mode == 't')
       +      while (buf_getline(in, line) != -1) {
       +        buf_cat(out, line);
       +        buf_nl(out);
       +    } else
       +      buf_rest(out, in);
       +  }
       +  buf_move(in, out);
       +  buf_free(line);
       +  buf_free(out);
       +  return (err);
       +}
       +
       +int pgp_uncompress(BUFFER *in)
       +{
       +  int err = -1;
       +
       +  switch(buf_getc(in)) {
       +  case 0:
       +    err = 0;
       +    break;
       +  case 1:
       +    err = buf_unzip(in, 0);
       +    break;
       +  case 2:
       +    err = buf_unzip(in, 1);
       +    break;
       +  default:
       +     err = -1;
       +     break;
       +  }
       +  return (err);
       +}
       +
       +int pgp_getsessionkey(BUFFER *in, BUFFER *pass, char *secring)
       +{
       +  BUFFER *out;
       +  BUFFER *key;
       +  BUFFER *keyid;
       +  int type;
       +  int i, csum = 0;
       +  int algo = 0;
       +  int err = -1;
       +  long expires;
       +
       +  out = buf_new();
       +  key = buf_new();
       +  keyid = buf_new();
       +  type = buf_getc(in);                /* packet type */
       +  if (type < 2 || type > 3)
       +    goto end;
       +  buf_get(in, keyid, 8);
       +  algo = buf_getc(in);
       +  err = pgpdb_getkey(PK_DECRYPT, algo, NULL, NULL, &expires, key, NULL, NULL, keyid,
       +                     secring, pass);
       +  if (err < 0)
       +    goto end;
       +  if (expires > 0 && (expires + KEYGRACEPERIOD < time(NULL))) {
       +    errlog(DEBUGINFO, "Key expired.\n"); /* DEBUGINFO ? */
       +    err = -1;
       +    goto end;
       +  }
       +  switch (algo) {
       +  case PGP_ES_RSA:
       +    mpi_get(in, out);
       +    err = pgp_rsa(out, key, PK_DECRYPT);
       +    break;
       +   case PGP_E_ELG:
       +    buf_rest(out, in);
       +    err = pgp_elgdecrypt(out, key);
       +    break;
       +  default:
       +    err = -1;
       +  }
       +  if (err == 0 && out->length > 3) {
       +    algo = buf_getc(out);
       +    buf_get(out, in, out->length - 3); /* return recovered key */
       +    csum = buf_geti(out);
       +    for (i = 0; i < in->length; i++)
       +      csum = (csum - in->data[i]) % 65536;
       +    if (csum != 0)
       +      err = -1;
       +  } else
       +    err = -1;
       +end:
       +  buf_free(out);
       +  buf_free(key);
       +  buf_free(keyid);
       +  return (err == 0 ? algo : err);
       +}
       +
       +void pgp_iteratedsk(BUFFER *out, BUFFER *salt, BUFFER *pass, byte c)
       +{
       +  int count;
       +  BUFFER *temp;
       +  temp = buf_new();
       +
       +  count = (16l + (c & 15)) << ((c >> 4) + 6);
       +  while (temp->length < count) {
       +    buf_cat(temp, salt);
       +    buf_cat(temp, pass);
       +  }
       +  buf_get(temp, out, count);
       +  buf_free(temp);
       +}
       +
       +int pgp_getsk(BUFFER *p, BUFFER *pass, BUFFER *key)
       +{
       +  int skalgo, skspecifier, hashalgo;
       +  BUFFER *salted; /* passphrase with salt */
       +
       +  if (!pass)
       +    return(-1);
       +
       +  salted = buf_new();
       +
       +  skalgo = buf_getc(p);
       +  skspecifier = buf_getc(p);
       +  hashalgo = buf_getc(p);
       +  switch (skspecifier) {
       +  case 0:
       +    buf_set(salted, pass);
       +    break;
       +  case 1:
       +    buf_get(p, salted, 8); /* salt */
       +    buf_cat(salted, pass);
       +    break;
       +  case 3:
       +    buf_get(p, salted, 8); /* salt */
       +    pgp_iteratedsk(salted, salted, pass, buf_getc(p));
       +    break;
       +  default:
       +    skalgo = -1;
       +    goto end;
       +  }
       +  if (pgp_expandsk(key, skalgo, hashalgo, salted) == -1)
       +    skalgo = -1;
       +
       + end:
       +  buf_free(salted);
       +  return (skalgo);
       +}
       +
       +int pgp_getsymsessionkey(BUFFER *in, BUFFER *pass)
       +{
       +  BUFFER *temp, *key, *iv;
       +  int algo = -1;
       +  temp = buf_new();
       +  key = buf_new();
       +  iv = buf_new();
       +
       +  if (buf_getc(in) == 4) {  /* version */
       +    algo = pgp_getsk(in, pass, key);
       +    buf_rest(temp, in);
       +    if (temp->length) {
       +      /* encrypted session key present */
       +      buf_appendzero(iv, pgp_blocklen(algo));
       +      skcrypt(temp, algo, key, iv, DECRYPT);
       +      algo = buf_getc(temp);
       +      buf_rest(in, temp);
       +    } else
       +      buf_set(in, key);
       +  }
       +  buf_free(temp);
       +  buf_free(key);
       +  buf_free(iv);
       +  return (algo);
       +}
       +
       +#endif /* USE_PGP */
   DIR diff --git a/Src/pool.c b/Src/pool.c
       t@@ -0,0 +1,981 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Send messages from pool
       +   $Id: pool.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +#include "mix3.h"
       +#include <stdlib.h>
       +#include <string.h>
       +#include <ctype.h>
       +#include <sys/types.h>
       +#include <time.h>
       +#ifdef POSIX
       +#include <unistd.h>
       +#else /* end of POSIX */
       +#include <io.h>
       +#endif /* else if not POSIX */
       +#ifndef _MSC
       +#include <dirent.h>
       +#endif /* not _MSC */
       +#include <assert.h>
       +#include <sys/stat.h>
       +#include <sys/types.h>
       +
       +#ifdef USE_PCRE
       +#include "pcre.h"
       +#endif /* USE_PCRE */
       +
       +int msg_send(char *name);
       +
       +int mix_send(void)
       +{
       +  return (mix_regular(FORCE_POOL));
       +}
       +
       +/* Message pool:       Unix  DOS
       + * latent messages:      l*  *.lat
       + * pooled messages:      m*  *.msg
       + * messages to be sent:  s*  *.snd
       + * temporary files:      t*  *.tmp
       + * files in user editor: x*
       + * incoming mail:        i*  *.inf
       + * partial messages:     p*  p*.*
       + * error messages:       e*  *.err
       + * outgoing messages:    out *.txt (to be used by external program)
       + */
       +
       +static int is(char *path, char *type)
       +{
       +#ifdef SHORTNAMES
       +  int s;
       +
       +  s = strlen(path);
       +  if (s <= 4)
       +    return 0;
       +  return (path[s - 4] == '.' && streq(path + s - 3, type));
       +#else /* end of SHORTNAMES */
       +  return (path[0] == type[0]);
       +#endif /* else if not SHORTNAMES */
       +}
       +
       +static void mv(char *name, char *newtype)
       +{
       +  char old[PATHMAX], new[PATHMAX];
       +
       +  sprintf(old, "%s%c%s", POOLDIR, DIRSEP, name);
       +#ifdef SHORTNAMES
       +  assert(strlen(name) > 4);
       +  strcpy(name + strlen(name) - 3, newtype);
       +#else /* end of SHORTNAMES */
       +  name[0] = newtype[0];
       +#endif /* else if not SHORTNAMES */
       +  sprintf(new, "%s%c%s", POOLDIR, DIRSEP, name);
       +  rename(old, new);
       +}
       +
       +int latent_read(void)
       +{
       +  char path[PATHMAX];
       +  DIR *d;
       +  FILE *f;
       +  struct dirent *e;
       +  int size = 0;
       +  long now, then;
       +
       +  now = time(NULL);
       +  d = opendir(POOLDIR);
       +  if (d != NULL)
       +    for (;;) {
       +      e = readdir(d);
       +      if (e == NULL)
       +        break;
       +      if (is(e->d_name, "lat")) {
       +        sprintf(path, "%s%c%s", POOLDIR, DIRSEP, e->d_name);
       +        f = fopen(path, "rb");
       +        if (f != NULL) {
       +          fscanf(f, "%*d %ld\n", &then);
       +          fclose(f);
       +          if (now > then)
       +            mv(e->d_name, "msg");
       +        }
       +      }
       +    }
       +  closedir(d);
       +  return (size);
       +}
       +
       +int infile_read(void)
       +{
       +  char path[PATHMAX];
       +  BUFFER *msg;
       +  DIR *d;
       +  FILE *f;
       +  struct dirent *e;
       +  int size = 0;
       +
       +  msg = buf_new();
       +  d = opendir(POOLDIR);
       +  if (d != NULL)
       +    for (;;) {
       +      e = readdir(d);
       +      if (e == NULL)
       +        break;
       +      if (is(e->d_name, "inf")) {
       +        mv(e->d_name, "tmp");
       +        sprintf(path, "%s%c%s", POOLDIR, DIRSEP, e->d_name);
       +        f = fopen(path, "rb");
       +        if (f != NULL) {
       +          buf_clear(msg);
       +          buf_read(msg, f);
       +          fclose(f);
       +          unlink(path);
       +          mix_decrypt(msg);
       +        }
       +      }
       +    }
       +  closedir(d);
       +  buf_free(msg);
       +  return (size);
       +}
       +
       +int mailin_maildir_one(char *dir)
       +/** Read mails from one directory
       +    This function reads all files from the directory passed and passes
       +    them on to mix_decrypt(). Each file is unlinked when its is read.
       +
       +    @param dir        The directory in which files are to be read. No path finding
       +                    voodoo is done to the path; It's passed it opendir() as is.
       +    @author        PP
       +    @return        Number of files read
       + */
       +{
       +  BUFFER *msg;
       +  DIR *d;
       +  FILE *f;
       +  struct dirent *e;
       +  int size = 0;
       +  char path[PATHMAX];
       +
       +  msg = buf_new();
       +  d = opendir(dir);
       +  if (d != NULL)
       +    for (;;) {
       +      e = readdir(d);
       +      if (e == NULL)
       +        break;
       +      if (e->d_name[0] != '.') {
       +        sprintf(path, "%s%c%s", dir, DIRSEP, e->d_name);
       +        path[PATHMAX-1]='\0';
       +        f = fopen(path, "rb");
       +        if (f != NULL) {
       +          buf_clear(msg);
       +          buf_read(msg, f);
       +          fclose(f);
       +          unlink(path);
       +          mix_decrypt(msg);
       +          size++;
       +        }
       +      }
       +    }
       +  closedir(d);
       +  buf_free(msg);
       +  return (size);
       +}
       +
       +int mailin_maildir(char *maildir)
       +/** Read mails from a mail folder in Maildir format
       +    Reads all files from the Maildir using mailin_maildir_one().
       +    All mails are removed after this function returns.
       +
       +    @param maildir        The Maildir to open. mixfile() is called to normalize the path.
       +    @author        PP
       +    @return        0
       + */
       +{
       +  char normalized[PATHMAX];
       +  char path[PATHMAX];
       +
       +  mixfile(normalized, maildir);
       +  sprintf(path, "%s%c%s", normalized, DIRSEP, "new");
       +  path[PATHMAX-1]='\0';
       +  mailin_maildir_one(path);
       +  sprintf(path, "%s%c%s", normalized, DIRSEP, "cur");
       +  path[PATHMAX-1]='\0';
       +  mailin_maildir_one(path);
       +  return (0);
       +}
       +
       +int mailin_mbox(char *path)
       +/** Read mails from a mail folder in mbox format
       +    Reads all messages from the mbox filder passes as an argument. Mails are
       +    handed over to mix_decrypt. After all mails have been read the mailbox
       +    is truncated to zero size i.e. all mails are deleted. The mbox is
       +    locked using lock() and unlock() during this operation.
       +
       +    @param maildir        Path to the mbox mail folder.
       +    @author        PP
       +    @return        0 on sucess, other on error
       + */
       +{
       +  char line[LINELEN];
       +  FILE *f;
       +  int state, eof;
       +  BUFFER *msg;
       +  int err=0;
       +
       +  msg = buf_new();
       +
       +  f = mix_openfile(path, "r+");
       +  if (f != NULL) {
       +    if (lock(f) != 0) {
       +      /* Locking failed */
       +      err = 1;
       +      goto end;
       +    }
       +    /* State machine
       +     * 1 - Look for the first ^From_ line
       +     * 2 - add messages as they come
       +     */
       +    state = 1;
       +    eof = 0;
       +    for(;;) {
       +      if (fgets(line, sizeof(line), f) == NULL)
       +        eof = 1;
       +
       +      switch (state) {
       +        case 1:
       +          /* Initial state - Looking for first appearance of From_ */
       +          if (eof)
       +            goto end_state;
       +          if (strleft(line, "From ")) {
       +#if 0
       +            buf_appends(msg, line);
       +#endif /* 0 */
       +            state = 2;
       +            break;
       +          };
       +          break;
       +        case 2:
       +          /* Within one mail - Adding lines to mail until we encounter another From_ or eof */
       +          if (eof || strleft(line, "From ")) {
       +            mix_decrypt(msg);
       +            buf_clear(msg);
       +          }
       +          if (eof)
       +            goto end_state;
       +          if (!strleft(line, "From "))
       +            buf_appends(msg, line);
       +          break;
       +        default:
       +          assert(0);
       +          err=1;
       +          goto end_state;
       +      }
       +    }
       +end_state:
       +#ifndef WIN32
       +    rewind(f);
       +    ftruncate(fileno(f), 0);
       +#else /* end of not WIN32 */
       +    chsize(fileno(f), 0);
       +#endif /* else if WIN32 */
       +    unlock(f);
       +    fclose(f);
       +  }
       +end:
       +  buf_free(msg);
       +  return (err);
       +}
       +
       +/** Process MAILIN if applicable
       +    If MAILIN is defined this function calls either mailin_maildir() or
       +    mailin_mbox() depending on whether the last character of MAILIN
       +    is DIRSEP.
       +
       +    @param mailbox        Path to the mbox or Maildir mail folder.
       +    @author        PP
       +    @return        0 on sucess, other on error
       + */
       +int mailin(char *mailbox)
       +{
       +  if (mailbox != NULL && (strcmp(mailbox, "") != 0))
       +    if (mailbox[strlen(mailbox)-1] == DIRSEP)
       +      return mailin_maildir(mailbox);
       +    else
       +      return mailin_mbox(mailbox);
       +  else
       +    return 0;
       +};
       +
       +int pool_add(BUFFER *msg, char *type)
       +{
       +  char path[PATHMAX], pathtmp[PATHMAX];
       +  FILE *f;
       +  int err = -1;
       +
       +  f = pool_new(type, pathtmp, path);
       +  if (f != NULL) {
       +    err = buf_write(msg, f);
       +    fclose(f);
       +  }
       +  if (err == 0) {
       +    rename(pathtmp, path);
       +    errlog(DEBUGINFO, "Added %s file to pool.\n", type);
       +  }
       +  return (err);
       +
       +}
       +
       +FILE *pool_new(char *type, char *tmpname, char *path)
       +{
       +  FILE *f;
       +  struct stat buf;
       +  int err;
       +
       +  assert(strlen(type) == 3);
       +#ifdef SHORTNAMES
       +  sprintf(tmpname, "%s%c%02x%02x%02x%02x.tmp", POOLDIR, DIRSEP, rnd_byte(), rnd_byte(),
       +          rnd_byte(), rnd_byte());
       +  strcpy(path, tmpname);
       +  memcpy(path + strlen(path) - 3, type, 3);
       +#else /* end of SHORTNAMES */
       +  sprintf(tmpname, "%s%ct%02x%02x%02x%02x%02x%02x%01x", POOLDIR, DIRSEP, rnd_byte(),
       +          rnd_byte(), rnd_byte(), rnd_byte(), rnd_byte(),
       +          rnd_byte(), rnd_byte() & 15);
       +  strcpy(path, tmpname);
       +  strrchr(path, DIRSEP)[1] = type[0];
       +#endif /* else if not SHORTNAMES */
       +  err = stat(tmpname, &buf);
       +  if (err == 0)
       +    errlog(WARNING, "Overwriting file %s\n", tmpname);
       +  f = fopen(tmpname, "wb");
       +  if (f == NULL)
       +    errlog(ERRORMSG, "Error creating temporary file %s\n", tmpname);
       +  return (f);
       +}
       +
       +int pool_read(BUFFER *pool)
       +{
       +  DIR *d;
       +  struct dirent *e;
       +  int size = 0;
       +
       +  d = opendir(POOLDIR);
       +  if (d != NULL) {
       +    for (;;) {
       +      e = readdir(d);
       +      if (e == NULL)
       +        break;
       +      if (is(e->d_name, "msg")) {
       +        if (pool != NULL) {
       +          buf_appends(pool, e->d_name);
       +          buf_appendc(pool, 0);
       +        }
       +        size++;
       +      }
       +    }
       +    closedir(d);
       +  } else
       +    errlog(WARNING, "Error reading pool dir %s\n", POOLDIR);
       +  return (size);
       +}
       +
       +void pool_dosend(void)
       +{
       +  DIR *d;
       +  struct dirent *e;
       +  char path[PATHMAX];
       +
       +  d = opendir(POOLDIR);
       +  if (d != NULL) {
       +    for (;;) {
       +      e = readdir(d);
       +      if (e == NULL)
       +        break;
       +      if (is(e->d_name, "snd")) {
       +        sendmail_begin();
       +        mv(e->d_name, "tmp");
       +        sprintf(path, "%s%c%s", POOLDIR, DIRSEP, e->d_name);
       +        if (msg_send(path) == 1)
       +          mv(e->d_name, "err");
       +      }
       +    }
       +    closedir(d);
       +  } else
       +    errlog(WARNING, "Error reading pool dir %s\n", POOLDIR);
       +  sendmail_end();
       +}
       +
       +int process_mailin()
       +{
       +  mailin(MAILIN);
       +  infile_read();
       +  return(0);
       +}
       +
       +int create_dummy_mailout()
       +{
       +  while (rnd_number(100) < OUTDUMMYP) {
       +    errlog(DEBUGINFO, "Generating dummy message with outgoing mail.\n");
       +    if (mix_encrypt(MSG_NULL, NULL, NULL, 1, NULL) == -1)
       +      return -1;
       +  }
       +  return 0;
       +}
       +
       +int pool_send(void)
       +{
       +  int size, max, i, r;
       +  BUFFER *pool;
       +  long int *ptr;
       +
       +  create_dummy_mailout();
       +
       +  latent_read();
       +  pool = buf_new();
       +  size = pool_read(pool);
       +  if (size <= POOLSIZE)
       +    goto end;
       +
       +  ptr = malloc(size * sizeof(long int));
       +
       +  if (ptr == NULL)
       +    goto end;
       +  for (i = 0; i < size; i++) {
       +    ptr[i] = pool->ptr;
       +    buf_getline(pool, NULL);
       +  }
       +
       +  max = size * RATE / 100;        /* send no more than RATE % of the messages */
       +  if (max < 0)
       +    max = 1;
       +
       +  for (i = 0; i < size - POOLSIZE && i < max; i++) {
       +    do
       +      r = rnd_number(size);        /* chose a new random message */
       +    while (is(pool->data + ptr[r], "snd"));
       +    mv(pool->data + ptr[r], "snd");
       +  }
       +  stats_out(size - --i);
       +  pool_dosend();
       +  free(ptr);
       +
       +end:
       +  buf_free(pool);
       +  return (size);
       +}
       +
       +int msg_send(char *name)
       +{
       +  FILE *f;
       +  int type = -1;
       +  BUFFER *m, *addr;
       +  int err = 0;
       +  char line[LINELEN];
       +  int userfrom = 0;
       +
       +  m = buf_new();
       +  addr = buf_new();
       +  if ((f = fopen(name, "rb")) == NULL) {
       +    err = -1;
       +    goto end;
       +  }
       +  fscanf(f, "%d %*d\n", &type);
       +  if (type == INTERMEDIATE) {
       +    fgets(line, sizeof(line), f);
       +    buf_sets(addr, line);
       +    buf_chop(addr);
       +    err = buf_read(m, f);
       +    if (err == -1)
       +      goto end;
       +    err = mix_armor(m);
       +    if (err == -1)
       +      goto end;
       +    err = sendmail(m, REMAILERADDR, addr);
       +    stats_log(3);
       +  } else if (type == MSG_MAIL || type == MSG_POST) {
       +    err = buf_read(m, f);
       +    if (err == -1)
       +      goto end;
       +    if (MIDDLEMAN && ! allowmessage(m)) {
       +      mix2_encrypt(type, m, FORWARDTO, 1, 1, NULL);
       +      stats_log(6);
       +    } else {
       +      err = filtermsg(m);
       +      if (err == 1)
       +        userfrom = 1, err = 0;
       +      if (err != -1) {
       +        /* message has recipients */
       +        errlog(DEBUGINFO, "Sending message (%ld bytes)\n", m->length);
       +
       +        if (type == MSG_MAIL) {
       +          err = sendmail(m, userfrom ? NULL : ANONNAME, NULL);
       +          stats_log(4);
       +        } else if (type == MSG_POST) {
       +          if (strchr(NEWS, '@') && !strchr(NEWS, ' ')) {
       +            errlog(LOG, "Mailing article to %s.\n", NEWS);
       +            buf_sets(addr, NEWS);
       +            err = sendmail(m, userfrom ? NULL : ANONNAME, addr);
       +          } else if (NEWS[0] != '\0') {
       +            FILE *f;
       +
       +            f = openpipe(NEWS);
       +            if (f == NULL)
       +              goto end;
       +            errlog(LOG, "Posting article.\n");
       +            if (!userfrom)
       +              fprintf(f, "From: %s\n", ANONNAME);
       +            if (ORGANIZATION[0] != '\0')
       +              fprintf(f, "Organization: %s\n", ORGANIZATION);
       +            buf_write(m, f);
       +            closepipe(f);
       +          } else
       +            errlog(NOTICE, "Rejecting news article.\n");
       +          stats_log(5);
       +        }
       +      } else
       +        errlog(ERRORMSG, "Bad message file.\n");
       +    }
       +  }
       +end:
       +  if (f != NULL)
       +    fclose(f);
       +  if (err != 1)                        /* problem sending mail */
       +    unlink(name);
       +  buf_free(m);
       +  buf_free(addr);
       +  return (err);
       +}
       +
       +int allowmessage(BUFFER *in)
       +/* Only called if remailer is middleman. Checks whether all Recipient
       + * addresses are in dest.allow. If yes return 1; 0 otherwhise
       + */
       +{
       +  BUFFER *out, *allow, *allow2, *line, *line2;
       +  int err=1;
       +  FILE *f;
       +
       +  allow = buf_new();
       +  allow2 = buf_new();
       +  out = buf_new();
       +  line = buf_new();
       +  line2 = buf_new();
       +
       +  f = mix_openfile(DESTALLOW, "r");
       +  if (f != NULL) {
       +    buf_read(allow, f);
       +    fclose(f);
       +  }
       +  f = mix_openfile(DESTALLOW2, "r");
       +  if (f != NULL) {
       +    buf_read(allow2, f);
       +    fclose(f);
       +    buf_cat(allow, allow2);
       +  }
       +
       +  /* Do header lines */
       +  while (buf_getline(in, line) == 0) {
       +    for (;;) {
       +      buf_lookahead(in, line2);
       +      if (!bufleft(line2, " ") && !bufleft(line2, "\t"))
       +        break;
       +      buf_getline(in, line2);
       +      buf_cat(line, line2);
       +    }
       +
       +    if (bufileft(line, "to:") || bufileft(line, "cc:") ||
       +        bufileft(line, "bcc:") || bufileft(line, "newsgroups:"))
       +      if (! doallow(line, allow))
       +              err = 0;
       +
       +    if (line->length > 0) {
       +      if (!buffind(line, ":"))
       +         buf_appends(out, "X-Invalid: ");
       +      buf_cat(out, line);
       +      buf_nl(out);
       +    }
       +  }
       +  buf_nl(out);
       +
       +  /* Rest of the message */
       +  buf_append(out, in->data + in->ptr, in->length - in->ptr);
       +
       +  buf_move(in, out);
       +  buf_free(out);
       +  buf_free(allow);
       +  buf_free(allow2);
       +  buf_free(line);
       +  buf_free(line2);
       +  return (err);
       +}
       +
       +int doallow(BUFFER *line, BUFFER *filter)
       +/* line is a To, CC or BCC line.
       + * problem is: there may be multiple addresses in one header
       + * line but we only want to allow if _all_ are allowed
       + *
       + * So to not send direct if we do not want, we _never_ send
       + * direct if there is more than one address: This is
       + * assumed to be the case when there is a
       + * comma in the header line.
       + *
       + * this should probably be rewritten somehwhen. therefore: FIXME
       + *
       + * returns: 1 if allowed
       + *          0 if message should be send indirectly
       + */
       +{
       +  if (strchr( line->data, ',')) return 0;
       +  return doblock(line, filter, 0);
       +}
       +
       +int filtermsg(BUFFER *in)
       +{
       +  BUFFER *out, *line, *line2, *mboundary, *block, *filter, *mid;
       +  FILE *f;
       +  int from = 0, dest = 0;
       +  int inbinary = 0, inpgp = 0, l = 80;
       +  int err = -1;
       +
       +  line = buf_new();
       +  line2 = buf_new();
       +  filter = buf_new();
       +  mid = buf_new();
       +  mboundary = buf_new();
       +  out = buf_new();
       +  block = NULL;
       +
       +  if (SIZELIMIT > 0 && in->length > SIZELIMIT * 1024) {
       +    errlog(NOTICE, "Message rejected: %ld bytes\n", in->length);
       +    goto end;
       +  }
       +
       +  block = readdestblk( );
       +  if ( !block ) block = buf_new( );
       +
       +  f = mix_openfile(HDRFILTER, "r");
       +  if (f != NULL) {
       +    buf_read(filter, f);
       +    fclose(f);
       +  }
       +
       +  f = mix_openfile(DISCLAIMFILE, "r");
       +  if (f != NULL) {
       +    buf_read(out, f);
       +    fclose(f);
       +  } else {
       +    if (strfind(DISCLAIMER, "%s"))
       +      buf_appendf(out, DISCLAIMER, COMPLAINTS);
       +    else
       +      buf_appends(out, DISCLAIMER);
       +  }
       +
       +  while (buf_getline(in, line) == 0) {
       +    for (;;) {
       +      buf_lookahead(in, line2);
       +      if (!bufleft(line2, " ") && !bufleft(line2, "\t"))
       +        break;
       +      buf_getline(in, line2);
       +      buf_cat(line, line2);
       +    }
       +
       +    if (bufileft(line, "to:") || bufileft(line, "cc:") ||
       +        bufileft(line, "bcc:") || bufileft(line, "newsgroups:"))
       +      if (doblock(line, block, 1) == 0)
       +        dest++;
       +    if (doblock(line, filter, 1) == -1)
       +      goto end;
       +    if (bufileft(line, "from:"))
       +      from = 1;
       +
       +    if (bufileft(line, "content-type:") && bufileft(line, "multipart"))
       +      get_parameter(line, "boundary", mboundary);
       +
       +    if (line->length > 0) {
       +      if (!buffind(line, ":"))
       +         buf_appends(out, "X-Invalid: ");
       +       buf_cat(out, line);
       +      buf_nl(out);
       +    }
       +  }
       +
       +  if (MID[0] != '\0' && tolower(MID[0]) != 'n') {
       +    char txt[LINELEN];
       +
       +    digestmem_md5(in->data + in->ptr, in->length - in->ptr, mid);
       +    id_encode(mid->data, txt);
       +
       +    if (MID[0] == '@')
       +      strcatn(txt, MID, sizeof(txt));
       +    else {
       +      if (strchr(REMAILERADDR, '@'))
       +        strcatn(txt, strchr(REMAILERADDR, '@'), sizeof(txt));
       +      else if (strchr(COMPLAINTS, '@'))
       +        strcatn(txt, strchr(COMPLAINTS, '@'), sizeof(txt));
       +    }
       +    buf_appendf(out, "Message-ID: <%s>\n", txt);
       +  }
       +  buf_nl(out);
       +
       +  if (from) {
       +    /* prepend Sender line to message header */
       +    buf_setf(line, "Sender: %s\n", ANONNAME);
       +    buf_cat(line, out);
       +    buf_move(out, line);
       +
       +    f = mix_openfile(FROMDSCLFILE, "r");
       +    if (f != NULL) {
       +      buf_read(out, f);
       +      fclose(f);
       +    } else
       +      buf_appends(out, FROMDISCLAIMER);
       +  }
       +
       +#if 0
       +  buf_append(out, in->data + in->ptr, in->length - in->ptr);
       +#endif /* 0 */
       +  while (buf_getline(in, line) != -1) {
       +      if (boundary(line, mboundary)) {
       +      buf_cat(out, line);
       +      buf_nl(out);
       +      while (buf_getline(in, line) == 0) {        /* MIME body part header */
       +        err = doblock(line, filter, 1);
       +        if (err == -1)
       +          goto end;
       +        buf_cat(out, line);
       +        buf_nl(out);
       +      }
       +    }
       +    if (BINFILTER && l > 20 && line->length == l &&
       +        (bufleft(line, "M") || !buffind(line, " ")))
       +      inbinary++;
       +    else
       +      inbinary = 0, l = line->length;
       +    if (bufileft(line, begin_pgp) || bufileft(line, begin_key))
       +      inpgp = 1;
       +    if (bufileft(line, end_pgp) || bufileft(line, end_key))
       +      inpgp = 0;
       +    if (inbinary < 10 || inpgp) {
       +      buf_cat(out, line);
       +      buf_nl(out);
       +    } else if (inbinary == 10) {
       +      errlog(NOTICE, "Binary message detected.\n");
       +      if (BINFILTER > 1) {
       +        err = -1;
       +        goto end;
       +      }
       +      buf_appends(out, BINDISCLAIMER);
       +      buf_nl(out);
       +    }
       +  }
       +
       +  f = mix_openfile(MSGFOOTERFILE, "r");
       +  if (f != NULL) {
       +    buf_read(out, f);
       +    fclose(f);
       +  } else
       +    buf_appends(out, MSGFOOTER);
       +
       +  /* return 1 for user supplied From line */
       +  err = from;
       +  if (dest == 0)
       +    err = -1;
       +
       +end:
       +  buf_move(in, out);
       +  buf_free(out);
       +  buf_free(line);
       +  buf_free(line2);
       +  if (block) buf_free(block);
       +  buf_free(filter);
       +  buf_free(mid);
       +  buf_free(mboundary);
       +  return (err);
       +}
       +
       +BUFFER *readdestblk( )
       +{
       +       char *destblklst = (char *)malloc( strlen( DESTBLOCK )+1 );
       +       char *destblk = NULL;
       +       FILE *f;
       +       BUFFER *addresses;
       +       BUFFER *temp;
       +       int err = 1;
       +
       +       addresses = buf_new( );
       +       temp = buf_new( );
       +
       +       strcpy( destblklst, DESTBLOCK );
       +
       +       while ( (destblk = strtok( destblk ? NULL : destblklst, " " )) )
       +       {
       +               if ( (f = mix_openfile( destblk, "r" )) )
       +               {
       +                       if ( !buf_read( temp, f ) )
       +                       {
       +                               buf_cat( addresses, temp );
       +                               err = 0;
       +                       }
       +                       fclose( f );
       +               }
       +       }
       +
       +       free( destblklst );
       +       buf_free( temp );
       +
       +       if ( err ) { buf_free( addresses ); return NULL; }
       +       else return addresses;
       +}
       +
       +int doblock(BUFFER *line, BUFFER *filter, int logandreset)
       +/* logandreset is usually 0
       + * it is only set to 1 when called from doallow
       + *  which only checks whether messages are allowed to
       + *  be sent directly
       + */
       +{
       +  int block = 0;
       +  BUFFER *pattern, *result;
       +  char *t;
       +#ifdef USE_PCRE
       +  int errptr, match;
       +  const char *error;
       +  pcre *compiled;
       +  int ovector[21];
       +  char *newstr;
       +#endif /* USE_PCRE */
       +
       +  pattern = buf_new();
       +  result = buf_new();
       +  assert(filter != NULL);
       +
       +  buf_rewind(filter);
       +  while (buf_getline(filter, pattern) != -1)
       +    if (pattern->length > 0 && !bufleft(pattern, "#")) {
       +      if (bufleft(pattern, "/") && (t = strchr(pattern->data + 1, '/'))
       +          != NULL) {
       +#ifdef USE_PCRE
       +        *t = '\0';
       +        compiled = pcre_compile(pattern->data + 1, PCRE_CASELESS,
       +                                &error, &errptr
       +#ifndef USE_PCRE_OLD
       +                                ,NULL
       +#endif /* not USE_PCRE_OLD */
       +          );
       +        if (compiled) {
       +          match = pcre_exec(compiled, NULL, line->data,
       +                            line->length,
       +#if (PCRE_MAJOR == 2 && PCRE_MINOR >= 06)
       +                            0,
       +#endif /* (PCRE_MAJOR == 2 && PCRE_MINOR >= 06) */
       +#if (PCRE_MAJOR >= 3)
       +                            0,
       +#endif /* (PCRE_MAJOR >= 3) */
       +                            0, ovector, sizeof(ovector) / sizeof(int));
       +          free(compiled);
       +
       +          if (match < -1) {
       +            *t = '/';
       +            errlog(ERRORMSG, "Bad regexp %b\n", pattern);
       +          }
       +          else if (match >= 0) {
       +            /* "/pattern/q" kills the entire message */
       +            if (logandreset
       +                && strlen(pattern->data + 1) + 1 < pattern->length
       +                && pattern->data[pattern->length - 1] == 'q') {
       +              *t = '/';
       +              errlog(NOTICE,
       +                     "Message rejected: %b matches %b.\n", line, pattern);
       +              block = -1;
       +              break;
       +            }
       +            if (strlen(pattern->data + 1) + 1 < pattern->length
       +                && pattern->data[pattern->length - 1] == '/') {
       +              pattern->data[pattern->length - 1] = '\0';
       +              newstr = pattern->data + strlen(pattern->data) + 1;
       +              buf_reset(result);
       +              buf_append(result, line->data, ovector[0]);
       +              while (strchr(newstr, '$')) {
       +                strchr(newstr, '$')[0] = '\0';
       +                buf_appends(result, newstr);
       +                newstr += strlen(newstr) + 1;
       +                if (*newstr >= '1' && *newstr <= '9')
       +                  buf_append(result, line->data +
       +                             ovector[2 * (*newstr - '0')],
       +                             ovector[2 * (*newstr - '0') + 1] -
       +                             ovector[2 * (*newstr - '0')]);
       +                newstr++;
       +              }
       +              buf_appends(result, newstr);
       +              buf_appends(result, line->data + ovector[1]);
       +              buf_clear(line);
       +              buf_appends(line, result->data);
       +            } else {
       +              block = 1;
       +              *t = '/';
       +              if (logandreset)
       +                errlog(NOTICE, "Blocked header line: %b matches %b.\n",
       +                       line, pattern);
       +            }
       +          }
       +        } else {
       +          *t = '/';
       +          errlog(ERRORMSG, "Bad regexp %b\n", pattern);
       +        }
       +#else /* end of USE_PCRE */
       +        errlog(ERRORMSG, "No regexp support! Ignoring %b\n", pattern);
       +#endif /* else if not USE_PCRE */
       +      } else if (bufifind(line, pattern->data)) {
       +        if (logandreset )
       +          errlog(NOTICE, "Blocked header line: %b matches %b.\n",
       +                 line, pattern);
       +        block = 1;
       +      }
       +    }
       +
       +  if (logandreset && (block == 1))
       +    buf_reset(line);
       +
       +  buf_free(pattern);
       +  buf_free(result);
       +  return (block);
       +}
       +
       +int mix_armor(BUFFER *in)
       +{
       +  BUFFER *out, *md;
       +
       +  md = buf_new();
       +  out = buf_new();
       +
       +  if (in->length != 20480)
       +    return (-1);
       +
       +  buf_sets(out, "\n::\n");
       +  buf_appends(out, remailer_type);
       +  buf_appends(out, VERSION);
       +  buf_nl(out);
       +  buf_nl(out);
       +  buf_appends(out, begin_remailer);
       +  buf_nl(out);
       +  buf_appends(out, "20480\n");
       +  digest_md5(in, md);
       +  encode(md, 0);
       +  buf_cat(out, md);
       +  buf_nl(out);
       +  encode(in, 40);
       +  buf_cat(out, in);
       +  buf_appends(out, end_remailer);
       +  buf_nl(out);
       +
       +  buf_move(in, out);
       +  buf_free(out);
       +  buf_free(md);
       +  return (0);
       +}
   DIR diff --git a/Src/random.c b/Src/random.c
       t@@ -0,0 +1,210 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Randomness
       +   $Id: random.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include "crypto.h"
       +#include <fcntl.h>
       +#ifdef POSIX
       +#include <sys/time.h>
       +#include <unistd.h>
       +#else /* end of POSIX */
       +#include <io.h>
       +#include <process.h>
       +#endif /* else if not POSIX */
       +#ifdef WIN32
       +#include <windows.h>
       +#endif /* WIN32 */
       +#include <assert.h>
       +#include <string.h>
       +
       +int rnd_state = RND_NOTSEEDED;
       +
       +#ifdef USE_OPENSSL
       +int rnd_init(void)
       +{
       +  char r[PATHMAX];
       +  int n;
       +  LOCK *rndlock;
       +
       +  if (rnd_state == RND_SEEDED)
       +    return(0);
       +  rndlock = lockfile(MIXRAND);
       +  mixfile(r, MIXRAND);
       +  n = RAND_load_file(r, 1024);
       +  if (n < 256 && rnd_seed() == -1)
       +    goto err;
       +  rnd_time();
       +  RAND_write_file(r);
       +  rnd_state = RND_SEEDED;
       + err:
       +  unlockfile(rndlock);
       +  return (rnd_state == RND_SEEDED ? 0 : -1);
       +}
       +
       +int rnd_final(void)
       +{
       +  int err = 0;
       +  char r[PATHMAX];
       +  LOCK *rndlock;
       +
       +  if (rnd_state != RND_SEEDED)
       +    return(-1);
       +
       +  rnd_update(NULL, 0);
       +  rndlock = lockfile(MIXRAND);
       +  mixfile(r, MIXRAND);
       +  RAND_load_file(r, 1024);        /* add seed file again in case other instances
       +                                   of the program have used it */
       +  if (RAND_write_file(r) < 1)
       +    err = -1;
       +  unlockfile(rndlock);
       +  RAND_cleanup();
       +  return (err);
       +}
       +
       +int rnd_add(byte *b, int l)
       +{
       +  RAND_seed(b, l);
       +  return (0);
       +}
       +#endif /* USE_OPENSSL */
       +
       +void rnd_time(void)
       +{
       +  int pid;
       +
       +#ifdef WIN32
       +  SYSTEMTIME t;
       +#endif /* WIN32 */
       +
       +#ifdef HAVE_GETTIMEOFDAY
       +  struct timeval tv;
       +
       +  gettimeofday(&tv, 0);
       +  rnd_add((byte *) &tv, sizeof(tv));
       +#elif defined(WIN32) /* end of HAVE_GETTIMEOFDAY */
       +  GetSystemTime(&t);
       +  rnd_add((byte *) &t, sizeof(t));
       +#else /* end of defined(WIN32) */
       +  rnd_add((byte *) time(NULL), sizeof(time_t));
       +#endif /* else if not defined(WIN32), HAVE_GETTIMEOFDAY */
       +  pid = getpid();
       +  rnd_add((byte *) &pid, sizeof(pid));
       +}
       +
       +void rnd_update(byte *seed, int l)
       +{
       +  int fd = -1;
       +  byte b[512];
       +
       +  rnd_time();
       +  if (seed)
       +    rnd_add(seed, l);
       +#ifdef DEV_URANDOM
       +  fd = open(DEV_URANDOM, O_RDONLY);
       +  if (fd != -1) {
       +    ssize_t ret;
       +
       +    ret = read(fd, b, sizeof(b));
       +    if (ret > 0) {
       +      rnd_add(b, ret);
       +    }
       +    close(fd);
       +  }
       +#endif /* DEV_URANDOM */
       +}
       +
       +int rnd_bytes(byte *b, int n)
       +{
       +  /* we frequently need to get small amounts of random data.
       +     speed up by pre-generating dating data */
       +
       +  static byte rand[BUFSIZE];
       +  static int idx = BUFSIZE;
       +
       +  if (rnd_state != RND_SEEDED)
       +    rnd_error();
       +
       +  if (n + idx < BUFSIZE) {
       +    memcpy(b, rand + idx, n);
       +    idx += n;
       +  } else
       +    RAND_bytes(b, n);
       +
       +  if (idx + 256 > BUFSIZE) {
       +    RAND_bytes(rand, BUFSIZE);
       +    idx = 0;
       +  }
       +  return (0);
       +}
       +
       +int rnd_number(int n)
       +{
       +  int r;
       +
       +  assert(n > 0);
       +  if (n > 65535)
       +    do
       +      r = rnd_byte() * 65536 +
       +        rnd_byte() * 256 + rnd_byte();
       +    while (r >= n);
       +  else if (n > 255)
       +    do
       +      r = rnd_byte() * 256 + rnd_byte();
       +    while (r >= n);
       +  else
       +    do
       +      r = rnd_byte();
       +    while (r >= n);
       +  return r;
       +}
       +
       +byte rnd_byte()
       +{
       +  byte b;
       +
       +  rnd_bytes(&b, 1);
       +  return b;
       +}
       +
       +void rnd_initialized(void)
       +{
       +  rnd_state = RND_SEEDED;
       +}
       +
       +#ifdef WIN32
       +
       +#define NEEDED 256
       +
       +int rnd_mouse(UINT i, WPARAM w, LPARAM l)
       +{
       +  static int entropy = 0;
       +  static int x, y, dx, dy;
       +  int newx, newy, newdx, newdy;
       +  int rnd[4];
       +
       +  if (i == WM_MOUSEMOVE) {
       +    newx = LOWORD(l);
       +    newy = HIWORD(l);
       +    newdx = x - newx;
       +    newdy = y - newy;
       +    if (dx != 0 && dy != 0 && dx - newdx != 0 && dy - newdy != 0) {
       +      entropy++;
       +      if (entropy >= NEEDED)
       +        rnd_state = RND_SEEDED;
       +    }
       +    x = newx, y = newy, dx = newdx, dy = newdy;
       +    rnd[0] = x; rnd[1] = y; rnd[2] = dx; rnd[3] = dy;
       +    rnd_update((byte*)rnd, 4 * sizeof(int));
       +  }
       +  return (rnd_state == RND_SEEDED ? 100 : entropy * 100 / NEEDED);
       +}
       +#endif /* WIN32 */
   DIR diff --git a/Src/rem.c b/Src/rem.c
       t@@ -0,0 +1,709 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Process remailer messages
       +   $Id: rem.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include <stdlib.h>
       +#include <string.h>
       +#include <time.h>
       +#include <ctype.h>
       +#include <sys/types.h>
       +#include <sys/stat.h>
       +#ifdef POSIX
       +#include <unistd.h>
       +#else /* end of POSIX */
       +#include <io.h>
       +#endif /* else if not POSIX */
       +#ifndef _MSC
       +#include <dirent.h>
       +#endif /* not _MSC */
       +#include <assert.h>
       +
       +int blockrequest(BUFFER *message);
       +int create_dummy_mailin();
       +
       +#define REQUESTHELP  100
       +#define REQUESTSTATS 101
       +#define REQUESTKEY   200
       +#define REQUESTCONF  201
       +#define REQUESTOPKEY 202
       +#define REQUESTOTHER 203
       +#define BLOCKREQUEST 666
       +#define DISABLED      99
       +
       +#define CPUNKMSG 1
       +#define MIXMSG 2
       +
       +
       +/** \brief get replies for additional information requests
       + *
       + * \param reply The buffer to store the reply in
       + * \param file        The file or name of information a user requested
       + * \returns 0 on success; -1 if a ressource has a valid name
       + *     but doesn't exist; 1 if the ressource name isn't valid.
       + * 
       + * This function returns additional information that a
       + * user may have requested.  One obvious example is help files
       + * in different languages.  We don't want to hack the source every
       + * time we or somebody else adds a new language.
       + *
       + * Therefore we add a new directory where the operator may
       + * just create new files (say "remailer-help-de"). If a user
       + * requests that using this (file|ressource) name in the
       + * subject line we respond by sending it.
       + *
       + * Perhaps we should build something that returns an index of
       + * available files (FIXME if done).
       + *
       + * A ressource name needs to start with the string "remailer-"
       + * and must only consist of alphanumerical characters and dashes.
       + * Checking is done by this function and an error returned
       + * if this is violated.
       + */
       +int get_otherrequests_reply(BUFFER *reply, BUFFER *filename)
       +{
       +  FILE *f = NULL;
       +  int c;
       +  int err;
       +  BUFFER *path;
       +
       +  path = buf_new();
       +
       +  assert(filename);
       +  assert(reply);
       +
       +  buf_rewind(filename);
       +  err = bufileft(filename, "remailer-");
       +  if (! err) {
       +    err = 1;
       +    goto end;
       +  };
       +
       +  while ((c = buf_getc(filename)) != -1) {
       +    int ok = (c >= 'A' && c <= 'Z') ||
       +             (c >= 'a' && c <= 'z') ||
       +             (c >= '0' && c <= '9') ||
       +             c == '-';
       +    if (!ok) {
       +      err = 1;
       +      goto end;
       +    };
       +  };
       +  buf_rewind(filename);
       +
       +  buf_appends(path, REQUESTDIR);
       +  buf_appends(path, "/");
       +  buf_cat(path, filename);
       +
       +  f = mix_openfile(path->data, "r");
       +  if (f == NULL) {
       +    err = -1;
       +    goto end;
       +  };
       +
       +  buf_read(reply, f);
       +  err = 0;
       +end:
       +  if (f)
       +    fclose(f);
       +  buf_free(path);
       +  return (err);
       +}
       +
       +int mix_decrypt(BUFFER *message)
       +{
       +  int type = 0;
       +  BUFFER *field, *content;
       +  BUFFER *to, *subject, *replyto, *reply;
       +  BUFFER *otherrequest;
       +  FILE *f;
       +  BUFFER *block;
       +  int err = 0;
       +  int quoted_printable = 0;     /* is this message quoted printable encoded */
       +
       +  mix_init(NULL);
       +  field = buf_new();
       +  content = buf_new();
       +  to = buf_new();
       +  replyto = buf_new();
       +  reply = buf_new();
       +  block = buf_new();
       +  subject = buf_new();
       +  otherrequest = buf_new();
       +  buf_sets(subject, "Subject: Re: your mail");
       +
       +  buf_rewind(message);
       +
       +  f = mix_openfile(SOURCEBLOCK, "r");
       +  if (f != NULL) {
       +    buf_read(block, f);
       +    fclose(f);
       +  }
       +  for (;;) {
       +    err = buf_getheader(message, field, content);
       +    if (err == 1) {
       +      /* "::" marks for additional header lines */
       +      while (buf_lookahead(message, field) == 1)
       +        buf_getheader(message, field, content);
       +      if (isline(field, HDRMARK))
       +        continue;
       +      else
       +        goto hdrend;
       +    }
       +    if (err == -1)
       +      goto hdrend;
       +
       +    if ((bufieq(field, "from") || bufieq(field, "sender") || bufieq(field,"received")) &&
       +       doblock(content, block, 1) != 0)
       +      goto end;
       +
       +    if (bufieq(field, "to"))
       +      buf_cat(to, content);
       +    else if (bufieq(field, "from") && replyto->length == 0)
       +      /* reply to From address if no Reply-To header present */
       +      buf_set(replyto, content);
       +    else if (bufieq(field, "reply-to"))
       +      buf_set(replyto, content);
       +    else if (MIX && bufieq(field, "remailer-type") &&
       +             bufileft(content, "mixmaster"))
       +      type = MIXMSG;
       +    else if (bufieq(field, "subject")) {
       +      if (bufieq(content, "help") || bufieq(content, "remailer-help"))
       +        type = REQUESTHELP;
       +      else if (bufieq(content, "remailer-stats"))
       +        type = REQUESTSTATS;
       +      else if (bufieq(content, "remailer-key"))
       +        type = REQUESTKEY;
       +      else if (bufieq(content, "remailer-adminkey"))
       +        type = REQUESTOPKEY;
       +      else if (bufieq(content, "remailer-conf"))
       +        type = REQUESTCONF;
       +      else if (bufileft(content, "remailer-")) {
       +        type = REQUESTOTHER;
       +        buf_set(otherrequest, content);
       +      } else if (bufileft(content, "destination-block"))
       +        type = BLOCKREQUEST;
       +      else {
       +        buf_sets(subject, "Subject: ");
       +        if (!bufileft(content, "re:"))
       +          buf_appends(subject, "Re: ");
       +        buf_cat(subject, content);
       +      }
       +    } else if (bufieq(field, "test-to") || bufieq(field, "encrypted") ||
       +               bufieq(field, "anon-to") ||
       +               bufieq(field, "request-remailing-to") ||
       +               bufieq(field, "remail-to") || bufieq(field, "anon-post-to") ||
       +               bufieq(field, "post-to") || bufieq(field, "anon-send-to") ||
       +               bufieq(field, "send-to") || bufieq(field, "remix-to") ||
       +               bufieq(field, "encrypt-to"))
       +      type = CPUNKMSG;
       +    else if (bufieq(field, "content-transfer-encoding")
       +             && bufieq(content, "quoted-printable")) {
       +      quoted_printable = 1;
       +    }
       +
       +  }
       +hdrend:
       +  if (quoted_printable)
       +    qp_decode_message(message);
       +
       +  if (type > 0 && REMAIL == 0)
       +    type = DISABLED;
       +  switch (type) {
       +  case REQUESTHELP:
       +    if (sendinfofile(HELPFILE, NULL, replyto, NULL) == -1)
       +      errlog(WARNING, "No help file available.\n");
       +    break;
       +  case REQUESTKEY:
       +    err = key(reply);
       +    if (err == 0)
       +      err = sendmail(reply, REMAILERNAME, replyto);
       +    break;
       +  case REQUESTOPKEY:
       +    err = adminkey(reply);
       +    if (err == 0)
       +      err = sendmail(reply, REMAILERNAME, replyto);
       +    break;
       +  case REQUESTSTATS:
       +    err = stats(reply);
       +    if (err == 0)
       +      err = sendmail(reply, REMAILERNAME, replyto);
       +    break;
       +  case REQUESTCONF:
       +    err = conf(reply);
       +    if (err == 0)
       +      err = sendmail(reply, REMAILERNAME, replyto);
       +    break;
       +  case REQUESTOTHER:
       +    err = get_otherrequests_reply(reply, otherrequest);
       +    if (err == 0)
       +      err = sendmail(reply, REMAILERNAME, replyto);
       +    break;
       +  case CPUNKMSG:
       +    err = t1_decrypt(message);
       +    if (err != 0) {
       +      errlog(LOG, "Invalid type 1 message from %b\n", replyto);
       +      sendinfofile(USAGEFILE, USAGELOG, replyto, NULL);
       +      logmail(err == -2 ? MAILUSAGE : MAILERROR, message);
       +    } else
       +      create_dummy_mailin();
       +    break;
       +  case MIXMSG:
       +    err = t2_decrypt(message);
       +    if (err == -1) {
       +      errlog(LOG, "Invalid type 2 message from %b\n", replyto);
       +      sendinfofile(USAGEFILE, USAGELOG, replyto, NULL);
       +      logmail(MAILERROR, message);
       +    } else
       +      create_dummy_mailin();
       +    break;
       +  case BLOCKREQUEST:
       +    blockrequest(message);
       +    /* Already wrote a log entry in blockrequest() */
       +    logmail(MAILBLOCK, message);
       +    break;
       +  case DISABLED:
       +    errlog(ERRORMSG, "Remailer is disabled.\n");
       +    buf_sets(reply, "Subject: remailer error\n\nThe remailer is disabled.\n");
       +    sendmail(reply, REMAILERNAME, replyto);
       +    logmail(MAILERROR, message);
       +    break;
       +  default:
       +    if (strifind
       +        (replyto->data, "mailer-daemon")) {
       +      errlog(LOG, "Bounce mail from %b\n", replyto);
       +      logmail(MAILBOUNCE, message);
       +    } else if (bufifind(to, REMAILERADDR) && blockrequest(message)) {
       +      /* Already wrote a log entry in blockrequest() */
       +      logmail(MAILBLOCK, message);
       +    } else if (bufifind(to, REMAILERADDR)) {
       +      errlog(LOG, "Non-remailer message from %b\n", replyto);
       +      if (AUTOREPLY)
       +        sendinfofile(USAGEFILE, USAGELOG, replyto, NULL);
       +      logmail(MAILUSAGE, message);
       +    } else if (bufifind(to, COMPLAINTS)) {
       +      errlog(WARNING, "Abuse complaint from %b\n", replyto);
       +      if (AUTOREPLY)
       +        sendinfofile(ABUSEFILE, NULL, replyto, subject);
       +      logmail(MAILABUSE, message);
       +    } else if (ANONADDR[0] && bufifind(to, ANONADDR)) {
       +      errlog(LOG, "Reply to anonymous message from %b\n", replyto);
       +      if (AUTOREPLY)
       +        sendinfofile(REPLYFILE, NULL, replyto, subject);
       +      logmail(MAILANON, message);
       +    } else {
       +      errlog(DEBUGINFO, "Mail from %b\n", replyto);
       +      logmail(MAILBOX, message);
       +    }
       +    err = 1;
       +  }
       +end:
       +  buf_free(field);
       +  buf_free(content);
       +  buf_free(to);
       +  buf_free(replyto);
       +  buf_free(reply);
       +  buf_free(block);
       +  buf_free(subject);
       +  buf_free(otherrequest);
       +  return (err);
       +}
       +
       +int create_dummy_mailin()
       +{
       +  while (rnd_number(100) < INDUMMYP) {
       +    errlog(DEBUGINFO, "Generating dummy message with incoming mail.\n");
       +    if (mix_encrypt(MSG_NULL, NULL, NULL, 1, NULL) == -1)
       +      return -1;
       +  }
       +  return 0;
       +}
       +
       +int t2_decrypt(BUFFER *in)
       +{
       +  int err = 0;
       +  BUFFER *msg;
       +
       +  msg = buf_new();
       +  do {
       +    err = mix_dearmor(in, msg);
       +    if (err != -1) {
       +      err = mix2_decrypt(msg);
       +    }
       +  }
       +  while (in->ptr + 1000 < in->length);        /* accept several packets in one message */
       +
       +  buf_free(msg);
       +  return (err);
       +}
       +
       +int mix_pool(BUFFER *msg, int type, long latent)
       +{
       +  char path[PATHMAX], pathtmp[PATHMAX];
       +  FILE *f;
       +  int err = -1;
       +
       +  f = pool_new(latent > 0 ? "lat" : "msg", pathtmp, path);
       +  if (f != NULL) {
       +    if (latent > 0)
       +      fprintf(f, "%d %ld\n", type, latent + time(NULL));
       +    else
       +      fprintf(f, "%d 0\n", type);
       +    err = buf_write_sync(msg, f);
       +  }
       +  if (err == 0) {
       +    rename(pathtmp, path);
       +    errlog(DEBUGINFO, "Added message to pool.\n");
       +  }
       +  return (err);
       +}
       +
       +int pool_packetfile(char *fname, BUFFER *mid, int packetnum)
       +     /* create a filename */
       +{
       +#ifdef SHORTNAMES
       +  sprintf(fname, "%s%cp%02x%02x%02x%01x.%02x", POOLDIR, DIRSEP,
       +          mid->data[0], mid->data[1], mid->data[2], mid->data[3] & 15,
       +          packetnum);
       +#else /* end of SHORTNAMES */
       +  sprintf(fname, "%s%cp%02x%02x%02x%02x%02x%02x%01x", POOLDIR, DIRSEP,
       +          packetnum, mid->data[0], mid->data[1], mid->data[2], mid->data[3],
       +          mid->data[4], mid->data[5] & 15);
       +#endif /* else if not SHORTNAMES */
       +  return (0);
       +}
       +
       +void pool_packetexp(void)
       +{
       +  char *path;
       +  DIR *d;
       +  struct dirent *e;
       +  struct stat sb;
       +
       +  d = opendir(POOLDIR);
       +  errlog(DEBUGINFO, "Checking for old parts.\n");
       +  if (d != NULL)
       +    for (;;) {
       +      e = readdir(d);
       +      if (e == NULL)
       +        break;
       +      if (e->d_name[0] == 'p' || e->d_name[0] == 'e' || e->d_name[0] == 't') {
       +        path=malloc(strlen(POOLDIR)+strlen(e->d_name)+strlen(DIRSEPSTR)+1);
       +        if (path) {
       +         strcpy(path, POOLDIR);
       +          strcat(path, DIRSEPSTR);
       +          strcat(path, e->d_name);
       +          if (stat(path, &sb) == 0 && time(NULL) - sb.st_mtime > PACKETEXP) {
       +             if (e->d_name[0] == 'p') {
       +                errlog(NOTICE, "Expiring incomplete partial message %s.\n",
       +                e->d_name);
       +             }
       +             else if (e->d_name[0] == 'e') {
       +                errlog(NOTICE, "Expiring old error message %s.\n",
       +                e->d_name);
       +             }
       +             else if (e->d_name[0] == 't') {
       +                errlog(NOTICE, "Expiring moldy temporary message %s.\n",
       +                e->d_name);
       +             }
       +             unlink(path);
       +          }
       +        free(path);
       +        }
       +      }
       +    }
       +  closedir(d);
       +}
       +
       +void logmail(char *mailbox, BUFFER *message)
       +{
       +  time_t t;
       +  struct tm *tc;
       +  char line[LINELEN];
       +
       +  /* mailbox is "|program", "user@host", "stdout", "Maildir/" or "filename" */
       +  buf_rewind(message);
       +  if (mailbox[0] == '\0')        /* default action */
       +    mailbox = MAILBOX;
       +  if (strieq(mailbox, "stdout"))
       +    buf_write(message, stdout);
       +  else if (mailbox[0] == '|') {
       +    FILE *p;
       +
       +    errlog(DEBUGINFO, "Piping message to %s.\n", mailbox + 1);
       +    p = openpipe(mailbox + 1);
       +    if (p != NULL) {
       +      buf_write(message, p);
       +      closepipe(p);
       +    }
       +  } else if (strchr(mailbox, '@')) {
       +    BUFFER *field, *content;
       +
       +    field = buf_new();
       +    content = buf_new();
       +    while (buf_getheader(message, field, content) == 0)
       +      if (bufieq(field, "x-loop") && bufifind(content, REMAILERADDR)) {
       +        errlog(WARNING, "Loop detected! Message not sent to %s.\n", mailbox);
       +        goto isloop;
       +      }
       +    buf_sets(content, mailbox);
       +    sendmail_loop(message, NULL, content);
       +  isloop:
       +    buf_free(field);
       +    buf_free(content);
       +  } else if (mailbox[strlen(mailbox)-1] == DIRSEP) {
       +    /* the user is requesting Maildir delivery */
       +    if(maildirWrite(mailbox, message, 1) != 0) {
       +      errlog(ERRORMSG, "Can't write to maildir %s\n", mailbox);
       +      return;
       +    }
       +  } else {
       +    FILE *mbox;
       +
       +    mbox = mix_openfile(mailbox, "a");
       +    if (mbox == NULL) {
       +      errlog(ERRORMSG, "Can't write to mail folder %s\n", mailbox);
       +      return;
       +    }
       +    lock(mbox);
       +    if (!bufileft(message, "From ")) {
       +      t = time(NULL);
       +      tc = localtime(&t);
       +      strftime(line, LINELEN, "From Mixmaster %a %b %d %H:%M:%S %Y\n", tc);
       +      fprintf(mbox, line);
       +    }
       +    buf_write(message, mbox);
       +    fprintf(mbox, "\n\n");
       +    unlock(mbox);
       +    fclose(mbox);
       +  }
       +}
       +
       +int blockrequest(BUFFER *message)
       +{
       +  int request = 0, num, i;
       +  BUFFER *from, *line, *field, *content, *addr, *remailer_addr, *copy_addr;
       +  REMAILER remailer[MAXREM];
       +  FILE *f;
       +  char *destblklst = (char *)malloc( strlen(DESTBLOCK)+1 );
       +  char *destblk;
       +
       +  from = buf_new();
       +  line = buf_new();
       +  field = buf_new();
       +  content = buf_new();
       +  addr = buf_new();
       +  remailer_addr = buf_new();
       +  copy_addr = buf_new();
       +
       +  if (destblklst == NULL) {
       +    errlog(ERRORMSG, "Can't malloc %n bytes for destblklst.\n", strlen(DESTBLOCK)+1);
       +    goto end;
       +  };
       +
       +  buf_rewind(message);
       +  while (buf_getheader(message, field, content) == 0)
       +    if (bufieq(field, "from"))
       +      buf_set(from, content);
       +    else if (bufieq(field, "subject"))
       +      buf_cat(message, content);
       +   /* Append the subject to the message body so destination block requests
       +      in the subject line work too (we process the body a few lines down) */
       +  while (buf_getline(message, line) != -1)
       +    if (bufifind(line, "destination-block")) {
       +      buf_clear(addr);
       +      request = 1;
       +      {
       +        int c = 0;
       +
       +        while (!strileft(line->data + line->ptr, "block"))
       +          line->ptr++;
       +        while (c != ' ' && c != -1)
       +          c = tolower(buf_getc(line));
       +        while (c == ' ')
       +          c = buf_getc(line);
       +        if (c != -1)
       +          do {
       +            buf_appendc(addr, c);
       +            c = buf_getc(line);
       +          } while (c > ' ');
       +      }
       +      if (addr->length == 0) {
       +        rfc822_addr (from, addr);
       +        buf_chop(addr);
       +      }
       +      /* Check whether somebody wants us to block ourselves */
       +      buf_set(copy_addr, addr);
       +      buf_sets(remailer_addr, REMAILERADDR);
       +      if (doblock(remailer_addr, copy_addr, 1)) {
       +        errlog(LOG, "Ignoring blocking request for %b from %b.\n", addr, from);
       +        request = 2;
       +        goto end;
       +      }
       +      /* Check if some evil person tries to block a known type II remailer */
       +      num = mix2_rlist(remailer, NULL);
       +      for (i = 0; i < num; i++) {
       +        buf_sets(remailer_addr, remailer[i].addr);
       +        if (doblock(remailer_addr, copy_addr, 1)) {
       +          errlog(LOG, "Ignoring blocking request for %b from %b.\n", addr, from);
       +          request = 2;
       +          goto end;
       +        }
       +      }
       +      /* Check if some evil person tries to block a known type I remailer */
       +      num = t1_rlist(remailer, NULL);
       +      for (i = 0; i < num; i++) {
       +        buf_sets(remailer_addr, remailer[i].addr);
       +        if (doblock(remailer_addr, copy_addr, 1)) {
       +          errlog(LOG, "Ignoring blocking request for %b from %b.\n", addr, from);
       +          request = 2;
       +          goto end;
       +        }
       +      }
       +
       +      if (buf_ieq(addr, from))
       +        errlog(NOTICE, "Blocking request for %b\n", addr);
       +      else
       +        errlog(NOTICE, "Blocking request for %b from %b\n", addr, from);
       +      if (AUTOBLOCK) {
       +        buf_clear(line);
       +        rfc822_addr(addr, line);
       +        if (line->length == 0) {
       +          errlog(LOG, "Nothing to block after rfc822_addr().\n");
       +        } else
       +          if (bufleft(line, "/")) {
       +            errlog(LOG, "Ignoring blocking request: %b is a regex.\n", addr);
       +          } else {
       +            if (strchr(line->data, '@') && strchr(strchr(line->data, '@'), '.')) {
       +              strcpy( destblklst, DESTBLOCK );
       +              destblk = strtok( destblklst, " " );
       +              f = mix_openfile( destblk, "a" );
       +              if (f != NULL) {
       +                lock(f);
       +
       +                buf_chop(line);
       +                sendinfofile(BLOCKFILE, NULL, line, NULL);
       +                if (line->length) {
       +                  fprintf(f, "%s\n", line->data);
       +                } else
       +                  errlog(NOTICE, "%b already blocked.\n", addr);
       +                unlock(f);
       +                fclose(f);
       +              } else
       +                errlog(ERRORMSG, "Can't write to %s.\n", DESTBLOCK);
       +            } else
       +              errlog(WARNING, "Invalid address not added to %s: %b\n", DESTBLOCK,
       +                     addr);
       +          }
       +      }
       +    }
       +
       +end:
       +  free( destblklst );
       +  buf_free(from);
       +  buf_free(line);
       +  buf_free(field);
       +  buf_free(content);
       +  buf_free(addr);
       +  buf_free(remailer_addr);
       +  buf_free(copy_addr);
       +
       +  return (request);
       +}
       +
       +
       +int idexp(void)
       +{
       +  FILE *f;
       +  long now, then;
       +  LOCK *i;
       +  idlog_t idbuf;
       +  long fpi = sizeof(idlog_t), fpo = sizeof(idlog_t);
       +
       +  if (IDEXP == 0)
       +    return (0);
       +
       +  f = mix_openfile(IDLOG, "rb+");
       +  if (f == NULL)
       +    return (-1);
       +  i = lockfile(IDLOG);
       +  now = time(NULL);
       +  if (fread(&idbuf, 1, sizeof(idlog_t), f) != sizeof(idlog_t)) { /* replace first line */
       +    fclose(f);
       +    unlockfile(i);
       +    return (-1);
       +  }
       +  then = idbuf.time;
       +  memset(idbuf.id,0,sizeof(idbuf.id));
       +  idbuf.time = now - IDEXP;
       +  fseek(f,0,SEEK_SET);
       +  fwrite(&idbuf,1,sizeof(idlog_t),f);
       +  fseek(f,fpi,SEEK_SET); /* this fseek does nothing, but MSVC CRT happilly reads past EOF (!!!) if we do not fseek here :-/ */
       +  while (fread(&idbuf, 1, sizeof(idlog_t), f) == sizeof(idlog_t)) {
       +    fpi+=sizeof(idlog_t);
       +    then = idbuf.time;
       +    if (now - then < IDEXP &&
       +      now - then > - SECONDSPERDAY * 180 )
       +      /* also expire packets that are dated more than half a year in the future.
       +       * That way we get rid of invalid packets introduced by the switch to a
       +       * binary id.log. */
       +    {
       +      fseek(f,fpo,SEEK_SET);
       +      fwrite(&idbuf,1,sizeof(idlog_t),f);
       +      fpo += sizeof(idlog_t);
       +      fseek(f,fpi,SEEK_SET);
       +    }
       +  }
       +#ifdef _MSC
       +    chsize(fileno(f),fpo);
       +#else /* end of _MSC */
       +    ftruncate(fileno(f),fpo);
       +#endif /* else if not _MSC */
       +  fclose(f);
       +  unlockfile(i);
       +  return (0);
       +}
       +
       +
       +int pgpmaxexp(void)
       +{
       +  FILE *f;
       +  BUFFER *b;
       +  long now, then;
       +  LOCK *i;
       +  char temp[LINELEN];
       +
       +  f = mix_openfile(PGPMAXCOUNT, "rb+");
       +  if (f == NULL)
       +    return (-1);
       +  i = lockfile(PGPMAXCOUNT);
       +  b = buf_new();
       +  now = time(NULL);
       +
       +  while (fgets(temp, sizeof(temp), f) != NULL)
       +    if (sscanf(temp, "%ld", &then) &&
       +        then >= now - SECONDSPERDAY)
       +      buf_appends(b, temp);
       +
       +  fseek(f,0,SEEK_SET);
       +
       +  buf_write(b, f);
       +
       +#ifdef _MSC
       +    chsize(fileno(f),b->length);
       +#else /* end of _MSC */
       +    ftruncate(fileno(f),b->length);
       +#endif /* else if not _MSC */
       +
       +  fclose(f);
       +  unlockfile(i);
       +  buf_free(b);
       +  return (0);
       +}
   DIR diff --git a/Src/rem1.c b/Src/rem1.c
       t@@ -0,0 +1,599 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Process Cypherpunk remailer messages
       +   $Id: rem1.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include <ctype.h>
       +#include <time.h>
       +#include <string.h>
       +#include <assert.h>
       +#include <stdlib.h>
       +
       +static int t1msg(BUFFER *in, int hdr);
       +
       +int isline(BUFFER *line, char *text)
       +{
       +  int i;
       +
       +  if (!bufileft(line, text))
       +    return (0);
       +
       +    for (i = strlen(text); i < line->length; i++)
       +      if (!isspace(line->data[i]))
       +        return(0);
       +    return(1);
       +}
       +
       +int t1_decrypt(BUFFER *in)
       +{
       +  int ret;
       +
       +  buf_rewind(in);
       +  if (TYPE1[0] == '\0')
       +    ret = t1msg(in, 1);
       +  else {
       +    FILE *f;
       +
       +    f = openpipe(TYPE1);
       +    if (f == NULL)
       +      return -1;
       +    buf_write(in, f);
       +    ret = closepipe(f);
       +  }
       +  if (ret == 0)
       +    stats_log(1);
       +  return (ret);
       +}
       +
       +#ifdef USE_IDEA
       +void t1_esub(BUFFER *esub, BUFFER *subject)
       +{
       +  BUFFER *iv, *out;
       +  char hex[33];
       +
       +  iv = buf_new();
       +  out = buf_new();
       +
       +  buf_appendrnd(iv, 8);
       +  id_encode(iv->data, hex);
       +  buf_append(out, hex, 16);
       +
       +  digest_md5(esub, esub);
       +  digest_md5(subject, subject);
       +  buf_ideacrypt(subject, esub, iv, ENCRYPT);
       +  id_encode(subject->data, hex);
       +  buf_appends(out, hex);
       +  buf_move(subject, out);
       +  buf_free(iv);
       +  buf_free(out);
       +}
       +#endif /* USE_IDEA */
       +
       +#define N(X) (isdigit(X) ? (X)-'0' : 0)
       +
       +static int readnum(BUFFER *b, int f)
       +{
       +  int num = 0;
       +
       +  if (b->length > 0)
       +    sscanf(b->data, "%d", &num);
       +  num *= f;
       +  if (strchr(b->data, 'r'))
       +    num = rnd_number(num) + 1;
       +  return (num);
       +}
       +
       +static int readdate(BUFFER *b)
       +{
       +  int num = -1;
       +
       +  if (b->length > 0)
       +    num = parsedate(b->data);
       +  return (num);
       +}
       +
       +static int reached_maxcount(BUFFER *md, int maxcount)
       +{
       +  FILE *f;
       +  char temp[LINELEN];
       +  int count = 0;
       +  int err = 0;
       +  long then;
       +  time_t now = time(NULL);
       +
       +  assert(md->length > 0);
       +
       +  encode(md, 0);
       +
       +  f = mix_openfile(PGPMAXCOUNT, "a+"); /* create file if it does not exist */
       +  fseek(f,0,SEEK_SET);
       +  if (f == NULL) {
       +    errlog(ERRORMSG, "Can't open %s!\n", PGPMAXCOUNT);
       +    return (-1);
       +  }
       +  lock(f);
       +  while (fgets(temp, sizeof(temp), f) != NULL)
       +    if (sscanf(temp, "%ld", &then) &&
       +        (then >= now - SECONDSPERDAY) &&
       +        strstr (temp, md->data))
       +      count++;
       +
       +  if (count > maxcount)
       +    err = 1;
       +  else
       +    fprintf(f, "%ld %s\n", (long) time(NULL), md->data);
       +
       +  unlock(f);
       +  fclose(f);
       +  return (err);
       +}
       +
       +static int t1msg(BUFFER *in, int hdr)
       +     /* hdr = 1: mail header, hdr = 2: pasted header, hdr = 0: ignore */
       +{
       +  BUFFER *field, *content, *line;
       +  BUFFER *cutmarks, *to, *newsgroups, *ek, *ekdes, *ekcast, *esub, *subject;
       +  BUFFER *temp, *header, *out;
       +  BUFFER *test, *testto, *remixto;
       +  BUFFER *digest;
       +  int err = 0;
       +  int encrypted = 0;
       +  int type = -1;
       +  int latent = 0;
       +  int remix = 0, repgp = 0;
       +  int inflate = 0;
       +  int maxsize = -1;
       +  int maxcount = -1;
       +  int maxdate = -2; /* -2 not used, -1 parse error */
       +
       +  field = buf_new();
       +  content = buf_new();
       +  line = buf_new();
       +  to = buf_new();
       +  remixto = buf_new();
       +  cutmarks = buf_new();
       +  newsgroups = buf_new();
       +  ek = buf_new();
       +  ekdes = buf_new();
       +  ekcast = buf_new();
       +  esub = buf_new();
       +  subject = buf_new();
       +  temp = buf_new();
       +  header = buf_new();
       +  out = buf_new();
       +  test = buf_new();
       +  testto = buf_new();
       +  digest = buf_new();
       +
       +  if (REMIX == 1)
       +    remix = 2;
       +  if (!UNENCRYPTED)
       +    encrypted = -1;
       +
       +header:
       +  while (buf_getheader(in, field, content) == 0) {
       +    if (header->length == 0 && bufieq(content, ":"))        /* HDRMARK */
       +      hdr = 2;
       +
       +    if (bufieq(field, "test-to"))
       +      buf_set(testto, content);
       +    else if (PGP && bufieq(field, "encrypted"))
       +      encrypted = 1;
       +    else if (bufieq(field, "remix-to")) {
       +      remix = 1; repgp = 0;
       +      buf_set(remixto, content);
       +      if (type == -1)
       +        type = MSG_MAIL;
       +    } else if (bufieq(field, "encrypt-to")) {
       +      repgp = remix = 1;
       +      buf_set(remixto, content);
       +      if (type == -1)
       +        type = MSG_MAIL;
       +    } else if (bufieq(field, "anon-to") ||
       +               bufieq(field, "request-remailing-to") ||
       +               bufieq(field, "remail-to") ||
       +               bufieq(field, "anon-send-to")) {
       +      if (bufieq(field, "remail-to"))
       +        repgp = remix = 0;
       +      if (to->length > 0)
       +        buf_appendc(to, ',');
       +      buf_cat(to, content);
       +      if (type == -1)
       +        type = MSG_MAIL;
       +    } else if (bufieq(field, "anon-post-to") || bufieq(field, "post-to")) {
       +      if (newsgroups->length > 0)
       +        buf_appendc(newsgroups, ',');
       +      buf_cat(newsgroups, content);
       +      type = MSG_POST;
       +    } else if (bufieq(field, "cutmarks"))
       +      buf_set(cutmarks, content);
       +    else if (bufieq(field, "latent-time")) {
       +      byte *q;
       +      int l;
       +
       +      q = content->data;
       +      l = strlen(q);
       +      latent = 0;
       +      if (q[0] == '+')
       +        q++;
       +      if (l >= 5 && q[2] == ':')
       +        latent = 600 * N(q[0]) + 60 * N(q[1]) + 10 * N(q[3]) + N(q[4]);
       +      else if (l >= 4 && q[1] == ':')
       +        latent = 60 * N(q[0]) + 10 * N(q[2]) + N(q[3]);
       +      else if (l >= 3 && q[0] == ':')
       +        latent = 10 * N(q[1]) + N(q[2]);
       +      if (!bufleft(content, "+")) {
       +        time_t now;
       +
       +        time(&now);
       +        latent -= localtime(&now)->tm_hour * 60;
       +        if (latent < 0)
       +          latent += 24 * 60;
       +      }
       +      if (q[l - 1] == 'r')
       +        latent = rnd_number(latent);
       +    } else if (bufieq(field, "null"))
       +      type = MSG_NULL;
       +#ifdef USE_IDEA
       +    else if (bufieq(field, "encrypt-key") || bufieq(field, "encrypt-idea"))
       +      buf_set(ek, content);
       +#else
       +    else if (bufieq(field, "encrypt-key") || bufieq(field, "encrypt-idea"))
       +      buf_set(ekdes, content);
       +#endif
       +    else if (bufieq(field, "encrypt-des") || bufieq(field, "encrypt-3des"))
       +      buf_set(ekdes, content);
       +    else if (bufieq(field, "encrypt-cast") || bufieq(field, "encrypt-cast5"))
       +      buf_set(ekcast, content);
       +    else if (bufieq(field, "encrypt-subject"))
       +      buf_set(esub, content);
       +    else if (bufieq(field, "inflate")) {
       +      inflate = readnum(content, 1024);
       +      if (inflate > INFLATEMAX * 1024)
       +        inflate = INFLATEMAX * 1024;
       +    } else if (bufieq(field, "rand-hop")) {
       +      int randhops, i;
       +      randhops = readnum(content, 1);
       +      if (randhops > MAXRANDHOPS)
       +        randhops = MAXRANDHOPS;
       +      buf_clear(temp);
       +      if (remixto->length)
       +         buf_move(temp, remixto);
       +      for (i = 0; i < randhops; i++) {
       +        if (remixto->length > 0)
       +          buf_appendc(remixto, ',');
       +        buf_appendc(remixto, '*');
       +      }
       +      if (temp->length) {
       +        buf_appendc(remixto, ',');
       +        buf_cat(remixto, temp);
       +      }
       +    } else if (bufieq(field, "max-size") || bufieq(field, "maxsize"))
       +      maxsize = readnum(content, 1024);
       +    else if (bufieq(field, "max-count") || bufieq(field, "maxcount"))
       +      maxcount = readnum(content, 1);
       +    else if (bufieq(field, "max-date") || bufieq(field, "maxdate"))
       +      maxdate = readdate(content);
       +#if USE_NSUB
       +    else if (bufieq(field, "subject"))
       +      buf_set(subject, content);
       +#endif /* USE_NSUB */
       +  }
       +
       +  if (cutmarks->length > 0) {
       +    BUFFER *cut;
       +
       +    cut = buf_new();
       +    buf_clear(temp);
       +
       +    while ((err = buf_getline(in, line)) != -1 && !buf_eq(line, cutmarks)) {
       +      buf_cat(temp, line);
       +      buf_nl(temp);
       +    }
       +    while (err != -1) {
       +      err = buf_getline(in, line);
       +      if (err == -1 || buf_eq(line, cutmarks)) {
       +        t1msg(cut, 0);
       +        buf_clear(cut);
       +      } else {
       +        buf_cat(cut, line);
       +        buf_nl(cut);
       +      }
       +    }
       +    buf_move(in, temp);
       +    buf_clear(cutmarks);
       +  }
       +  if (encrypted == 1) {
       +#ifdef USE_PGP
       +    err = pgp_dearmor(in, temp);
       +    if (err == 0) {
       +      BUFFER *pass;
       +      digest_sha1(temp, digest);
       +
       +      pass = buf_new();
       +      buf_sets(pass, PASSPHRASE);
       +      err = pgp_decrypt(temp, pass, NULL, NULL, NULL);
       +      buf_free(pass);
       +    }
       +    if (err != -1 && temp->length == 0) {
       +      errlog(ERRORMSG, "Empty PGP message.\n");
       +      err = -1;
       +      goto end;
       +    }
       +    if (err != -1) {
       +      buf_rest(temp, in);        /* dangerous, but required for reply blocks */
       +      buf_move(in, temp);
       +      encrypted = 0;
       +      hdr = 0;
       +      goto header;
       +    }
       +#endif /* USE_PGP */
       +    if (testto->length == 0)
       +      errlog(ERRORMSG, "Can't decrypt PGP message.\n");
       +    buf_appends(test, "Can't decrypt PGP message.\n");
       +  }
       +  while ((err = buf_lookahead(in, line)) == 1)
       +    buf_getline(in, line);
       +#if 0
       +  if (err == -1)
       +    goto end;
       +#endif /* 0 */
       +
       +  if (isline(line, HDRMARK) && (hdr == 0 || hdr == 1)) {
       +    buf_getline(in, NULL);
       +    hdr = 2;
       +    goto header;
       +  } else if (isline(line, HASHMARK)) {
       +    buf_getline(in, NULL);
       +    for (;;) {
       +      if (buf_lookahead(in, line) == 0 && bufileft(line, "subject:")) {
       +        buf_getheader(in, field, content);
       +        buf_set(subject, content);
       +      }
       +      if (buf_getline(in, line) != 0)
       +        break;
       +      buf_cat(header, line);
       +      buf_nl(header);
       +    }
       +  }
       +  if (encrypted == -1) {
       +    if (testto->length == 0)
       +      errlog(LOG, "Unencrypted message detected.\n");
       +    buf_appends(test, "Unencrypted message detected.\n");
       +    err = -2;
       +    goto end;
       +  }
       +  if (maxdate == -1) {
       +    if (testto->length == 0)
       +      errlog(LOG, "Could not parse Max-Date: header.\n");
       +    buf_appends(test, "Could not parse Max-Date: header.\n");
       +    err = -2;
       +    goto end;
       +  } else if (maxdate >= 0 && maxdate <= time(NULL)) {
       +    if (testto->length == 0)
       +      errlog(LOG, "Message is expired.\n");
       +    buf_appends(test, "Message is expired.\n");
       +    err = -2;
       +    goto end;
       +  }
       +  if (maxsize >= 0 && in->length >= maxsize) {
       +    if (testto->length == 0)
       +      errlog(LOG, "Message Size exceeds Max-Size.\n");
       +    buf_appends(test, "Message Size exceeds Max-Size.\n");
       +    err = -2;
       +    goto end;
       +  }
       +  if (maxcount >= 0) {
       +    if (digest->length == 0) {
       +      if (testto->length == 0)
       +        errlog(LOG, "Max-Count yet not encrypted.\n");
       +      buf_appends(test, "Max-Count yet not encrypted.\n");
       +      err = -2;
       +      goto end;
       +    }
       +    if (reached_maxcount(digest, maxcount)) {
       +      if (testto->length == 0)
       +        errlog(LOG, "Max-Count reached - discarding message.\n");
       +      buf_appends(test, "Max-Count reached - discarding message.\n");
       +      err = -2;
       +      goto end;
       +    }
       +  }
       +
       +  if (type == MSG_POST && subject->length == 0)
       +    buf_sets(subject, "(no subject)");
       +
       +  if (to->length > 0)
       +    buf_appendf(out, "To: %b\n", to);
       +  else if (remixto->length > 0)
       +    buf_appendf(out, "To: %b\n", remixto);
       +  if (newsgroups->length > 0)
       +    buf_appendf(out, "Newsgroups: %b\n", newsgroups);
       +  if (subject->length > 0) {
       +#ifdef USE_IDEA
       +    if (esub->length > 0)
       +      t1_esub(esub, subject);
       +#endif /* USE_IDEA */
       +    buf_appendf(out, "Subject: %b\n", subject);
       +  }
       +  buf_cat(out, header);
       +  buf_nl(out);
       +
       +#if 0
       +  inflate -= in->length;
       +#endif /* 0 */
       +  if (inflate > 0) {
       +    buf_setrnd(temp, inflate * 3 / 4);
       +    encode(temp, 64);
       +    buf_appends(in, "\n-----BEGIN GARBAGE-----\n");
       +    buf_cat(in, temp);
       +    buf_appends(in, "-----END GARBAGE-----\n");
       +  }
       +
       +  if (!(ek->length || ekdes->length || ekcast->length))
       +    buf_rest(out, in);
       +  else {
       +    err = 0;
       +    buf_clear(temp);
       +    while (buf_getline(in, line) != -1) {
       +      if (isline(line, EKMARK)) {
       +        buf_cat(out, temp);
       +        buf_clear(temp);
       +        buf_rest(temp, in);
       +        break;
       +      }
       +      else {
       +        buf_cat(temp, line);
       +        buf_nl(temp);
       +      }
       +    }
       +#ifdef USE_PGP
       +    if (ekcast->length) {
       +      err = pgp_encrypt(PGP_CONVCAST | PGP_TEXT, temp, ekcast, NULL, NULL,
       +                        NULL, NULL);
       +      buf_clear(ekcast);
       +    }
       +    if (ekdes->length) {
       +      err = pgp_encrypt(PGP_CONV3DES | PGP_TEXT, temp, ekdes, NULL, NULL,
       +                        NULL, NULL);
       +      buf_clear(ekdes);
       +    }
       +    if (ek->length) {
       +      err = pgp_encrypt(PGP_CONVENTIONAL | PGP_TEXT, temp, ek, NULL, NULL,
       +                        NULL, NULL);
       +      buf_clear(ek);
       +    }
       +    buf_appends(out, EKMARK);
       +    buf_nl(out);
       +    buf_cat(out, temp);
       +#else /* end of USE_PGP */
       +    err = -1;
       +#endif /* Else if not USE_PGP */
       +  }
       +
       +  if (type == -1) {
       +    buf_appends(test, "No destination.\n");
       +    err = -1;
       +  }
       +
       +end:
       +  if (testto->length) {
       +    BUFFER *report;
       +    int i;
       +
       +    report = buf_new();
       +    buf_sets(report,
       +             "Subject: remailer test report\n\nThis is an automated response to the test message you sent to ");
       +    buf_appends(report, SHORTNAME);
       +    buf_appends(report, ".\nYour test message results follow:\n\n");
       +    buf_appends(report, remailer_type);
       +    buf_appends(report, VERSION);
       +    buf_appends(report, "\n\n");
       +    if (err == 0) {
       +      err = filtermsg(out);
       +      if (err == -1)
       +        buf_appends(report, "This remailer cannot deliver the message.\n\n");
       +      else {
       +        buf_appends(report, "Valid ");
       +        buf_appends(report, type == MSG_POST ? "Usenet" : "mail");
       +        buf_appends(report, " message.\n");
       +        if (remixto->length) {
       +          if (remix && MIX)
       +            buf_appends(report, "Delivery via Mixmaster: ");
       +          else if (remix)
       +            buf_appends(report, "Error! Can't remix: ");
       +          else
       +            buf_appends(report, "Delivery via Cypherpunk remailer: ");
       +          buf_cat(report, remixto);
       +          buf_nl(report);
       +        }
       +        else if (type == MSG_POST && strchr(NEWS, '@') && !strchr(NEWS, ' ')) {
       +          buf_appendf(report, "News gateway: %s\n", NEWS);
       +        }
       +        buf_appends(report,
       +                    "\n=========================================================================\nThe first 20 lines of the message follow:\n");
       +        if (err != 1)
       +          buf_appendf(report, "From: %s\n", ANONNAME);
       +        if (type == MSG_POST && ORGANIZATION[0] != '\0')
       +          buf_appendf(report, "Organization: %s\n", ORGANIZATION);
       +      }
       +      for (i = 0; i < 20 && buf_getline(out, test) != -1; i++)
       +        buf_cat(report, test), buf_nl(report);
       +    } else {
       +      buf_appends(report, "The remailer message is invalid.\n\n");
       +      if (test->length) {
       +        buf_appends(report, "The following error occurred: ");
       +        buf_cat(report, test);
       +        buf_nl(report);
       +      }
       +    }
       +    buf_appends(report,
       +                "=========================================================================\nThe first 20 lines of your message to the remailer follow:\n");
       +    buf_rewind(in);
       +    for (i = 0; i < 20 && buf_getline(in, test) != -1; i++)
       +      buf_cat(report, test), buf_nl(report);
       +
       +    sendmail(report, REMAILERNAME, testto);
       +    err = 0;
       +    buf_free(report);
       +  } else if (err == 0 && type != MSG_NULL) {
       +    err = 1;
       +    if (bufieq(to, REMAILERADDR)) /* don't remix to ourselves */
       +      remix = 0;
       +    if (remix && remixto->length == 0)
       +      buf_set(remixto, to);
       +    if (remixto->length > 0) {
       +      /* check that the remix-to path isn't too long */
       +      int remixcount = 1;
       +      char *tmp = remixto->data;
       +      while ((tmp = strchr(tmp+1, ','))) {
       +        remixcount ++;
       +        if (remixcount > MAXRANDHOPS) {
       +          *tmp = '\0';
       +          break;
       +        }
       +      };
       +    }
       +    if (remix && !repgp && remixto->length != 0)
       +      err = mix_encrypt(type, out, remixto->data, 1, line);
       +    if (err != 0) {
       +      if (remix == 1 && !repgp)
       +        errlog(NOTICE, "Can't remix -- %b\n", line);
       +      else {
       +        if (remixto->length)
       +          err = t1_encrypt(type, out, remixto->data, 0, 0, line);
       +        if (err != 0 && repgp)
       +          errlog(NOTICE, "Can't repgp -- %b\n", line);
       +        else
       +          err = mix_pool(out, type, latent * 60);
       +      }
       +    }
       +  }
       +
       +  buf_free(field);
       +  buf_free(content);
       +  buf_free(line);
       +  buf_free(to);
       +  buf_free(remixto);
       +  buf_free(newsgroups);
       +  buf_free(subject);
       +  buf_free(ek);
       +  buf_free(ekcast);
       +  buf_free(ekdes);
       +  buf_free(esub);
       +  buf_free(cutmarks);
       +  buf_free(temp);
       +  buf_free(out);
       +  buf_free(header);
       +  buf_free(test);
       +  buf_free(testto);
       +  buf_free(digest);
       +  return (err);
       +}
   DIR diff --git a/Src/rem2.c b/Src/rem2.c
       t@@ -0,0 +1,486 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Process Mixmaster remailer messages
       +   $Id: rem2.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include <string.h>
       +#include <time.h>
       +#include <ctype.h>
       +#include <sys/types.h>
       +#include <sys/stat.h>
       +#ifdef POSIX
       +#include <unistd.h>
       +#else /* end of POSIX */
       +#include <io.h>
       +#endif /* else if not POSIX */
       +#ifndef _MSC
       +#include <dirent.h>
       +#endif /* not _MSC */
       +#include <assert.h>
       +
       +int mix_dearmor(BUFFER *in, BUFFER *out)
       +{
       +  BUFFER *line, *md;
       +  int tempbuf = 0;
       +  int err = 0;
       +
       +  line = buf_new();
       +  md = buf_new();
       +
       +  if (in == out) {
       +    tempbuf = 1;
       +    out = buf_new();
       +  }
       +  do {
       +    err = buf_getline(in, line);
       +    if (err == -1)
       +      goto end;
       +  }
       +  while (!bufeq(line, begin_remailer));
       +
       +  do {
       +    /* skip lines before message digest */
       +    if (buf_getline(in, md) == -1)
       +      break;
       +  } while (strlen(md->data) != 24);
       +
       +  decode(in, out);
       +
       +  err = buf_getline(in, line);
       +  if (err != 0 || !bufeq(line, end_remailer))
       +    err = -1;
       +  else {
       +    digest_md5(out, line);
       +    encode(line, 0);
       +    if (!buf_eq(md, line))
       +      err = -1;
       +    if (out->length != 20480)
       +      err = -1;
       +  }
       +
       +end:
       +  if (err == -1)
       +    errlog(NOTICE, "Malformatted message.\n");
       +
       +  if (tempbuf) {
       +    buf_move(in, out);
       +    buf_free(out);
       +  }
       +  buf_free(line);
       +  buf_free(md);
       +  return (err);
       +}
       +
       +static int isnewid(BUFFER *id, long timestamp)
       +/* return values:
       + *   0: ignore message, no error
       + *   1: ok, process message
       + *  -1: bad message, send reply
       + */
       +{
       +  FILE *f;
       +  int ret = 1;
       +  long now, old = 0;
       +  LOCK *i = NULL;
       +  idlog_t idbuf;
       +
       +  if (REMAIL == 0)
       +    return (1); /* don't keep statistics for the client */
       +
       +  now = time(NULL);
       +
       +  if ((f = mix_openfile(IDLOG, "rb+")) != NULL) {
       +    fread(&idbuf,1,sizeof(idlog_t),f);
       +    old = idbuf.time;
       +  } else {
       +    if (IDEXP == 0) {
       +      if (timestamp > 0 && timestamp <= now - 7 * SECONDSPERDAY) {
       +        errlog(LOG, "Ignoring old message.\n");
       +        return (0);
       +      }
       +    } else {
       +      if ((f = mix_openfile(IDLOG, "wb")) != NULL) {
       +        memset(idbuf.id,0,sizeof(idbuf.id));
       +        idbuf.time = now;
       +        fwrite(&idbuf,1,sizeof(idlog_t),f);
       +        memcpy(idbuf.id,id->data,sizeof(idbuf.id));
       +        idbuf.time = now;
       +        fwrite(&idbuf,1,sizeof(idlog_t),f);
       +        fclose(f);
       +        errlog(NOTICE, "Creating %s\n", IDLOG);
       +      } else {
       +        errlog(ERRORMSG, "Can't create %s\n", IDLOG);
       +      }
       +      return (1);
       +    }
       +  }
       +
       +  if (now - old < 5 * SECONDSPERDAY)        /* never reject messages less than */
       +    old = now - 5 * SECONDSPERDAY;        /* 5 days old (== minimum IDEXP) */
       +
       +  if (timestamp > 0 && timestamp <= old) {
       +    errlog(LOG, "Ignoring old message.\n");
       +    ret = 0;
       +    goto end;
       +  }
       +  i = lockfile(IDLOG);
       +  while (fread(&idbuf, 1, sizeof(idlog_t), f) == sizeof(idlog_t)) {
       +    if (!memcmp(idbuf.id, id->data, sizeof(idbuf.id))) {
       +      char idstr[33];
       +      id_encode(id->data, idstr);
       +      errlog(LOG, "Ignoring redundant message: %s.\n", idstr);
       +      ret = 0;
       +      goto end;
       +    }
       +  }
       +  if (timestamp > now) {
       +    errlog(LOG, "Ignoring message with future timestamp.\n");
       +    ret = -1;
       +    goto end;
       +  }
       +  if (ftell(f)%sizeof(idlog_t)) fseek(f,0-(ftell(f)%sizeof(idlog_t)),SEEK_CUR); /* make sure that we're on sizeof(idlog_t) byte boundary */
       +  memcpy(idbuf.id,id->data,sizeof(idbuf.id));
       +  idbuf.time = now;
       +  fwrite(&idbuf,1,sizeof(idlog_t),f);
       +end:
       +  if (i)
       +    unlockfile(i);
       +  fclose(f);
       +  return (ret);
       +}
       +
       +int mix2_decrypt(BUFFER *m)
       +     /*  0: ok
       +      * -1: error
       +      * -2: old message */
       +{
       +  int err = 0;
       +  int i;
       +  BUFFER *privkey;
       +  BUFFER *keyid;
       +  BUFFER *dec, *deskey;
       +  BUFFER *packetid, *mid, *digest, *addr, *temp, *iv, *ivvec;
       +  int type, packet = 0, numpackets = 0, timestamp = 0;
       +  BUFFER *body;
       +  BUFFER *header, *out;
       +
       +  privkey = buf_new();
       +  keyid = buf_new();
       +  dec = buf_new();
       +  deskey = buf_new();
       +  packetid = buf_new();
       +  mid = buf_new();
       +  digest = buf_new();
       +  addr = buf_new();
       +  temp = buf_new();
       +  iv = buf_new();
       +  ivvec = buf_new();
       +  body = buf_new();
       +  header = buf_new();
       +  out = buf_new();
       +
       +  buf_get(m, keyid, 16);
       +  err = db_getseckey(keyid->data, privkey);
       +  if (err == -1)
       +    goto end;
       +  buf_get(m, deskey, buf_getc(m));
       +  err = pk_decrypt(deskey, privkey);
       +  if (err == -1 || deskey->length != 24) {
       +    err = -1;
       +    errlog(NOTICE, "Cannot decrypt message.\n");
       +    goto end;
       +  }
       +  buf_get(m, iv, 8);
       +  buf_get(m, dec, 328);
       +  buf_crypt(dec, deskey, iv, DECRYPT);
       +  buf_get(dec, packetid, 16);
       +  buf_get(dec, deskey, 24);
       +  type = buf_getc(dec);
       +  switch (type) {
       +  case 0:
       +    buf_get(dec, ivvec, 152);
       +    buf_get(dec, addr, 80);
       +    break;
       +  case 1:
       +    buf_get(dec, mid, 16);
       +    buf_get(dec, iv, 8);
       +    break;
       +  case 2:
       +    packet = buf_getc(dec);
       +    numpackets = buf_getc(dec);
       +    buf_get(dec, mid, 16);
       +    buf_get(dec, iv, 8);
       +    break;
       +  default:
       +    errlog(WARNING, "Unknown message type.\n");
       +    err = -1;
       +    goto end;
       +  }
       +  if (dec->data[dec->ptr] == '0' && dec->data[dec->ptr + 1] == '0' &&
       +      dec->data[dec->ptr + 2] == '0' && dec->data[dec->ptr + 3] == '0' &&
       +      dec->data[dec->ptr + 4] == '\0') {
       +    dec->ptr += 5;
       +    timestamp = buf_geti_lo(dec);
       +  } else {
       +    errlog(LOG, "Ignoring message without timestamp.\n");
       +    err = -1;
       +    goto end;
       +  }
       +  buf_get(dec, digest, 16);
       +
       +  dec->length = dec->ptr - 16;        /* ignore digest */
       +  dec->ptr = dec->length;
       +
       +  if (!isdigest_md5(dec, digest)) {
       +    errlog(NOTICE, "Message digest does not match.\n");
       +    err = -1;
       +    goto end;
       +  }
       +  switch (isnewid(packetid, timestamp * SECONDSPERDAY)) {
       +    case  0: err = -2; /* redundant message */
       +             goto end;
       +    case -1: err = -1; /* future timestamp */
       +             goto end; 
       +  }
       +  buf_append(body, m->data + 20 * 512, 10240);
       +
       +  switch (type) {
       +  case 0:
       +    buf_chop(addr);
       +    buf_cat(out, addr);
       +    buf_nl(out);
       +    for (i = 0; i < 19; i++) {
       +      buf_reset(header);
       +      buf_append(header, m->data + (i + 1) * 512, 512);
       +      buf_reset(iv);
       +      buf_append(iv, ivvec->data + i * 8, 8);
       +      buf_crypt(header, deskey, iv, DECRYPT);
       +      buf_cat(out, header);
       +    }
       +    buf_reset(header);
       +    buf_pad(header, 512);
       +    buf_cat(out, header);
       +    buf_reset(iv);
       +    buf_append(iv, ivvec->data + 144, 8);
       +    buf_crypt(body, deskey, iv, DECRYPT);
       +    buf_cat(out, body);
       +    mix_pool(out, INTERMEDIATE, -1);
       +    break;
       +  case 1:
       +    buf_crypt(body, deskey, iv, DECRYPT);
       +    err = v2body_setlen(body);
       +    if (err == -1)
       +      goto end;
       +    assert(body->ptr == 4);
       +    v2body(body);
       +    break;
       +  case 2:
       +    buf_crypt(body, deskey, iv, DECRYPT);
       +    v2partial(body, mid, packet, numpackets);
       +    break;
       +  }
       +end:
       +  buf_free(privkey);
       +  buf_free(keyid);
       +  buf_free(dec);
       +  buf_free(deskey);
       +  buf_free(packetid);
       +  buf_free(mid);
       +  buf_free(digest);
       +  buf_free(addr);
       +  buf_free(temp);
       +  buf_free(iv);
       +  buf_free(ivvec);
       +  buf_free(body);
       +  buf_free(header);
       +  buf_free(out);
       +
       +  return (err);
       +}
       +
       +int v2body_setlen(BUFFER *body)
       +{
       +  long length;
       +
       +  length = buf_getl_lo(body);
       +  if (length < 0 || length > body->length)
       +    return (-1);
       +  body->length = length + 4;
       +  return (0);
       +}
       +
       +int v2body(BUFFER *body)
       +{
       +  int i, n;
       +  BUFFER *to, *newsgroups;
       +  BUFFER *temp, *out;
       +  BUFFER *line;
       +  int type = MSG_MAIL;
       +  int subject = 0;
       +
       +  line = buf_new();
       +  to = buf_new();
       +  newsgroups = buf_new();
       +  temp = buf_new();
       +  out = buf_new();
       +
       +  n = buf_getc(body);
       +  for (i = 0; i < n; i++) {
       +    buf_get(body, line, 80);
       +    buf_chop(line);
       +    if (bufileft(line, "null:"))
       +      goto end;
       +    if (bufileft(line, "post:")) {
       +      type = MSG_POST;
       +      if (line->length > 5) {
       +        int j = 5;
       +
       +        while (j < line->length && isspace(line->data[j]))
       +          j++;
       +        if (newsgroups->length > 0)
       +          buf_appends(newsgroups, ",");
       +        buf_append(newsgroups, line->data + j, line->length - j);
       +      }
       +    } else {
       +      if (to->length > 0)
       +        buf_appends(to, ",");
       +      buf_cat(to, line);
       +    }
       +  }
       +  if (to->length > 0) {
       +    buf_appends(out, "To: ");
       +    buf_cat(out, to);
       +    buf_nl(out);
       +  }
       +  if (newsgroups->length > 0) {
       +    buf_appends(out, "Newsgroups: ");
       +    buf_cat(out, newsgroups);
       +    buf_nl(out);
       +  }
       +  n = buf_getc(body);
       +  for (i = 0; i < n; i++) {
       +    buf_get(body, line, 80);
       +    buf_chop(line);
       +    if (bufileft(line, "Subject:"))
       +      subject = 1;
       +    buf_cat(out, line);
       +    buf_nl(out);
       +  }
       +
       +  buf_rest(temp, body);
       +  buf_uncompress(temp);
       +  buf_set(body, temp);
       +  buf_reset(temp);
       +
       +  if (buf_lookahead(body, line) == 0 && isline(line, HASHMARK)) {
       +    buf_getline(body, line);
       +    while (buf_getline(body, line) == 0) {
       +      if (bufileft(line, "subject:"))
       +        subject = 1;
       +      buf_cat(out, line);
       +      buf_nl(out);
       +    }
       +  }
       +  if (type == MSG_POST && !subject)
       +    buf_appends(out, "Subject: (no subject)\n");
       +
       +  buf_nl(out);
       +  buf_rest(out, body);
       +  buf_reset(body);
       +  mix_pool(out, type, -1);
       +
       +end:
       +  buf_free(line);
       +  buf_free(to);
       +  buf_free(newsgroups);
       +  buf_free(temp);
       +  buf_free(out);
       +  return (0);
       +}
       +
       +int v2_merge(BUFFER *mid)
       +{
       +  char fname[PATHMAX], line[LINELEN];
       +  BUFFER *temp, *msg;
       +  FILE *l, *f;
       +  int i, numpackets;
       +  struct stat sb;
       +  long d;
       +  int n;
       +  int err = -1;
       +
       +  temp = buf_new();
       +  msg = buf_new();
       +  pool_packetfile(fname, mid, 0);
       +  l = fopen(fname, "a+");
       +  if (l != NULL)
       +    lock(l);
       +
       +  pool_packetfile(fname, mid, 1);
       +  f = fopen(fname, "rb");
       +  if (f == NULL)
       +    goto end;
       +  fscanf(f, "%32s %ld %d %d\n", line, &d, &i, &numpackets);
       +  fclose(f);
       +
       +  /* do we have all packets? */
       +  for (i = 1; i <= numpackets; i++) {
       +    pool_packetfile(fname, mid, i);
       +    if (stat(fname, &sb) != 0)
       +      goto end;
       +  }
       +  errlog(LOG, "Reassembling multipart message.\n");
       +  for (i = 1; i <= numpackets; i++) {
       +    pool_packetfile(fname, mid, i);
       +    f = fopen(fname, "rb");
       +    if (f == NULL)
       +      goto end;
       +    fscanf(f, "%32s %ld %d %d\n", line, &d, &n, &n);
       +    buf_clear(temp);
       +    buf_read(temp, f);
       +    v2body_setlen(temp);
       +    buf_append(msg, temp->data + 4, temp->length - 4);
       +    fclose(f);
       +    unlink(fname);
       +  }
       +  err = v2body(msg);
       +
       +end:
       +  if (l != NULL)
       +    fclose(l);
       +  pool_packetfile(fname, mid, 0);
       +  unlink(fname);
       +  buf_free(temp);
       +  buf_free(msg);
       +  return (err);
       +}
       +
       +int v2partial(BUFFER *m, BUFFER *mid, int packet, int numpackets)
       +{
       +  char fname[PATHMAX], idstr[33];
       +  FILE *f;
       +  int err = 1;
       +
       +  pool_packetfile(fname, mid, packet);
       +  f = fopen(fname, "wb");
       +  if (f == NULL) {
       +    err = -1;
       +    goto end;
       +  }
       +  id_encode(mid->data, idstr);
       +  fprintf(f, "%s %ld %d %d\n", idstr, (long) time(NULL), packet,
       +          numpackets);
       +  buf_write(m, f);
       +  buf_reset(m);
       +  fclose(f);
       +  v2_merge(mid);
       +end:
       +  return (err);
       +}
   DIR diff --git a/Src/remailer.c b/Src/remailer.c
       t@@ -0,0 +1,36 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Simple remailer frontend: Read mix packets from standard input.
       +   $Id: remailer.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix.h"
       +#include <stdio.h>
       +
       +/** main *****************************************************************/
       +
       +/* Returns:
       + 0 successful operation
       + 1 error */
       +
       +int main(int argc, char *argv[])
       +{
       +  BUFFER *msg;
       +  int ret;
       +
       +  mix_init(NULL);
       +  msg = buf_new();
       +  ret = buf_read(msg, stdin);
       +  if (ret != -1)
       +    ret = mix_decrypt(msg);
       +
       +  mix_regular(0);
       +  mix_exit();
       +  buf_free(msg);
       +  return (ret == 0 ? 0 : 1);
       +}
   DIR diff --git a/Src/rfc822.c b/Src/rfc822.c
       t@@ -0,0 +1,585 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Parse RFC 822 headers
       +   $Id: rfc822.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +
       +static int is_specials(int c);
       +static int is_qtext(char c);
       +static int is_ctext(char c);
       +static void wsc(BUFFER *in, BUFFER *xomment);
       +static int word(BUFFER *in, BUFFER *word, BUFFER *x);
       +static int atom(BUFFER *in, BUFFER *atom, BUFFER *x);
       +static int quoted_string(BUFFER *in, BUFFER *string, BUFFER *x);
       +static int comment(BUFFER *in, BUFFER *string);
       +static int local_part(BUFFER *in, BUFFER *addr, BUFFER *x);
       +static int domain(BUFFER *in, BUFFER *domain, BUFFER *x);
       +static int sub_domain(BUFFER *in, BUFFER *sub, BUFFER *x);
       +static int domain_ref(BUFFER *in, BUFFER *dom, BUFFER *x);
       +static int domain_literal(BUFFER *in, BUFFER *dom, BUFFER *x);
       +static int addr_spec(BUFFER *in, BUFFER *addr, BUFFER *x);
       +static int route_addr(BUFFER *in, BUFFER *addr, BUFFER *x);
       +static int phrase(BUFFER *in, BUFFER *phr, BUFFER *x);
       +static int mailbox(BUFFER *in, BUFFER *mailbox, BUFFER *name, BUFFER *x);
       +static int group(BUFFER *in, BUFFER *group, BUFFER *name, BUFFER *x);
       +
       +static void backtrack(BUFFER *b, int len)
       +{
       +  if (b) {
       +    b->length = len;
       +    b->data[b->length] = '\0';
       +  }
       +}
       +
       +/* white space and comments */
       +static void wsc(BUFFER *in, BUFFER *string)
       +{
       +  int c;
       +
       +  for (;;) {
       +    c = buf_getc(in);
       +    if (c == -1)
       +      break;
       +    else if (c == '\n') {
       +      c = buf_getc(in);
       +      if (c != ' ' && c != '\t') {
       +        if (c != -1)
       +          buf_ungetc(in), buf_ungetc(in);
       +        break;
       +      }
       +    } else {
       +      if (c != ' ' && c != '\t') {
       +        buf_ungetc(in);
       +        if (!comment(in, string))
       +          break;
       +      }
       +    }
       +  }
       +}
       +
       +/*          specials    =  "(" / ")" / "<" / ">" / "@"  ; Must be in quoted-
       + *                      /  "," / ";" / ":" / "\" / <">  ;  string, to use
       + *                      /  "." / "[" / "]"              ;  within a word.
       + */
       +
       +static int is_specials(int c)
       +{
       +  return (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' ||
       +          c == ',' || c == ';' || c == ':' || c == '\\' || c == '\"' ||
       +          c == '.' || c == '[' || c == ']');
       +}
       +
       +/*           qtext       =  <any CHAR excepting <">,     ; => may be folded
       + *                          "\" & CR, and including
       + *                          linear-white-space>
       + */
       +static int is_qtext(char c)
       +{
       +  return (c != '\"' && c != '\\' && c != '\n');
       +}
       +
       +/*           ctext       =  <any CHAR excluding "(",     ; => may be folded
       + *                          ")", "\" & CR, & including
       + *                          linear-white-space>
       + */
       +static int is_ctext(char c)
       +{
       +  return (c != '(' && c != ')' && c != '\\' && c != '\n');
       +}
       +
       +/*           word        =  atom / quoted-string
       + */
       +static int word(BUFFER *in, BUFFER *word, BUFFER *x)
       +{
       +  return (atom(in, word, x) || quoted_string(in, word, x));
       +}
       +
       +/*          atom        =  1*<any CHAR except specials, SPACE and CTLs>
       + */
       +static int atom(BUFFER *in, BUFFER *atom, BUFFER *x)
       +{
       +  int c;
       +
       +  buf_clear(atom);
       +  wsc(in, x);
       +  for (;;) {
       +    c = buf_getc(in);
       +    if (c == -1)
       +      break;
       +    else if (is_specials(c) || c == ' ' || c < 32 || c == 127) {
       +      buf_ungetc(in);
       +      break;
       +    } else
       +      buf_appendc(atom, c);
       +  }
       +  if (atom->length)
       +    wsc(in, x);
       +  return (atom->length);
       +}
       +
       +/*           quoted-string = <"> *(qtext/quoted-pair) <">; Regular qtext or
       + *                                                       ;   quoted chars.
       + */
       +static int quoted_string(BUFFER *in, BUFFER *string, BUFFER *x)
       +{
       +  int ptr, xlen;
       +  int c;
       +
       +  ptr = in->ptr, xlen = x ? x->length : 0;
       +  buf_clear(string);
       +  wsc(in, NULL);
       +  c = buf_getc(in);
       +  if (c == '\"') {
       +#if 0
       +    buf_appendc(string, c);
       +#endif
       +    for (;;) {
       +      c = buf_getc(in);
       +      if (c == -1)              /* catch unterminated quoted string */
       +        break;
       +      if (is_qtext(c))
       +        buf_appendc(string, c);
       +      else if (c == '\n') {
       +        c = buf_getc(in);
       +        if (c != ' ' && c != '\n')
       +          break;
       +      } else if (c == '\\') {
       +        c = buf_getc(in);
       +        if (c == -1)
       +          break;
       +        else
       +          buf_appendc(string, c);
       +      } else if (c == '\"') {
       +#if 0
       +        buf_appendc(string, c);
       +#endif
       +        wsc(in, NULL);
       +        return (1);
       +      } else
       +        break;
       +    }
       +  }
       +  in->ptr = ptr, backtrack(x, xlen);
       +  return (0);
       +}
       +
       +/*           comment     =  "(" *(ctext / quoted-pair / comment) ")"
       + */
       +static int comment(BUFFER *in, BUFFER *string)
       +{
       +  int ptr, xlen;
       +  int separator = 0;
       +  int c;
       +
       +  ptr = in->ptr;
       +  xlen = string ? string->length : 0;
       +  if (xlen)
       +    separator = 1;
       +  c = buf_getc(in);
       +  if (c == '(') {
       +    for (;;) {
       +      c = buf_getc(in);
       +      if (c == -1)
       +        return(1); /* unterminated comment, bail out */
       +      if (is_ctext(c)) {
       +        if (string != NULL) {
       +          if (separator)
       +            buf_appendc(string, ' '), separator = 0;
       +          buf_appendc(string, c);
       +        }
       +      } else if (c == '\n') {
       +        c = buf_getc(in);
       +        if (c != ' ' && c != '\n')
       +          break;
       +      } else if (c == '\\') {
       +        c = buf_getc(in);
       +        if (c != -1) {
       +          if (string != NULL) {
       +            if (separator)
       +              buf_appendc(string, ' '), separator = 0;
       +            buf_appendc(string, c);
       +          }
       +        }
       +      } else if (c == ')')
       +        return (1);
       +      else {
       +        BUFFER *s;
       +        int o;
       +
       +        s = buf_new();
       +        buf_ungetc(in);
       +        o = comment(in, s);
       +        if (o && string != NULL) {
       +          if (separator)
       +            buf_appendc(string, ' '), separator = 0;
       +          buf_cat(string, s);
       +        }
       +        buf_free(s);
       +        if (!o)
       +          break;
       +      }
       +    }
       +  }
       +  in->ptr = ptr;
       +  backtrack(string, xlen);
       +  return (0);
       +}
       +
       +/*          local-part  =  word *("." word)             ; uninterpreted
       + *                                                      ; case-preserved
       + */
       +static int local_part(BUFFER *in, BUFFER *addr, BUFFER *x)
       +{
       +  BUFFER *w;
       +  int c;
       +
       +  buf_clear(addr);
       +  if (!word(in, addr, x))
       +    return (0);
       +  w = buf_new();
       +  for (;;) {
       +    c = buf_getc(in);
       +    if (c == -1)
       +      break;
       +    if (c == '.' && (word(in, w, x)))
       +      buf_appendc(addr, '.'), buf_cat(addr, w);
       +    else {
       +      buf_ungetc(in);
       +      break;
       +    }
       +  }
       +  buf_free(w);
       +  return (addr->length);
       +}
       +
       +/*           domain      =  sub-domain *("." sub-domain)
       + */
       +static int domain(BUFFER *in, BUFFER *domain, BUFFER *x)
       +{
       +  BUFFER *sub;
       +  int c;
       +
       +  if (!sub_domain(in, domain, x))
       +    return (0);
       +  sub = buf_new();
       +  for (;;) {
       +    c = buf_getc(in);
       +    if (c == -1)
       +      break;
       +    if (c == '.' && (sub_domain(in, sub, x)))
       +      buf_appendc(domain, '.'), buf_cat(domain, sub);
       +    else {
       +      buf_ungetc(in);
       +      break;
       +    }
       +  }
       +  buf_free(sub);
       +  return (domain->length);
       +}
       +
       +/*             sub-domain  =  domain-ref / domain-literal
       + */
       +static int sub_domain(BUFFER *in, BUFFER *sub, BUFFER *x)
       +{
       +  return (domain_ref(in, sub, x) || domain_literal(in, sub, x));
       +}
       +
       +/*           domain-ref  =  atom                         ; symbolic reference
       + */
       +static int domain_ref(BUFFER *in, BUFFER *d, BUFFER *x)
       +{
       +  return (atom(in, d, x));
       +}
       +
       +/*           addr-spec   =  local-part "@" domain        ; global address
       + */
       +static int addr_spec(BUFFER *in, BUFFER *addr, BUFFER *x)
       +{
       +  BUFFER *dom;
       +  int ptr, xlen;
       +
       +  ptr = in->ptr, xlen = x ? x->length : 0;
       +  dom = buf_new();
       +  buf_clear(addr);
       +  if (local_part(in, addr, x) && buf_getc(in) == '@' && domain(in, dom, x))
       +    buf_appendc(addr, '@'), buf_cat(addr, dom);
       +  else
       +    buf_clear(addr), in->ptr = ptr, backtrack(x, xlen);
       +  buf_free(dom);
       +  return (addr->length);
       +}
       +
       +/*           route-addr  =  "<" [route] addr-spec ">"
       + */
       +static int route_addr(BUFFER *in, BUFFER *addr, BUFFER *x)
       +{
       +  int c;
       +  int ptr, xlen;
       +
       +  ptr = in->ptr, xlen = x ? x->length : 0;
       +  c = buf_getc(in);
       +  if (c == -1)
       +    return (0);
       +  if (c != '<') {
       +    buf_ungetc(in);
       +    return (0);
       +  }
       +  if (addr_spec(in, addr, x) && buf_getc(in) == '>')
       +    return (1);
       +  in->ptr = ptr, backtrack(x, xlen);
       +  return (0);
       +}
       +
       +/*           phrase      =  1*word                       ; Sequence of words
       + */
       +static int phrase(BUFFER *in, BUFFER *phr, BUFFER *x)
       +{
       +  BUFFER *w;
       +
       +  buf_clear(phr);
       +  w = buf_new();
       +  while (word(in, w, x)) {
       +    if (phr->length)
       +      buf_appendc(phr, ' ');
       +    buf_cat(phr, w);
       +  }
       +  buf_free(w);
       +  return (phr->length);
       +}
       +
       +/*          mailbox     =  addr-spec                    ; simple address
       + *                      /  [phrase] route-addr          ; name & addr-spec
       + *                                                        (RFC 1123)
       + */
       +static int mailbox(BUFFER *in, BUFFER *mailbox, BUFFER *name, BUFFER *x)
       +{
       +  int ptr, xlen, ret;
       +
       +  buf_clear(name);
       +  if (addr_spec(in, mailbox, x))
       +    return (1);
       +
       +  ptr = in->ptr, xlen = x ? x->length : 0;
       +  ret = phrase(in, name, x) && route_addr(in, mailbox, x);
       +  if (!ret) {
       +    in->ptr = ptr, backtrack(x, xlen);
       +    ret = route_addr(in, mailbox, x);
       +  }
       +
       +  return (ret);
       +}
       +
       +/*          address     =  mailbox                      ; one addressee
       + *                      /  group                        ; named list
       + */
       +static int address(BUFFER *in, BUFFER *address, BUFFER *name, BUFFER *x)
       +{
       +  return (mailbox(in, address, name, x) || group(in, address, name, x));
       +}
       +
       +/*          group       =  phrase ":" [#mailbox] ";"
       + */
       +static int group(BUFFER *in, BUFFER *group, BUFFER *name, BUFFER *x)
       +{
       +  BUFFER *addr, *tmp;
       +  int ptr, xlen, ret = 0;
       +
       +  ptr = in->ptr, xlen = x ? x->length : 0;
       +  addr = buf_new();
       +  tmp = buf_new();
       +  buf_clear(group);
       +  if (phrase(in, name, x) && buf_getc(in) == ':') {
       +    while (mailbox(in, addr, tmp, x))
       +      buf_cat(group, addr), buf_nl(group);
       +    ret = buf_getc(in) == ';';
       +  }
       +  if (!ret)
       +    in->ptr = ptr, backtrack(x, xlen);
       +  buf_free(addr);
       +  buf_free(tmp);
       +  return (ret);
       +}
       +
       +/*         domain-literal =  "[" *(dtext / quoted-pair) "]"
       + */
       +static int domain_literal(BUFFER *in, BUFFER *dom, BUFFER *x)
       +{
       +  return 0;                        /* XXX */
       +}
       +
       +/* local address without `@' is not specified in RFC 822 */
       +
       +/* local_addr = "<" atom ">" */
       +static int local_addr(BUFFER *in, BUFFER *addr, BUFFER *x)
       +{
       +  int c;
       +  int ptr, xlen;
       +
       +  ptr = in->ptr, xlen = x ? x->length : 0;
       +  c = buf_getc(in);
       +  if (c == -1)
       +    return (0);
       +  if (c != '<') {
       +    buf_ungetc(in);
       +    return (0);
       +  }
       +  if (atom(in, addr, x) && buf_getc(in) == '>')
       +    return (1);
       +  in->ptr = ptr, backtrack(x, xlen);
       +  return (0);
       +}
       +
       +static int localaddress(BUFFER *in, BUFFER *address, BUFFER *name, BUFFER *x)
       +{
       +  int ptr, xlen;
       +
       +  buf_clear(name);
       +  if (local_addr(in, address, x))
       +    return (1);
       +  ptr = in->ptr, xlen = x ? x->length : 0;
       +  if (phrase(in, name, x) && local_addr(in, address, x))
       +    return (1);
       +  in->ptr = ptr, backtrack(x, xlen);
       +  buf_clear(name);
       +  return (atom(in, address, x));
       +}
       +
       +void rfc822_addr(BUFFER *destination, BUFFER *list)
       +{
       +  BUFFER *addr, *name;
       +
       +  addr = buf_new();
       +  name = buf_new();
       +
       +  for (;;) {
       +    if (!address(destination, addr, name, NULL) &&
       +        !localaddress(destination, addr, name, NULL))
       +      break;
       +    buf_cat(list, addr);
       +    buf_nl(list);
       +    if (buf_getc(destination) != ',')
       +      break;
       +  }
       +  buf_free(addr);
       +  buf_free(name);
       +}
       +
       +void rfc822_name(BUFFER *line, BUFFER *name)
       +{
       +  BUFFER *addr, *comment;
       +  int ret;
       +
       +  addr = buf_new();
       +  comment = buf_new();
       +  ret = address(line, addr, name, comment);
       +  if (ret == 0)
       +    ret = localaddress(line, addr, name, comment);
       +  if (ret) {
       +    if (name->length == 0)
       +      buf_set(name, comment);
       +    if (name->length == 0)
       +      buf_set(name, addr);
       +  }
       +  if (ret == 0)
       +    buf_set(name, line);
       +  buf_free(addr);
       +  buf_free(comment);
       +}
       +
       +/* MIME extensions. RFC 2045 */
       +
       +/*    tspecials :=  "(" / ")" / "<" / ">" / "@" /
       + *                  "," / ";" / ":" / "\" / <">
       + *                  "/" / "[" / "]" / "?" / "="
       + */
       +
       +static int is_tspecials(int c)
       +{
       +  return (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' ||
       +          c == ',' || c == ';' || c == ':' || c == '\\' || c == '\"' ||
       +          c == '/' || c == '[' || c == ']' || c == '?' || c == '=');
       +}
       +
       +/* token := 1*<any (US-ASCII) CHAR except SPACE, CTLs,
       + *                or tspecials>
       + */
       +static int token(BUFFER *in, BUFFER *token, BUFFER *x)
       +{
       +  int c;
       +
       +  buf_clear(token);
       +  wsc(in, x);
       +  for (;;) {
       +    c = buf_getc(in);
       +    if (c == -1)
       +      break;
       +    else if (is_tspecials(c) || c == ' ' || c < 32 || c == 127) {
       +      buf_ungetc(in);
       +      break;
       +    } else
       +      buf_appendc(token, c);
       +  }
       +  if (token->length)
       +    wsc(in, x);
       +  return (token->length);
       +}
       +
       +/*   value := token / quoted-string
       + */
       +
       +static int value(BUFFER *in, BUFFER *value, BUFFER *x)
       +{
       +  return (token(in, value, x) || quoted_string(in, value, x));
       +}
       +
       +/*   parameter := attribute "=" value
       + */
       +
       +static int parameter(BUFFER *in, BUFFER *attribute, BUFFER *val, BUFFER *x)
       +{
       +  int ptr;
       +  ptr = in->ptr;
       +  token(in, attribute, x);
       +  if (buf_getc(in) != '=') {
       +    in->ptr = ptr;
       +    return(0);
       +  }
       +  return(value(in, val, x));
       +}
       +
       +/* get type */
       +int get_type(BUFFER *content, BUFFER *type, BUFFER *subtype)
       +{
       +  token(content, type, NULL);
       +  if (buf_getc(content) == '/')
       +    return (token(content, subtype, NULL));
       +  buf_ungetc(content);
       +  buf_clear(type);
       +  return (0);
       +}
       +
       +/* get parameter value */
       +void get_parameter(BUFFER *content, char *attribute, BUFFER *value)
       +{
       +  BUFFER *tok;
       +  tok = buf_new();
       +  buf_clear(value);
       +
       +  get_type(content, tok, tok);
       +    for (;;) {
       +      if (buf_getc(content) != ';')
       +        break;
       +      if (parameter(content, tok, value, NULL) &&
       +          strieq(attribute, tok->data))
       +        break; /* found */
       +      buf_clear(value);
       +    }
       +  buf_free(tok);
       +}
   DIR diff --git a/Src/rndseed.c b/Src/rndseed.c
       t@@ -0,0 +1,157 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Get randomness from device or user
       +   $Id: rndseed.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include <assert.h>
       +#include <time.h>
       +#include <fcntl.h>
       +#include <time.h>
       +#include <stdlib.h>
       +#ifdef POSIX
       +#include <unistd.h>
       +#include <termios.h>
       +#else /* end of POSIX */
       +#include <io.h>
       +#include <process.h>
       +#endif /* else if not POSIX */
       +#if defined(WIN32) || defined(MSDOS)
       +#include <conio.h>
       +#endif /* defined(WIN32) || defined(MSDOS) */
       +#ifdef WIN32
       +#include <windows.h>
       +#endif /* WIN32 */
       +
       +#define NEEDED 128
       +
       +#ifndef O_NDELAY
       +#define O_NDELAY 0
       +#endif /* not O_NDELAY */
       +
       +int kbd_noecho(void)
       +{
       +#ifdef HAVE_TERMIOS
       +  int fd;
       +  struct termios attr;
       +
       +  setbuf(stdin, NULL);
       +  fd = fileno(stdin);
       +  if (tcgetattr(fd, &attr) != 0)
       +    return (-1);
       +  attr.c_lflag &= ~(ECHO | ICANON);
       +  if (tcsetattr(fd, TCSAFLUSH, &attr) != 0)
       +    return (-1);
       +#endif /* HAVE_TERMIOS */
       +  return (0);
       +}
       +
       +int kbd_echo(void)
       +{
       +#ifdef HAVE_TERMIOS
       +  int fd;
       +  struct termios attr;
       +
       +  setvbuf(stdin, NULL, _IOLBF, BUFSIZ);
       +  fd = fileno(stdin);
       +  if (tcgetattr(fd, &attr) != 0)
       +    return (-1);
       +  attr.c_lflag |= ECHO | ICANON;
       +  if (tcsetattr(fd, TCSAFLUSH, &attr) != 0)
       +    return (-1);
       +#endif /* HAVE_TERMIOS */
       +  return (0);
       +}
       +
       +void rnd_error(void)
       +{
       +  errlog(ERRORMSG,
       +         "Random number generator not initialized. Aborting.\n\
       +Run the program interactively to seed the generator.\n");
       +  exit(3);
       +}
       +
       +/* get randomness from system or user. If the application has promised that
       +   it will seed the RNG later, we do not ask for user input */
       +
       +int rnd_seed(void)
       +{
       +  int fd = -1;
       +  byte b[512], c = 0;
       +  int bytes = 0;
       +
       +#ifdef DEV_RANDOM
       +  fd = open(DEV_RANDOM, O_RDONLY | O_NDELAY);
       +#endif /* DEV_RANDOM */
       +  if (fd == -1) {
       +#if 1
       +    if (rnd_state == RND_WILLSEED)
       +      return(-1);
       +    if (!isatty(fileno(stdin)))
       +      rnd_error();
       +#else /* end of 1 */
       +#error "should initialize the prng from system ressources"
       +#endif /* else if not 1 */
       +    fprintf(stderr, "Please enter some random characters.\n");
       +    kbd_noecho();
       +    while (bytes < NEEDED) {
       +      fprintf(stderr, "  %d     \r", NEEDED - bytes);
       +#ifdef HAVE_GETKEY
       +      if (kbhit(), *b = getkey())
       +#else /* end of HAVE_GETKEY */
       +      if (read(fileno(stdin), b, 1) > 0)
       +#endif /* else if not HAVE_GETKEY */
       +        {
       +          rnd_add(b, 1);
       +          rnd_time();
       +          if (*b != c)
       +            bytes++;
       +          c = *b;
       +        }
       +    }
       +    fprintf(stderr, "Thanks.\n");
       +    sleep(1);
       +    kbd_echo();
       +  }
       +#ifdef DEV_RANDOM
       +  else {
       +    bytes = read(fd, b, sizeof(b));
       +    if (bytes > 0) {
       +      rnd_add(b, bytes);
       +    } else {
       +      bytes = 0;
       +    }
       +    close(fd);
       +    if (bytes < NEEDED) {
       +      fd = open(DEV_RANDOM, O_RDONLY);        /* re-open in blocking mode */
       +      if (isatty(fileno(stdin))) {
       +        fprintf(stderr,
       +                "Please move the mouse, enter random characters, etc.\n");
       +        kbd_noecho();
       +      }
       +      while (bytes < NEEDED) {
       +        if (isatty(fileno(stdin)))
       +          fprintf(stderr, "  %d     \r", NEEDED - bytes);
       +        if (read(fd, b, 1) > 0) {
       +          rnd_add(b, 1);
       +          bytes++;
       +        }
       +      }
       +      if (isatty(fileno(stdin))) {
       +        fprintf(stderr, "Thanks.\n");
       +        sleep(1);
       +        kbd_echo();
       +      }
       +      close(fd);
       +    }
       +  }
       +#endif /* DEV_RANDOM */
       +  rnd_state = RND_SEEDED;
       +  return (0);
       +}
   DIR diff --git a/Src/service.c b/Src/service.c
       t@@ -0,0 +1,331 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Win32 Service support
       +   $Id: service.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include <windows.h>
       +#include <stdio.h>
       +#include <direct.h>
       +#include <io.h>
       +#include <fcntl.h>
       +
       +#include "mix3.h"
       +
       +#ifdef WIN32SERVICE
       +
       +#define SVCNAME        "Mixmaster"
       +#define SVCDISPLAYNAME "Mixmaster Service"
       +
       +
       +/* internal variables */
       +static SERVICE_STATUS           ssStatus;
       +static SERVICE_STATUS_HANDLE    sshStatusHandle;
       +static BOOL                     not_service = FALSE;
       +
       +static HANDLE hThread = NULL;
       +static HANDLE hMustTerminate = NULL;
       +
       +/* internal function prototypes */
       +VOID WINAPI service_ctrl(DWORD ctrl_code);
       +VOID WINAPI service_main(DWORD argc, LPSTR *argv);
       +static DWORD service_run(void);
       +static void service_stop();
       +static int set_stdfiles();
       +static int install_service();
       +static int remove_service();
       +static int run_notservice(int argc, char **argv);
       +BOOL WINAPI console_ctrl_handler(DWORD ctrl_type);
       +static char *GetLastErrorText();
       +static BOOL send_status(DWORD current_state, DWORD exit_code, DWORD wait_hint, DWORD id);
       +static void event_log(DWORD id, char *eventmsg);
       +
       +int mix_main(int argc, char *argv[]);
       +
       +
       +int main(int argc, char *argv[])
       +{
       +    SERVICE_TABLE_ENTRY dispatchTable[] = {
       +        {SVCNAME, (LPSERVICE_MAIN_FUNCTION)service_main},
       +        {NULL,    NULL} };
       +
       +    if ((argc > 1) && ((argv[1][0] == '-') && (argv[1][1] == '-'))) {
       +        if (!_stricmp("install-svc", argv[1]+2))
       +            return install_service();
       +        else if (!_stricmp("remove-svc", argv[1]+2))
       +            return remove_service();
       +        else if (_stricmp("run-svc", argv[1]+2) && !is_nt_service())
       +            return run_notservice(argc, argv);
       +    } else if (!is_nt_service()) {
       +        return run_notservice(argc, argv);
       +    }
       +    printf("mix --install-svc   install the service\n");
       +    printf("mix --remove-svc    remove the service\n");
       +    printf("mix --run-svc       run as a service\n");
       +    printf("mix -h          view a summary of the command line options.\n");
       +
       +    printf("\nStartServiceCtrlDispatcher being called.\n" );
       +    printf("This may take several seconds.  Please wait.\n" );
       +    if (!StartServiceCtrlDispatcher(dispatchTable)) {
       +        printf("Service not started: StartServiceCtrlDispatcher failed.\n" );
       +        event_log(1000, "Service not started: StartServiceCtrlDispatcher failed");
       +    }
       +    return 0;
       +} /* main */
       +
       +
       +VOID WINAPI service_main(DWORD argc, LPSTR *argv)
       +{
       +    DWORD err = 0;
       +
       +    if (!(sshStatusHandle = RegisterServiceCtrlHandler(SVCNAME, service_ctrl)))
       +        return;
       +
       +    ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
       +    ssStatus.dwServiceSpecificExitCode = 0;
       +    if (send_status(SERVICE_START_PENDING, NO_ERROR, 1000, 1020))
       +        err = service_run();
       +
       +    send_status(SERVICE_STOPPED, err, 0, err ? 1030 : 30);
       +} /* service_main */
       +
       +
       +VOID WINAPI service_ctrl(DWORD ctrl_code)
       +{   /* Handle the requested control code. */
       +    if (ctrl_code == SERVICE_CONTROL_STOP || ctrl_code == SERVICE_CONTROL_SHUTDOWN)
       +        service_stop();
       +    else
       +        send_status(ssStatus.dwCurrentState, NO_ERROR, 0, 1040 + ctrl_code);
       +} /* service_ctrl */
       +
       +
       +static DWORD service_run(void)
       +{
       +    char filename[_MAX_PATH+1];
       +    char home[_MAX_PATH+1], *p;
       +    char *svc_argv[2] = {filename, "-D"};
       +
       +    if (!hMustTerminate)
       +        hMustTerminate = CreateEvent(NULL, FALSE, FALSE, NULL);
       +    set_nt_exit_event(hMustTerminate);
       +    DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(),
       +            &hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
       +
       +    GetModuleFileName(NULL , filename, _MAX_PATH);
       +    strcpy(home, filename);
       +    if (p = strrchr(home, '\\')) {
       +        *p = 0;
       +        chdir(home);
       +    }
       +
       +    if (!set_stdfiles()) {
       +        event_log(1010, "stdin|stdout|stderr not created");
       +        return ERROR_SERVICE_NOT_ACTIVE;
       +    }
       +
       +    send_status(SERVICE_RUNNING, NO_ERROR, 0, 1060);
       +    event_log(10, "Mixmaster Service started");
       +
       +    mix_main(2, svc_argv);
       +    return 0;
       +} /* service_run */
       +
       +
       +static void service_stop(void)
       +{
       +    send_status(SERVICE_STOP_PENDING, NO_ERROR, 5000, 1070);
       +    if (hMustTerminate) {
       +        SetEvent(hMustTerminate);
       +        if (WaitForSingleObject(hThread, 4500) == WAIT_TIMEOUT) {
       +            if (hThread) {
       +                TerminateThread(hThread, 0);
       +                event_log(1080, "Mixmaster Service terminated forcibly");
       +            }
       +        } else
       +            event_log(20, "Mixmaster Service stopped");
       +        CloseHandle(hMustTerminate);
       +        hMustTerminate = NULL;
       +    } else
       +        if (hThread)
       +            TerminateThread(hThread, 0);
       +    if (hThread)
       +        CloseHandle(hThread);
       +    hThread = NULL;
       +    ssStatus.dwCurrentState = SERVICE_STOPPED;
       +} /* service_stop */
       +
       +
       +static int set_stdfiles()
       +{ /* needed for _popen() */
       +    static DWORD std_handles[]={STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE};
       +    FILE *stdfile[]={stdin, stdout, stderr};
       +    HANDLE hStd;
       +    int fh, stf_fileno;
       +    FILE *fl;
       +
       +    AllocConsole();
       +    for (stf_fileno=0; stf_fileno<=2; stf_fileno++) {
       +        hStd = GetStdHandle(std_handles[stf_fileno]);
       +        if (hStd == INVALID_HANDLE_VALUE)
       +            return 0;
       +        fh = _open_osfhandle((long)std_handles[stf_fileno], (stf_fileno ? _O_WRONLY : _O_RDONLY ) | _O_BINARY);
       +        dup2(fh, stf_fileno);
       +        fl = _fdopen(stf_fileno, (stf_fileno ? "wcb" : "rcb" ));
       +        fflush(stdfile[stf_fileno]);
       +        memcpy(stdfile[stf_fileno], fl, sizeof(FILE));
       +    }
       +    return 1;
       +} /* set_stdfiles */
       +
       +
       +static BOOL send_status(DWORD current_state, DWORD exit_code, DWORD wait_hint, DWORD id)
       +{
       +    static DWORD dwCheckPoint = 1;
       +    BOOL ret_val;
       +
       +    if (not_service)
       +        return TRUE;
       +
       +    ssStatus.dwCurrentState = current_state;
       +    ssStatus.dwWin32ExitCode = exit_code;
       +    ssStatus.dwWaitHint = wait_hint;
       +    ssStatus.dwControlsAccepted = (current_state == SERVICE_START_PENDING) ?
       +        0 : SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
       +    ssStatus.dwCheckPoint = ((current_state == SERVICE_RUNNING) || (current_state == SERVICE_STOPPED)) ?
       +        0 : dwCheckPoint++;
       +
       +    if (!(ret_val = SetServiceStatus(sshStatusHandle, &ssStatus)))
       +        event_log(id, "SetServiceStatus failed");
       +    return ret_val;
       +} /* send_status */
       +
       +
       +static void event_log(DWORD id, char *eventmsg)
       +{
       +    HANDLE  hEventSource;
       +    char    *pStrings[2] = {"", eventmsg};
       +
       +    if (not_service)
       +        return;
       +
       +    if (id > 1000)
       +        pStrings[0] = GetLastErrorText();
       +
       +    if (!(hEventSource = RegisterEventSource(NULL, SVCNAME)))
       +        return;
       +    ReportEvent(hEventSource, (WORD)((id < 1000) ? EVENTLOG_SUCCESS : EVENTLOG_ERROR_TYPE),
       +        0, id, NULL, 2, 0, pStrings, NULL);
       +    DeregisterEventSource(hEventSource);
       +} /* event_log */
       +
       +
       +static int run_notservice(int argc, char ** argv)
       +{
       +    not_service = TRUE;
       +    return mix_main(argc, argv);
       +} /* run_notservice */
       +
       +
       +static int install_service()
       +{
       +    SC_HANDLE schService, schSCManager;
       +    char filename[_MAX_PATH+10];
       +
       +    if (GetModuleFileName(NULL, filename, _MAX_PATH) == 0) {
       +        printf("Unable to install Mixmaster Service: %s\n", GetLastErrorText());
       +        return 1;
       +    }
       +    strcat(filename, " --run-svc");
       +
       +    if (!(schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) {
       +        printf("OpenSCManager failed: %s\n", GetLastErrorText());
       +        return 1;
       +    }
       +    schService = CreateService(schSCManager, SVCNAME, SVCDISPLAYNAME,
       +        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
       +        filename, NULL, NULL, NULL, NULL, NULL);
       +
       +    if (schService) {
       +        printf("Mixmaster Service installed.\n");
       +        CloseServiceHandle(schService);
       +    } else {
       +        printf("CreateService failed: %s\n", GetLastErrorText());
       +    }
       +
       +    CloseServiceHandle(schSCManager);
       +    return 0;
       +} /* install_service */
       +
       +
       +static int remove_service()
       +{
       +    SC_HANDLE schService, schSCManager;
       +    int ret_val = 0;
       +
       +    if (!(schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) {
       +        printf("OpenSCManager failed: %s\n", GetLastErrorText());
       +        return 1;
       +    }
       +    if (!(schService = OpenService(schSCManager, SVCNAME, SERVICE_ALL_ACCESS))) {
       +        CloseServiceHandle(schSCManager);
       +        printf("OpenService failed: %s\n", GetLastErrorText());
       +        return 1;
       +    }
       +    /* try to stop the service */
       +    if (ControlService(schService, SERVICE_CONTROL_STOP, &ssStatus)) {
       +        printf("Stopping Mixmaster Service");
       +        do {
       +            sleep(1);
       +            printf(".");
       +            QueryServiceStatus(schService, &ssStatus);
       +        } while (ssStatus.dwCurrentState != SERVICE_STOP_PENDING);
       +
       +        if (ssStatus.dwCurrentState == SERVICE_STOPPED)
       +            printf("\nMixmaster Service stopped.\n");
       +        else
       +            printf("\n%Mixmaster Service failed to stop.\n");
       +    }
       +
       +    /* now remove the service */
       +    if (!DeleteService(schService)) {
       +        ret_val = 1;
       +        printf("DeleteService failed: %s\n", GetLastErrorText());
       +    } else
       +        printf("Mixmaster Service removed.\n");
       +
       +    CloseServiceHandle(schService);
       +    CloseServiceHandle(schSCManager);
       +    return ret_val;
       +} /* remove_service */
       +
       +
       +static char *GetLastErrorText()
       +{
       +    static char error_buf[256];
       +    DWORD dwRet, err;
       +    LPSTR lpszTemp = NULL;
       +
       +    dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
       +                          NULL, err=GetLastError(), LANG_NEUTRAL, (LPSTR)&lpszTemp, 0, NULL);
       +
       +    /* supplied buffer is not long enough */
       +    if (!dwRet || (256 < (long)dwRet+14))
       +        sprintf(error_buf, "Error (0x%x)", err);
       +    else {
       +        lpszTemp[lstrlen(lpszTemp)-2] = '\0';
       +        /* remove cr and newline character */
       +        sprintf(error_buf, "%s (0x%x)", lpszTemp, err);
       +    }
       +
       +    if (lpszTemp)
       +        LocalFree((HLOCAL)lpszTemp);
       +
       +    return error_buf;
       +} /* GetLastErrorText */
       +
       +#endif /* WIN32SERVICE */
   DIR diff --git a/Src/stats.c b/Src/stats.c
       t@@ -0,0 +1,442 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Remailer statistics
       +   $Id: stats.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +
       +#include "mix3.h"
       +#include <stdio.h>
       +#include <string.h>
       +#include <time.h>
       +
       +/* log that a message of type t has been received. Statistics for type 2
       +   messages are taken from the IDLOG instead of calling this function */
       +int stats_log(int t)
       +{
       +  FILE *f;
       +
       +  f = mix_openfile(STATS, "a");
       +  if (f == NULL) {
       +    errlog(ERRORMSG, "Can't open %s!\n", STATS);
       +    return (-1);
       +  }
       +  lock(f);
       +  fprintf(f, "%d 1 %ld\n", t, (long) time(NULL));
       +  unlock(f);
       +  fclose(f);
       +  return (0);
       +}
       +
       +/* log the current pool size after sending messages */
       +int stats_out(int pool)
       +{
       +  FILE *f;
       +
       +  if (REMAIL == 0)
       +    return (0); /* don't keep statistics for the client */
       +
       +  f = mix_openfile(STATS, "a");
       +  if (f == NULL) {
       +    errlog(ERRORMSG, "Can't open %s!\n", STATS);
       +    return (-1);
       +  }
       +  lock(f);
       +  fprintf(f, "p 1 %d %ld\n", pool, (long) time(NULL));
       +  unlock(f);
       +  fclose(f);
       +  return (0);
       +}
       +
       +int stats(BUFFER *b)
       +{
       +  FILE *s, *f;
       +  char line[LINELEN];
       +  long now, today, then;
       +  time_t t;
       +  long updated = 0, havestats = 0;
       +  int msgd[7][24], msg[7][80];
       +  /* 0 .. Unencrypted
       +   * 1 .. Type I PGP
       +   * 2 .. Mix
       +   *
       +   * 3 .. intermediate
       +   * 4 .. final hop mail
       +   * 5 .. final hop news
       +   * 6 .. randhopped (will get counted in intermediate again)
       +   */
       +  int poold[2][24], pool[2][80];
       +  int i, num, type, assigned, daysum;
       +  char c;
       +  idlog_t idbuf;
       +
       +  now = (time(NULL) / (60 * 60) + 1) * 60 * 60;
       +  today = (now / SECONDSPERDAY) * SECONDSPERDAY;
       +
       +  for (i = 0; i < 24; i++)
       +    msgd[0][i] = msgd[1][i] = msgd[2][i] = msgd[3][i] = msgd[4][i] = msgd[5][i] = msgd[6][i]= poold[0][i] = poold[1][i] = 0;
       +  for (i = 0; i < 80; i++)
       +    msg[0][i] = msg[1][i] = msg[2][i] = msg[3][i] = msg[4][i] = msg[5][i] = msg[6][i] = pool[0][i] = pool[1][i] = 0;
       +
       +  s = mix_openfile(STATS, "r");
       +  if (s != NULL) {
       +    lock(s);
       +    fscanf(s, "%ld", &updated);
       +    while (fgets(line, sizeof(line), s) != NULL) {
       +      switch (line[0]) {
       +      case '0':
       +      case '1':
       +      case '2':
       +      case '3':
       +      case '4':
       +      case '5':
       +      case '6':
       +        c = '\0';
       +        assigned = sscanf(line, "%d %d %ld %c", &type, &num, &then, &c);
       +        daysum = (assigned == 4 && c == 'd');
       +
       +        if (now - then < 0 || (daysum && today - then < 0))
       +          break;                /* keep memory consistent even if the time
       +                                   suddenly goes backwards :) */
       +        if (now - then < SECONDSPERDAY && !daysum)
       +          msgd[type][(now - then) / (60 * 60)] += num;
       +        else if (today - then < 80 * SECONDSPERDAY)
       +          msg[type][(today - then) / SECONDSPERDAY] += num;
       +        if (havestats == 0 || then < havestats)
       +          havestats = then;
       +        break;
       +      case 'p':
       +        c = '\0';
       +        assigned = sscanf(line, "p %d %d %ld %c", &num, &i, &then, &c);
       +        daysum = (assigned == 4 && c == 'd');
       +
       +        if (now - then < 0 || (daysum && today - then < 0))
       +          break;
       +        if (now - then < SECONDSPERDAY && !daysum) {
       +          poold[0][(now - then) / (60 * 60)] += num;
       +          poold[1][(now - then) / (60 * 60)] += i;
       +        } else if (today - then < 80 * SECONDSPERDAY) {
       +          pool[0][(today - then) / (24 * 60 * 60)] += num;
       +          pool[1][(today - then) / (24 * 60 * 60)] += i;
       +        }
       +        if (havestats == 0 || then < havestats)
       +          havestats = then;
       +        break;
       +      }
       +    }
       +    unlock(s);
       +    fclose(s);
       +  }
       +  f = mix_openfile(IDLOG, "rb");
       +  if (f != NULL) {
       +    while (fread(&idbuf, 1, sizeof(idlog_t), f) == sizeof(idlog_t)) {
       +      then = idbuf.time;
       +      if (then < updated || now - then < 0)
       +        continue;
       +      if (now - then < SECONDSPERDAY)
       +        msgd[2][(now - then) / (60 * 60)]++;
       +      else if (today - then < 80 * SECONDSPERDAY)
       +        msg[2][(today - then) / SECONDSPERDAY]++;
       +      if (havestats == 0 || then < havestats)
       +        havestats = then;
       +    }
       +    fclose(f);
       +  }
       +  if (havestats == 0) {
       +    if (b != NULL)
       +      errlog(NOTICE, "No statistics available.\n");
       +    return (-1);
       +  }
       +  s = mix_openfile(STATS, "w");
       +  if (s == NULL) {
       +    errlog(ERRORMSG, "Can't create %s!\n", STATS);
       +    return (-1);
       +  }
       +  lock(s);
       +  fprintf(s, "%ld\n", (long) time(NULL));        /* time of stats.log update */
       +  for (i = 0; i < 24; i++) {
       +    for (type = 0; type < 7; type++)
       +      if (msgd[type][i] > 0)
       +        fprintf(s, "%d %d %ld\n", type, msgd[type][i], now - i * 60 * 60);
       +    if (poold[0][i] > 0)
       +      fprintf(s, "p %d %d %ld\n", poold[0][i], poold[1][i], now - i * 60 * 60);
       +  }
       +  for (i = 0; i < 80; i++) {
       +    for (type = 0; type < 7; type++)
       +      if (msg[type][i] > 0)
       +        fprintf(s, "%d %d %ld d\n", type, msg[type][i],
       +                today - i * 24 * 60 * 60);
       +    if (pool[0][i] > 0)
       +      fprintf(s, "p %d %d %ld d\n", pool[0][i], pool[1][i],
       +              today - i * 24 * 60 * 60);
       +  }
       +  unlock(s);
       +  fclose(s);
       +  if (b != NULL) {
       +    struct tm *gt;
       +
       +    buf_sets(b, "Subject: Statistics for the ");
       +    buf_appends(b, SHORTNAME);
       +    buf_appends(b, " remailer\n\n");
       +
       +    buf_appends(b, "Number of messages in the past 24 hours:\n");
       +    t = now;
       +    gt = gmtime(&t);
       +    for (i = 23; i >= 0; i--) {
       +      buf_appendf(b, "   %2dh: ", (24 + gt->tm_hour - i) % 24);
       +      if (MIX) {
       +        if (PGP || UNENCRYPTED)
       +          buf_appends(b, "   Mix:");
       +        buf_appendf(b, "%4d", msgd[2][i]);
       +      }
       +      if (PGP)
       +        buf_appendf(b, "     PGP: %4d", msgd[1][i]);
       +      if (UNENCRYPTED)
       +        buf_appendf(b, "     Unencrypted:%4d", msgd[0][i]);
       +      if (poold[0][i] > 0)
       +        buf_appendf(b, "  [Pool size:%4d]", poold[1][i] / poold[0][i]);
       +#if 0
       +      else
       +        buf_appends(b, "  [ no remailing ]");
       +#endif /* 0 */
       +      buf_nl(b);
       +    }
       +    if ((today - havestats) / SECONDSPERDAY >= 1)
       +      buf_appends(b, "\nNumber of messages per day:\n");
       +    for ((i = (today - havestats) / SECONDSPERDAY) > 79 ? 79 : i;
       +         i >= 1; i--) {
       +      t = now - i * SECONDSPERDAY;
       +      gt = gmtime(&t);
       +      strftime(line, LINELEN, "%d %b: ", gt);
       +      buf_appends(b, line);
       +
       +      if (MIX) {
       +        if (PGP || UNENCRYPTED)
       +          buf_appends(b, "   Mix:");
       +        buf_appendf(b, "%4d", msg[2][i]);
       +      }
       +      if (PGP)
       +        buf_appendf(b, "     PGP: %4d", msg[1][i]);
       +      if (UNENCRYPTED)
       +        buf_appendf(b, "     Unencrypted:%4d", msg[0][i]);
       +      if (STATSDETAILS) {
       +        buf_appendf(b, "  Intermediate:%4d", msg[3][i]);
       +        buf_appendf(b, "  Mail:%4d", msg[4][i]);
       +        buf_appendf(b, "  Postings:%4d", msg[5][i]);
       +        if (MIDDLEMAN)
       +          buf_appendf(b, "  Randhopped:%4d", msg[6][i]);
       +      }
       +      if (pool[0][i] > 0)
       +        buf_appendf(b, "  [Pool size:%4d]", pool[1][i] / pool[0][i]);
       +#if 0
       +      else
       +        buf_appends(b, "  [ no remailing ]");
       +#endif /* 0 */
       +      buf_nl(b);
       +    }
       +  }
       +  return (0);
       +}
       +
       +int conf(BUFFER *out)
       +{
       +  FILE *f;
       +  BUFFER *b, *line;
       +  int flag = 0;
       +  REMAILER remailer[MAXREM];
       +  int pgpkeyid[MAXREM];
       +  int i, num;
       +  char tmpline[LINELEN];
       +
       +  b = buf_new();
       +  line = buf_new();
       +
       +  buf_sets(out, "Subject: Capabilities of the ");
       +  buf_appends(out, SHORTNAME);
       +  buf_appends(out, " remailer\n\n");
       +  buf_appends(out, remailer_type);
       +  buf_appends(out, VERSION);
       +  buf_nl(out);
       +
       +  if (MIX + PGP + UNENCRYPTED == 1)
       +    buf_appends(out, "Supported format:");
       +  else
       +    buf_appends(out, "Supported formats:\n");
       +  if (MIX)
       +    buf_appends(out, "   Mixmaster\n");
       +  if (PGP)
       +    buf_appends(out, "   Cypherpunk with PGP encryption\n");
       +  if (UNENCRYPTED)
       +    buf_appends(out, "   Cypherpunk (unencrypted)\n");
       +
       +  buf_appendf(out, "Pool size: %d\n", POOLSIZE);
       +  if (SIZELIMIT)
       +    buf_appendf(out, "Maximum message size: %d kB\n", SIZELIMIT);
       +
       +  /* display destinations to which delivery is explicitly permitted
       +     when in middleman mode (contents of DESTALLOW file.)  */
       +
       +  if (MIDDLEMAN) {
       +    f = mix_openfile(DESTALLOW, "r");
       +    if (f != NULL) {
       +      buf_read(b, f);
       +      fclose(f);
       +      while(buf_getline(b, line) != -1) {
       +        if (line->length > 0 && line->data[0] != '#') {
       +          if (flag == 0) {
       +            buf_appends(out, "In addition to other remailers, this remailer also sends mail to these\n addresses directly:\n");
       +            flag = 1;
       +          }
       +          buf_appendf(out, "   %b\n", line);
       +        }
       +      }
       +    }
       +  }
       +
       +  flag = 0;
       +  f = mix_openfile(HDRFILTER, "r");
       +  if (f != NULL) {
       +    buf_read(b, f);
       +    fclose(f);
       +    while(buf_getline(b, line) != -1)
       +      if (line->length > 0 && line->data[0] != '#') {
       +        if (flag == 0) {
       +          buf_appends(out, "The following header lines will be filtered:\n");
       +          flag = 1;
       +        }
       +        buf_appends(out, "   ");
       +        if (line->length > 3 && streq(line->data + line->length - 2, "/q")) {
       +          buf_append(out, line->data, line->length - 1);
       +          buf_appends(out, " => delete message");
       +        }
       +        else
       +          buf_cat(out, line);
       +        buf_nl(out);
       +      }
       +    buf_free(b);
       +  }
       +  flag = 0;
       +  b = readdestblk( );
       +  if ( b != NULL ) {
       +    while(buf_getline(b, line) != -1)
       +      if (line->length > 0 && !bufleft(line, "#") && !buffind(line, "@")) {
       +        /* mail addresses are not listed */
       +        if (flag == 0) {
       +          if (NEWS[0])
       +            buf_appends(out,
       +                        "The following newsgroups/domains are blocked:\n");
       +          else
       +            buf_appends(out, "The following domains are blocked:\n");
       +          flag = 1;
       +        }
       +        buf_appendf(out, "   %b\n", line);
       +      }
       +    if (flag == 0 && NEWS[0])
       +      buf_appends(out, "Note that other newsgroups may be unavailable at the remailer's news server.\n");
       +  }
       +
       +  buf_nl(out);
       +  conf_premail(out);
       +
       +  if (LISTSUPPORTED) {
       +   /* SUPPORTED CPUNK (TYPE I) REMAILERS
       +    * 0xDC7532F9        "Heex Remailer <remailer@xmailer.ods.org>"
       +    * 0x759ED311        "znar <ka5tkn@cox-internet.com>"
       +    *
       +    * SUPPORTED MIXMASTER (TYPE II) REMAILERS
       +    * aarg remailer@aarg.net 475f3f9fe8da22896c10082695a92c2d 2.9b33 C
       +    * anon mixmaster@anon.978.org 7384ba1eec585bfd7d2b0e9b307f0b1d 2.9b36 MCNm
       +    */
       +
       +    buf_nl(out);
       +#ifdef USE_PGP
       +    if (PGP) {
       +      buf_appends(out, "SUPPORTED CPUNK (TYPE I) REMAILERS\n");
       +      num = t1_rlist(remailer, NULL);
       +      pgp_rkeylist(remailer, pgpkeyid, num);
       +      for (i=1; i<=num; i++) {
       +        if (remailer[i].flags.pgp) {
       +          snprintf(tmpline, LINELEN, "0x%08X        \"%s <%s>\"\n", pgpkeyid[i], remailer[i].name, remailer[i].addr);
       +          tmpline[LINELEN-1] = '\0';
       +          buf_appends(out, tmpline);
       +        }
       +      }
       +      buf_nl(out);
       +    }
       +#endif /* USE_PGP */
       +    if (MIX) {
       +      buf_appends(out, "SUPPORTED MIXMASTER (TYPE II) REMAILERS\n");
       +      prepare_type2list(out);
       +      buf_nl(out);
       +    }
       +  }
       +
       +
       +  if ( b ) buf_free(b);
       +  buf_free(line);
       +  return (0);
       +}
       +
       +void conf_premail(BUFFER *out)
       +{
       +  buf_appends(out, "$remailer{\"");
       +  buf_appends(out, SHORTNAME);
       +  buf_appends(out, "\"} = \"<");
       +  buf_appends(out, REMAILERADDR);
       +  buf_appendc(out, '>');
       +  if (PGP || UNENCRYPTED)
       +    buf_appends(out, " cpunk max");
       +  if (MIX)
       +    buf_appends(out, " mix");
       +  if (MIDDLEMAN)
       +    buf_appends(out, " middle");
       +  if (PGP)
       +    buf_appends(out, " pgp");
       +  if (PGP && !UNENCRYPTED)
       +    buf_appends(out, " pgponly");
       +  if (PGP && REPGP) {
       +    if (REMIX == 1)
       +      buf_appends(out, " repgp");
       +    else
       +      buf_appends(out, " repgp2");
       +  }
       +  if (REMIX == 1)
       +    buf_appends(out, " remix");
       +  else if (REMIX)
       +    buf_appends(out, " remix2");
       +  if (PGP || UNENCRYPTED)
       +    buf_appends(out, " latent hash cut test");
       +  if (PGP) {
       +#ifdef USE_IDEA
       +    buf_appends(out, " ek");
       +#endif /* USE_IDEA */
       +    buf_appends(out, " ekx");
       +  }
       +#ifdef USE_IDEA
       +  buf_appends(out, " esub");
       +#endif /* USE_IDEA */
       +#if 0                                /* obsolete */
       +#ifdef USE_NSUB
       +  buf_appends(out, " nsub");
       +#else /* end of USE_NSUB */
       +  buf_appends(out, " ksub");
       +#endif /* else if not USE_NSUB */
       +#endif /* 0 */
       +  if (INFLATEMAX)
       +    buf_appendf(out, " inflt%d", INFLATEMAX);
       +  if (MAXRANDHOPS)
       +    buf_appendf(out, " rhop%d", MAXRANDHOPS);
       +  if (POOLSIZE >= 5)
       +    buf_appends(out, " reord");
       +  if (NEWS[0])
       +    buf_appends(out, " post");
       +  if (SIZELIMIT)
       +    buf_appendf(out, " klen%d", SIZELIMIT);
       +  if (EXTFLAGS[0])
       +    buf_appendf(out, " %s", EXTFLAGS);
       +  buf_appends(out, "\";\n");
       +}
   DIR diff --git a/Src/tests/test-parse_yearmonthday.c b/Src/tests/test-parse_yearmonthday.c
       t@@ -0,0 +1,59 @@
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <time.h>
       +
       +#define LINELEN 128
       +
       +time_t parse_yearmonthday(char* str)
       +{
       +  time_t date;
       +  int day, month, year;
       +
       +  if (sscanf( str, "%d-%d-%d", &year, &month, &day) == 3 ) {
       +    struct tm timestruct;
       +    char *tz;
       +
       +    tz = getenv("TZ");
       +#ifdef HAVE_SETENV
       +    setenv("TZ", "GMT", 1);
       +#else /* end of HAVE_SETENV */
       +    putenv("TZ=GMT");
       +#endif /* else if not HAVE_SETENV */
       +    tzset();
       +    memset(&timestruct, 0, sizeof(timestruct));
       +    timestruct.tm_mday = day;
       +    timestruct.tm_mon = month - 1;
       +    timestruct.tm_year = year - 1900;
       +    date = mktime(&timestruct);
       +#ifdef HAVE_SETENV
       +    if (tz)
       +      setenv("TZ", tz, 1);
       +    else
       +      unsetenv("TZ");
       +#else  /* end of HAVE_SETENV */
       +    if (tz) {
       +      char envstr[LINELEN];
       +      snprintf(envstr, LINELEN, "TZ=%s", tz);
       +      putenv(envstr);
       +    } else
       +      putenv("TZ=");
       +#endif /* else if not HAVE_SETENV */
       +    tzset();
       +    return date;
       +  } else
       +    return -1;
       +}
       +
       +int main()
       +{
       +        int t;
       +        
       +        t = parse_yearmonthday("2003-04-02");
       +        if (t == 1049241600) {
       +                printf("OK.\n");
       +                exit(0);
       +        } else {
       +                printf("Failed.\n");
       +                exit(1);
       +        }
       +}
   DIR diff --git a/Src/util.c b/Src/util.c
       t@@ -0,0 +1,704 @@
       +/* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
       +
       +   Mixmaster may be redistributed and modified under certain conditions.
       +   This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +   ANY KIND, either express or implied. See the file COPYRIGHT for
       +   details.
       +
       +   Utility functions
       +   $Id: util.c 934 2006-06-24 13:40:39Z rabbi $ */
       +
       +#include "mix3.h"
       +#include <stdlib.h>
       +#include <string.h>
       +#include <ctype.h>
       +#include <fcntl.h>
       +#include <sys/types.h>
       +#include <sys/stat.h>
       +#ifdef POSIX
       +#include <signal.h>
       +#include <errno.h>
       +#include <unistd.h>
       +#include <sys/file.h>
       +#include <termios.h>
       +#else /* end of POSIX */
       +#include <io.h>
       +#endif /* else if not POSIX */
       +#ifdef HAVE_GETKEY
       +#include <pc.h>
       +#endif /* HAVE_GETKEY */
       +#include <assert.h>
       +
       +/** string comparison functions. return 1 on match, 0 otherwise ********/
       +
       +int strileft(const char *string, const char *keyword)
       +{
       +  register unsigned int i;
       +
       +  for (i = 0; keyword[i] != '\0'; i++)
       +    if (tolower(string[i]) != tolower(keyword[i]))
       +      return 0;
       +  return 1;
       +}
       +
       +int striright(const char *string, const char *keyword)
       +{
       +  int l;
       +  l = strlen(string) - strlen(keyword);
       +  return (l >= 0 ? strieq(string + l, keyword) : -1);
       +}
       +
       +int strleft(const char *string, const char *keyword)
       +{
       +  register unsigned int i;
       +
       +  for (i = 0; keyword[i] != '\0'; i++)
       +    if (string[i] != keyword[i])
       +      return 0;
       +  return 1;
       +}
       +
       +int strifind(const char *string, const char *keyword)
       +{
       +  register unsigned int i, j;
       +  char k;
       +
       +  k = tolower(keyword[0]);
       +  for (i = 0; string[i] != '\0'; i++) {
       +    if (tolower(string[i]) == k) {
       +      for (j = 1; keyword[j] != '\0'; j++)
       +        if (tolower(string[i + j]) != tolower(keyword[j]))
       +          goto next;
       +      return 1;
       +    }
       +  next:
       +    ;
       +  }
       +  return 0;
       +}
       +
       +int strieq(const char *s1, const char *s2)
       +{
       +  register unsigned int i = 0;
       +
       +  do
       +    if (tolower(s1[i]) != tolower(s2[i]))
       +      return 0;
       +  while (s1[i++] != '\0') ;
       +  return 1;
       +}
       +
       +int streq(const char *a, const char *b)
       +{
       +  return (strcmp(a, b) == 0);
       +}
       +
       +int strfind(const char *a, const char *keyword)
       +{
       +  return (strstr(a, keyword) != NULL);
       +}
       +
       +void strcatn(char *dest, const char *src, int n)
       +{
       +  int l;
       +  l = strlen(dest);
       +  if (l < n)
       +    strncpy(dest + l, src, n - l - 1);
       +  dest[n-1] = '\0';
       +}
       +
       +/** files **************************************************************/
       +
       +int mixfile(char *path, const char *name)
       +{
       +  char *h;
       +  assert(path != NULL && name != NULL);
       +
       +#ifdef POSIX
       +  if (name[0] == '~' && name[1] == DIRSEP && (h = getenv("HOME")) != NULL) {
       +    strncpy(path, h, PATHMAX);
       +    path[PATHMAX-1] = '\0';
       +    strcatn(path, name + 1, PATHMAX);
       +  } else
       +#endif /* POSIX */
       +  if (name[0] == DIRSEP || (isalpha(name[0]) && name[1] == ':') || MIXDIR == NULL) {
       +    strncpy(path, name, PATHMAX);
       +    path[PATHMAX-1] = '\0';
       +  } else {
       +    strncpy(path, MIXDIR, PATHMAX);
       +    path[PATHMAX-1] = '\0';
       +    strcatn(path, name, PATHMAX);
       +  }
       +  return (0);
       +}
       +
       +FILE *mix_openfile(const char *name, const char *a)
       +{
       +  char path[PATHMAX];
       +
       +  mixfile(path, name);
       +  return (fopen(path, a));
       +}
       +
       +FILE *openpipe(const char *prog)
       +{
       +  FILE *p = NULL;
       +
       +#ifdef POSIX
       +  p = popen(prog, "w");
       +#endif /* POSIX */
       +#ifdef _MSC
       +  p = _popen(prog, "w");
       +#endif /* _MSC */
       +
       +  if (p == NULL)
       +    errlog(ERRORMSG, "Unable to open pipe to %s\n", prog);
       +  return p;
       +}
       +
       +int
       +file_to_out(const char *filename)
       +{
       +    int len;
       +    FILE *fp;
       +    char chunk[1024];
       +
       +    if ((fp = mix_openfile(filename, "r")) == NULL)
       +            return -1;
       +    while ((len = fread(chunk, 1, sizeof(chunk), fp)) > 0)
       +            {
       +            fwrite(chunk, 1, len, stdout);
       +        }
       +    fclose (fp);
       +    return (len == 0 ? 0 : (-1));
       +}
       +
       +int closepipe(FILE *p)
       +{
       +#ifdef POSIX
       +  return (pclose(p));
       +#elif defined(_MSC) /* end of POSIX */
       +  return (_pclose(p));
       +#else /* end of defined(_MSC) */
       +  return -1;
       +#endif /* else if not defined(_MSC), POSIX */
       +}
       +
       +/** Base 64 encoding ****************************************************/
       +
       +static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
       +static byte asctobin[] =
       +{
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0076, 0x80, 0x80, 0x80, 0077,
       +  0064, 0065, 0066, 0067, 0070, 0071, 0072, 0073,
       +  0074, 0075, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0000, 0001, 0002, 0003, 0004, 0005, 0006,
       +  0007, 0010, 0011, 0012, 0013, 0014, 0015, 0016,
       +  0017, 0020, 0021, 0022, 0023, 0024, 0025, 0026,
       +  0027, 0030, 0031, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0032, 0033, 0034, 0035, 0036, 0037, 0040,
       +  0041, 0042, 0043, 0044, 0045, 0046, 0047, 0050,
       +  0051, 0052, 0053, 0054, 0055, 0056, 0057, 0060,
       +  0061, 0062, 0063, 0x80, 0x80, 0x80, 0x80, 0x80,
       +
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
       +  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
       +};
       +
       +void id_encode(byte id[], byte *s)
       +{
       +  sprintf
       +    (s, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
       +     id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9],
       +     id[10], id[11], id[12], id[13], id[14], id[15]);
       +}
       +
       +void id_decode(byte *s, byte id[])
       +{
       +  int i, x[16];
       +
       +  sscanf
       +    (s, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
       +     x, x + 1, x + 2, x + 3, x + 4, x + 5, x + 6, x + 7, x + 8,
       +     x + 9, x + 10, x + 11, x + 12, x + 13, x + 14, x + 15);
       +  for (i = 0; i < 16; i++)
       +    id[i] = x[i];
       +}
       +
       +int encode(BUFFER *in, int linelen)
       +{
       +  byte *b, *e;
       +  int i, l, m;
       +  unsigned long u;
       +  BUFFER *out;
       +
       +  out = buf_new();
       +
       +  l = in->length;
       +  if (l % 3 != 0)
       +    l += 2;
       +  l = l / 3 * 4;
       +
       +  if (linelen) {
       +    l += l / linelen + (l % linelen > 0 ? 1 : 0);
       +  }
       +  linelen /= 4;                        /* blocks of 4 characters */
       +
       +  buf_prepare(out, l);
       +
       +  b = in->data;
       +  e = out->data;
       +  m = in->length - 2;
       +  for (i = 0, l = 0; i < m; i += 3) {
       +    u = ((unsigned long) b[i] << 16) | ((unsigned long) b[i + 1] << 8) |
       +        b[i + 2];
       +    *e++ = bintoasc[(u >> 18) & 0x3f];
       +    *e++ = bintoasc[(u >> 12) & 0x3f];
       +    *e++ = bintoasc[(u >> 6) & 0x3f];
       +    *e++ = bintoasc[u & 0x3f];
       +    if (linelen && ++l >= linelen) {
       +      l = 0;
       +      *e++ = '\n';
       +    }
       +  }
       +  if (i < in->length) {
       +    *e++ = bintoasc[b[i] >> 2];
       +    *e++ = bintoasc[((b[i] << 4) & 0x30) | ((b[i + 1] >> 4) & 0x0f)];
       +    if (i + 1 == in->length)
       +      *e++ = '=';
       +    else
       +      *e++ = bintoasc[((b[i + 1] << 2) & 0x3c) | ((b[i + 2] >> 6) & 0x03)];
       +    *e++ = '=';
       +    ++l;
       +  }
       +  if (linelen && l != 0)
       +    *e++ = '\n';
       +  *e = '\0';
       +
       +  assert(out->data + out->length == e);
       +  buf_move(in, out);
       +  buf_free(out);
       +  return (0);
       +}
       +
       +int decode(BUFFER *in, BUFFER *out)
       +{
       +  int err = 0;
       +  register byte c0 = 0, c1 = 0, c2 = 0, c3 = 0;
       +  register byte *a, *d, *end;
       +  int tempbuf = 0;
       +  int i;
       +
       +  if (in == out) {
       +    out = buf_new();
       +    tempbuf = 1;
       +  }
       +  buf_prepare(out, 3 * (in->length - in->ptr) / 4);
       +
       +  a = in->data + in->ptr;
       +  end = in->data + in->length - 3;
       +  d = out->data;
       +  i = 0;
       +
       +  while (a < end) {
       +    if ((c0 = asctobin[a[0]]) & 0x80 ||
       +        (c1 = asctobin[a[1]]) & 0x80 ||
       +        (c2 = asctobin[a[2]]) & 0x80 ||
       +        (c3 = asctobin[a[3]]) & 0x80) {
       +      if (a[0] == '\n') {        /* ignore newline */
       +        a++;
       +        continue;
       +      } else if (a[0] == '\r' && a[1] == '\n') {        /* ignore crlf */
       +        a += 2;
       +        continue;
       +      } else if (a[0] == '=' && a[1] == '4' && a[2] == '6' && !(asctobin[a[5]] & 0x80) ) {
       +        a += 2;                        /* '=46' at the left of a line really is 'F' */
       +        *a = 'F';                /* fix in memory ... */
       +        continue;
       +      } else if (a[2] == '=' || a[3] == '=') {
       +        if (a[0] & 0x80 || (c0 = asctobin[a[0]]) & 0x80 ||
       +            a[1] & 0x80 || (c1 = asctobin[a[1]]) & 0x80)
       +          err = -1;
       +        else if (a[2] == '=')
       +          c2 = 0, i += 1;
       +        else if (a[2] & 0x80 || (c2 = asctobin[a[2]]) & 0x80)
       +          err = -1;
       +        else
       +          i += 2;
       +        if (err == 0) {
       +          /* read the correct final block */
       +          *d++ = (byte) ((c0 << 2) | (c1 >> 4));
       +          *d++ = (byte) ((c1 << 4) | (c2 >> 2));
       +          if (a[3] != '=')
       +            *d++ = (byte) ((c2 << 6));
       +#if 1
       +          if (a + 4 < in->data + in->length) {
       +            a += 4;
       +            continue;                /* support Mixmaster 2.0.3 encoding */
       +          }
       +#endif /* 1 */
       +          break;
       +        }
       +      }
       +      err = -1;
       +      break;
       +    }
       +    a += 4;
       +
       +    *d++ = (byte) ((c0 << 2) | (c1 >> 4));
       +    *d++ = (byte) ((c1 << 4) | (c2 >> 2));
       +    *d++ = (byte) ((c2 << 6) | c3);
       +    i += 3;
       +  }
       +
       +  in->ptr = a - in->data;
       +
       +  assert(i <= out->length);
       +  out->length = i;
       +
       +  if (tempbuf) {
       +    buf_move(in, out);
       +    buf_free(out);
       +  }
       +  return (err);
       +}
       +
       +LOCK *lockfile(char *filename)
       +{
       +  LOCK *l;
       +  char name[LINELEN];
       +
       +  strcpy(name, "lck");
       +  if (strchr(filename, DIRSEP))
       +    strcatn(name, strrchr(filename, DIRSEP), LINELEN);
       +  else
       +    strcatn(name, filename, LINELEN);
       +  l = malloc(sizeof(LOCK));
       +
       +  l->name = malloc(PATHMAX);
       +  mixfile(l->name, name);
       +  l->f = mix_openfile(l->name, "w+");
       +  if (l->f)
       +    lock(l->f);
       +  return (l);
       +}
       +
       +int unlockfile(LOCK *l)
       +{
       +  if (l->f) {
       +    unlock(l->f);
       +    fclose(l->f);
       +  }
       +  unlink(l->name);
       +  free(l->name);
       +  free(l);
       +  return (0);
       +}
       +
       +int lock(FILE *f)
       +{
       +#ifndef WIN32
       +  struct flock lockstruct;
       +
       +  lockstruct.l_type = F_WRLCK;
       +  lockstruct.l_whence = 0;
       +  lockstruct.l_start = 0;
       +  lockstruct.l_len = 0;
       +  return (fcntl(fileno(f), F_SETLKW, &lockstruct));
       +#else /* end of WIN32 */
       +  return (0);
       +#endif /* else if not WIN32 */
       +}
       +
       +int unlock(FILE *f)
       +{
       +#ifndef WIN32
       +
       +  struct flock lockstruct;
       +
       +  lockstruct.l_type = F_UNLCK;
       +  lockstruct.l_whence = 0;
       +  lockstruct.l_start = 0;
       +  lockstruct.l_len = 0;
       +  return (fcntl(fileno(f), F_SETLKW, &lockstruct));
       +#else /* end of not WIN32 */
       +  return (0);
       +#endif /* else if WIN32 */
       +}
       +
       +/* get passphrase ******************************************************/
       +
       +static int getuserpass(BUFFER *b, int mode)
       +{
       +  char p[LINELEN];
       +  int fd;
       +  int n;
       +
       +#ifdef HAVE_TERMIOS
       +  struct termios attr;
       +
       +#endif /* HAVE_TERMIOS */
       +
       +  if (mode == 0)
       +    fprintf(stderr, "enter passphrase: ");
       +  else
       +    fprintf(stderr, "re-enter passphrase: ");
       +  fflush(stderr);
       +#ifndef UNIX
       +#ifdef HAVE_GETKEY
       +  for (n = 0; p[n] != '\n' && n < LINELEN; n++) {
       +    p[n] = getkey();
       +  }
       +  p[n] = 0;
       +#else /* end of HAVE_GETKEY */
       +  scanf("%127s", p);
       +#endif /* else if not HAVE_GETKEY */
       +#else /* end of not UNIX */
       +  fd = open("/dev/tty", O_RDONLY);
       +  if (tcgetattr(fd, &attr) != 0)
       +    return (-1);
       +  attr.c_lflag &= ~ECHO;
       +  attr.c_lflag |= ICANON;
       +  if (tcsetattr(fd, TCSAFLUSH, &attr) != 0)
       +    return (-1);
       +
       +  n = read(fd, p, LINELEN);
       +
       +  attr.c_lflag |= ECHO;
       +  if (tcsetattr(fd, TCSAFLUSH, &attr) != 0)
       +    return (-1);
       +
       +  close(fd);
       +  fprintf(stderr, "\n");
       +  p[n - 1] = 0;
       +#endif /* else if UNIX */
       +  if (mode == 0)
       +    buf_appends(b, p);
       +  else
       +    return (bufeq(b, p));
       +  return (0);
       +}
       +
       +static BUFFER *userpass = NULL;
       +
       +int user_pass(BUFFER *key)
       +{
       +  if (userpass == NULL) {
       +    userpass = buf_new();
       +    userpass->sensitive = 1;
       +    if (getenv("MIXPASS"))
       +      buf_sets(userpass, getenv("MIXPASS"));
       +    else if (menu_getuserpass(userpass, 0) == -1)
       +      getuserpass(userpass, 0);
       +  }
       +  buf_set(key, userpass);
       +  key->sensitive = 1;
       +  return (0);
       +}
       +
       +int user_confirmpass(BUFFER *key)
       +{
       +  int ok;
       +
       +  ok = menu_getuserpass(key, 1);
       +  if (ok == -1)
       +    ok = getuserpass(key, 1);
       +  return (ok);
       +}
       +
       +void user_delpass(void)
       +{
       +  if (userpass)
       +    buf_free(userpass);
       +  userpass = NULL;
       +}
       +
       +int write_pidfile(char *pidfile)
       +{
       +  int err = 0;
       +#ifdef POSIX
       +  FILE *f;
       +  char host[LINELEN], myhostname[LINELEN];
       +  int pid, mypid;
       +  int assigned;
       +
       +  mypid = getpid();
       +  gethostname(myhostname, LINELEN);
       +  myhostname[LINELEN-1] = '\0';
       +
       +  f = mix_openfile(pidfile, "r+");
       +  if (f != NULL) {
       +    assert(LINELEN > 71);
       +    assigned = fscanf(f, "%d %70s", &pid, host);
       +    if (assigned == 2) {
       +      if (strcmp(host, myhostname) == 0) {
       +        if (kill (pid, 0) == -1) {
       +          if (errno == ESRCH) {
       +            fprintf(stderr, "Rewriting stale pid file.\n");
       +            rewind(f);
       +            ftruncate(fileno(f), 0);
       +            fprintf(f, "%d %s\n", mypid, myhostname);
       +          } else {
       +            fprintf(stderr, "Pid file exists and process still running.\n");
       +            err = -1;
       +          }
       +        } else {
       +          fprintf(stderr, "Pid file exists and process still running.\n");
       +          err = -1;
       +        }
       +      } else {
       +        /* Pid file was written on another host, fail */
       +        fprintf(stderr, "Pid file exists and was created on another host (%s).\n", host);
       +        err = -1;
       +      }
       +    } else {
       +      fprintf(stderr, "Pid file exists and and could not be parsed.\n");
       +      err = -1;
       +    }
       +  } else {
       +    if (errno == ENOENT) {
       +      f = mix_openfile(pidfile, "w+");
       +      if (f != NULL) {
       +        fprintf(f, "%d %s\n", mypid, myhostname);
       +      } else {
       +        fprintf(stderr, "Could not open pidfile for writing: %s\n", strerror(errno));
       +        err = -1;
       +      }
       +    } else {
       +      fprintf(stderr, "Could not open pidfile for readwrite: %s\n", strerror(errno));
       +      err = -1;
       +    };
       +  }
       +  if(f)
       +    fclose(f);
       +#endif /* POSIX */
       +  return (err);
       +}
       +
       +int clear_pidfile(char *pidfile)
       +{
       +#ifdef POSIX
       +  char path[PATHMAX];
       +
       +  mixfile(path, pidfile);
       +  return (unlink(path));
       +#else /* end of POSIX */
       +  return (0);
       +#endif /* else if not POSIX */
       +}
       +
       +time_t parse_yearmonthday(char* str)
       +{
       +  time_t date;
       +  int day, month, year;
       +
       +  if (sscanf( str, "%d-%d-%d", &year, &month, &day) == 3 ) {
       +    struct tm timestruct;
       +    char *tz;
       +
       +    tz = getenv("TZ");
       +#ifdef HAVE_SETENV
       +    setenv("TZ", "GMT", 1);
       +#else /* end of HAVE_SETENV */
       +    putenv("TZ=GMT");
       +#endif /* else if not HAVE_SETENV */
       +    tzset();
       +    memset(&timestruct, 0, sizeof(timestruct));
       +    timestruct.tm_mday = day;
       +    timestruct.tm_mon = month - 1;
       +    timestruct.tm_year = year - 1900;
       +    date = mktime(&timestruct);
       +#ifdef HAVE_SETENV
       +    if (tz)
       +      setenv("TZ", tz, 1);
       +    else
       +      unsetenv("TZ");
       +#else  /* end of HAVE_SETENV */
       +    if (tz) {
       +      char envstr[LINELEN];
       +      snprintf(envstr, LINELEN, "TZ=%s", tz);
       +      putenv(envstr);
       +    } else
       +      putenv("TZ=");
       +#endif /* else if not HAVE_SETENV */
       +    tzset();
       +    return date;
       +  } else
       +    return -1;
       +}
       +
       +/* functions missing on some systems *************************************/
       +
       +#ifdef __RSXNT__
       +int fileno(FILE *f)
       +{
       +  return (f->_handle);
       +}
       +
       +#endif /* __RSXNT__ */
       +
       +#ifdef _MSC        /* Visual C lacks dirent */
       +
       +DIR *opendir(const char *name)
       +{
       +  DIR *dir;
       +  WIN32_FIND_DATA d;
       +  char path[PATHMAX];
       +
       +  dir = malloc(sizeof(HANDLE));
       +
       +  sprintf(path, "%s%c*", name, DIRSEP);
       +  *dir = FindFirstFile(path, &d);
       +  /* first file found is "." -- can be safely ignored here */
       +
       +  if (*dir == INVALID_HANDLE_VALUE) {
       +    free(dir);
       +    return (NULL);
       +  } else
       +    return (dir);
       +}
       +
       +struct dirent e;
       +struct dirent *readdir(DIR *dir)
       +{
       +  WIN32_FIND_DATA d;
       +  int ok;
       +
       +  ok = FindNextFile(*dir, &d);
       +  if (ok) {
       +    strncpy(e.d_name, d.cFileName, PATHMAX);
       +    return (&e);
       +  } else
       +    return (NULL);
       +}
       +
       +int closedir(DIR *dir)
       +{
       +  if (dir) {
       +    FindClose(*dir);
       +    free(dir);
       +    return (0);
       +  }
       +  return (-1);
       +}
       +
       +#endif /* _MSC */
   DIR diff --git a/Src/version.h b/Src/version.h
       t@@ -0,0 +1 @@
       +#define VERSION "3.0"
   DIR diff --git a/THANKS b/THANKS
       t@@ -0,0 +1,102 @@
       +Mixmaster Version 3.0
       +
       +As I write this, Mixmaster is over a decade old. This incarnation of the
       +codebase was begun almost exactly 10 years ago, and the idea conceived
       +nearly half that again. Despite many changes in the social, political,
       +legal, and technological landscape, Mixmaster has continuously provided
       +anonymity services to those who need it throughout this time. 
       +
       +Many people have helped with the development of Mixmaster during its
       +long history. Lance Cottrell wrote the original 1.x and 2.0.x versions. 
       +Ulf Möller contributed significantly to the 2.0.x versions, and wrote
       +the core code for 2.9 from scratch. I'd like to give special thanks to
       +Peter Palfrader, Colin Tuckley, and Steve Crook. As the core members of
       +the Mixmaster development team, without their tireless efforts, this
       +project would not be sustainable.
       +
       +Additionally, I would like to honor the memory of a former valued member 
       +of the development team, Janis Jagars, whose work made this release 
       +possible, though sadly, he passed away tragically before it was 
       +completed. "Disastry", you are missed.
       +
       +Mixmaster uses Jean-loup Gailly and Mark Adler's compression library zlib,
       +Philip Hazel's Perl Compatible Regular Expressions library, the ncurses
       +library (originally written by Zeyd Ben-Halim and Eric Raymond), and
       +OpenSSL (based on work by Eric Young and Tim Hudson.)
       +
       +I have compiled below a partial list of people who have contributed to
       +Mixmaster's success, through suggestions, bug reports, patches, or other
       +contributions. Please report any omissions to me.
       +
       +There have been numerous anonymous contributions to this project as well.
       +While we obviously can't thank the contributor(s) by name, they are still
       +very much appreciated.
       +
       +Thanks also to all the remailer operators, who give their time and service
       +(and perform what is too often a thankless job) to ensure that our right
       +to anonymous speech is preserved.
       +
       +Finally, thank you to my colleagues at COSIC, and my advisors, Prof. 
       +Bart Preneel and Prof. David Chaum, for their support of my work on this 
       +project.
       +
       +
       +Len Sassaman
       +03 March 2008
       +Leuven, Belgium
       +http://homes.esat.kuleuven.be/~lsassama/
       +
       +
       +Credits:
       +
       +Antonomasia
       +Erik Arneson
       +Adam Back
       +Kevin Bennett
       +Gerd Beuster
       +Jim Castleberry
       +cmeclax
       +Bram Cohen
       +Steve Crook
       +Lance Cottrell
       +Richard Christman
       +Todd Cutter
       +Dingo Admin
       +Andy Dustman
       +Sami Farin
       +John B. Fleming
       +Bryan Fordham
       +Laurent Fousse
       +Ron Fritz
       +goblin
       +Mark Grant
       +Lucky Green
       +Mark Hahn
       +Janis Jagars
       +Richard Johnson
       +Alex de Joode
       +Katherine
       +Johannes Kroeger
       +Hauke Lampe
       +Ben Laurie
       +Patrick J. LoPresti
       +L. McCarthy
       +Medusa
       +Christian Mock
       +Bodo Möller
       +Ulf Möller
       +noise
       +Bill O'Hanlon
       +Peter Palfrader
       +John A. Perry
       +Scott Renfro
       +RProcess
       +Len Sassaman
       +Senshi-Admin
       +Markus Stöger
       +Nikolay Sturm
       +Trek
       +Rodney Thayer
       +Colin Tuckley
       +André M. VanKlaveren
       +Michael Young
   DIR diff --git a/TODO b/TODO
       t@@ -0,0 +1,77 @@
       +Items that need to be completed before the next MAIN release:
       +
       +- revert renaming of conf files for WIN32.
       +
       +Items to watch:
       +
       +- Hunt and kill bug in Mixmaster causing echolot pings to be turned
       +  into permanent t* files.
       +  [This is a pesky one. Changing the .forward pipe to go through 
       +   truss first 'fixes' it. Grr. --rabbi]
       +
       +Items for 3.0.x:
       +- doallow() should check more than one email address in a line
       +- Automatically fetch pinger list and stats during installation process
       +- destblk request confirmation (patch # 873498)
       +    + perhaps we should phase this out in favor of a distributed RAB?
       +- general bug fixes that do not break backward compatibility
       +
       +Items for 3.1.x
       +- Full WIN32 support.
       +  - Sane randomness handling
       +  - Resolve crash when running with --post
       +  - Resolve crash when config contains "SENDMAIL outfile"
       +  - Confirm operation as a WIN32 service
       +  - Test on Vista.
       +- Include a formal win32 binary release, complete with docs.
       +- Integrate RAB support -- automatic downloading similar to stats.
       +- Introduce hashed RAB handling where mail recipients are hashed and
       +  compared against a downloaded rab.hash file.  This solves the issue
       +  of publishing a plain-text list of email addresses.
       +    + We might want to salt these hashes but the salt would have to be
       +      known to remops.
       +- Hashcash support?
       +
       +Items for 3.5:
       +
       +- binomial mix implementation
       +- RGB dummies
       +- native echolot
       +- Regroup-and-Go?
       +
       +Packaging:
       +- Modify release tarball generation script to build the .tab.c file from
       +  parsedate.y, so we don't end up requiring bison on every system that
       +  wants to build mixmaster  (rabbi)
       +- rpm -- dybbuk
       +- Windows build instructions/files  (zax)
       +- provide a packaged Windows build to be used with QuickSilver
       +- Macintosh OS/X support  (rabbi)
       +- Update Install script to put files in global system locations if
       +  invoked by root. Also update to be smart about AES support.
       +  (dybbuk said he would do this, but status is unclear.)
       +
       +Wishlist:
       +- permit CRAM-MD5 SMTP AUTH in addition to LOGIN.  n/a (patch welcome)
       +- do full regression tests on as many platforms possible
       +  - list only these platforms as supported
       +  - test on Solaris 9 on SPARC.
       +- saner usage of /dev/[u]random is required -- throw warning when not in
       +  daemon mode (patch 873497 -- needs work)
       +- clean up documentation and tarball contents
       +  + reorganize directory structure
       +- AES support -- requires OpenSSL 0.9.7  dybbuk
       +
       +
       +Abandoned/Deferred:
       +D Remove OpenSSL version checks. Maybe print a message stating the 
       +  supported versions, and leave it up to the user?
       +D allow for verification of clearsigned OpenPGP messages  disastry
       +D honor key preferences when encrypting to multiple keys  ulf/disastry (n/a)
       +D further mpgp testing of AES/MDC packet support  ulf
       +D make mpgp friendlier
       +D COMMENT entire existing codebase!  (HAHA)
       +D support for Borland compiler on Windows.
       +  D I'ld even go so far as drop Visual C (or whatever we're supporting at
       +    the moment) and require gcc with Cygwin to build it. But only if this
       +    results in a Binary that runs without additional DLLs. (Weasel)
   DIR diff --git a/conf/abuse.txt.in b/conf/abuse.txt.in
       t@@ -0,0 +1,99 @@
       +Thank you for contacting the Abuse Complaint Administrator
       +of the %RMN.
       +
       +We sincerely apologize for any inconvenience that you may have
       +experienced as a result of inappropriate use of this system by a
       +particular individual.
       +
       +The purpose of this anonymous remailer is to permit individuals
       +including crime victims, domestic violence victims, persons in recovery,
       +and others, such as those living under oppressive regimes, to
       +communicate confidentially in a manner that ensures their privacy under
       +even the most adverse conditions. Unfortunately, there will always be a
       +very small percentage of individuals that choose to abuse the anonymity
       +that this and similar systems worldwide afford to insult, harass, or
       +send otherwise unwelcome email.
       +
       +The operator of this remailer does not condone such messages, or their
       +content, in any way.  
       +
       +Just as the Post Office is unable to prevent abuse of the mail system as
       +long as there are public mailboxes into which a person can drop a letter
       +without including a return address, this remailer cannot preemptively
       +prevent irresponsible individuals from using this system to send
       +inappropriate messages. However, unlike the Post Office, this remailer
       +enables you to assure that you will not be inconvenienced by users of
       +this remailer in the future.
       +=========================================================================
       +
       +How to block your email address from receiving email from the 
       +%RMN:
       +
       +To block the users of this remailer from sending email to your address,
       +please send a message to <%RMA>
       +containing the line
       +
       +DESTINATION-BLOCK
       +
       +anywhere in the body text of the email.  You can simply reply to this
       +message using your email program and send back this entire message for
       +your current email address to be permanently blocked from users of the
       +%RMN.
       +
       +If you wish to block additional email addresses that you may use from
       +receiving email though this remailer, please reply to this email with a
       +line similar to
       +
       +DESTINATION-BLOCK my_other_email_address@my_domain.com
       +
       +You must include one such line per email address that you wish to block.
       +You can include more than one line in your reply.
       +==========================================================================
       +
       +How to block an entire domain from receiving email from the 
       +%RMN:
       +
       +If you are the legitimate root administrator or postmaster of a domain,
       +you may request that all email addresses served by you domain are
       +blocked from receiving email from this remailer . To place this block,
       +please send the following line as "root" or "postmaster" to
       +<%RMA> in the body text of your email:
       +
       +DESTINATION-BLOCK @domain_to_be_blocked.com
       +
       +==========================================================================
       +Note that there are similar remailer systems in operation on the
       +Internet that not affiliated with the %RMN.
       +
       +Since the administrator of this remailer has no influence on those other
       +systems and is likely to be unaware of many of these other systems, a
       +destination block that you may choose to request by replying to this
       +email is only effective for the %RMN,
       +not for similar systems that may exist on the Internet.
       +
       +==========================================================================
       +
       +How to obtain the name of the sender of an email that you received
       +though this remailer:
       +
       +This remailer uses the Mixmaster anonymous remailer software. The
       +Mixmaster software has been carefully designed to withstand attack by
       +even the most severe regimes in which torture is a common means of
       +inquiry and basic human rights are nonexistent.  As such, it is
       +impossible to determine the original sender of an email that has passed
       +through this system.
       +
       +The administrator of this system is technically unable to determine the
       +original sender of a message that has passed through this remailer, no
       +matter how much the administrator may desire to do so, even if the
       +administrator were ordered to do so by legal or extra-legal means. We
       +regret any inconvenience this necessary safety protection may cause to
       +some recipients of undesired emails.
       +
       +Remember: you can prevent future unwanted emails sent to you via this
       +remailer by simply replying to this message.
       +
       +Sincerely,
       +
       +-- The %RMN Administrator
       +
   DIR diff --git a/conf/adminkey.txt b/conf/adminkey.txt
       t@@ -0,0 +1 @@
       +Remailer Administrator's key goes here.
   DIR diff --git a/conf/blocked.txt.in b/conf/blocked.txt.in
       t@@ -0,0 +1,20 @@
       +Subject: %RMN Blocking Confirmation 
       +Reply-To: Abuse Complaint Administrator <%CA>
       +
       +Thank you for contacting the Abuse Complaint Administrator of the
       +%RMN.
       +The administrator has processed your request to not receive emails from
       +this anonymous remailer. This remailer will no longer send emails to the
       +email address(es) for which you requested a block. Note that due to fact
       +that Internet email can arrive at the destination out-of-sequence, it is
       +possible, though unlikely, that you may receive emails from this
       +remailer that were sent prior to your blocking request, but have not yet
       +been received by you.
       +
       +We again wish to apologize for any inconvenience that may have been
       +caused to you.
       +
       +Sincerely,
       +
       +-- The %RMN Administrator
       + 
   DIR diff --git a/conf/dest.alw b/conf/dest.alw
       t@@ -0,0 +1,41 @@
       +## List of addresses to which Mixmaster will deliver, even in middleman mode
       +## Beware: substring matches
       +##
       +## $Id: dest.alw,v 1.3 2003/09/03 16:51:12 packbart Exp $
       +
       +
       +##
       +## allowed destinations
       +##
       +
       +## Allows mail to *@example.com
       +#/@example\.com$/
       +
       +## Matches *myaddress@example.net*
       +#myaddress@example.net
       +
       +## Allows direct posts to alt.test and alt.anonymous.messages
       +## (only mix posts unless mail2news@ is whitelisted, too)
       +#/^Newsgroups: +(alt\.test|alt\.anonymous\.messages)$/
       +
       +
       +##
       +## nymservers
       +##
       +
       +/@nym\.alias\.net$/
       +/@hod\.aarg\.net$/
       +/@blackhole\.riot\.eu\.org$/
       +/@nym\.cryptofortress\.com$/
       +/@nym\.xganon\.com$/
       +/@rodent\.frell\.eu\.org$/
       +
       +##
       +## presumably dead nymservers
       +##
       +
       +#/@redneck\.gacracker\.org$/
       +#/@anon\.nymserver\.com$/
       +#/@mailanon\.com$/
       +/@alias\.cyberpass\.net$/
       +
   DIR diff --git a/conf/dest.blk b/conf/dest.blk
       t@@ -0,0 +1,2 @@
       +president@whitehouse.gov
       +majordomo@
   DIR diff --git a/conf/end.hlp b/conf/end.hlp
       t@@ -0,0 +1,36 @@
       +Abuse Policy:
       +
       +Unfortunately, there will always be a very small percentage of
       +individuals that choose to abuse the anonymity that this and similar
       +systems worldwide afford to send otherwise unwelcome email. The
       +%RMN does not condone such messages, or their content,
       +in any way.
       +
       +Just as the Post Office is unable to prevent abuse of the mail system as
       +long as there are public mailboxes into which a person can drop a letter
       +without including a return address, the %RMN cannot preemptively
       +prevent irresponsible individuals from using this system to send
       +inappropriate messages. However, unlike the Post Office, this remailer
       +enables you to assure that you will not be inconvenienced by users of
       +this remailer in the future.
       +
       +To block the users of this remailer from sending email to your address,
       +please send a message to <%RMA>
       +containing the line
       +
       +DESTINATION-BLOCK
       +
       +anywhere in the body text of the email.  You can simply reply to this
       +message using your email program and send back this entire message for
       +your current email address to be permanently blocked from users of the
       +%RMN.
       +
       +For additional information on this remailer's abuse policy, instructions
       +on how to block more than one email address, and to reach the
       +%RMN operator, please send
       +email to <%CA>.
       +  
       +Thank you for your interest in secure and private communications,
       +
       +-- The %RMN Administrator
       +
   DIR diff --git a/conf/header.blk b/conf/header.blk
       t@@ -0,0 +1,22 @@
       +# Header lines to be filtered out.
       +
       +/^From:/
       +/^Sender:/
       +/^X-Sender:/
       +/^Resent-/
       +/^Approved:/
       +/^Errors-To:/
       +/^Message-ID:/
       +/^Comments: Authenticated sender is/
       +/^Path:/
       +/^Received:/
       +
       +/^Control: rmgroup/q
       +/^Control: newgroup/q
       +/^Control: sendsys/q
       +/^Control: checkgroups/q
       +/^Control: version/q
       +
       +# Don't allow excessive crossposting:
       +/^Newsgroups:.*,.*,.*,.*,.*,/q
       +
   DIR diff --git a/conf/intro.hlp b/conf/intro.hlp
       t@@ -0,0 +1,15 @@
       +Subject: Your help request for the %RMN
       +Reply-To: <%RMA>
       +
       +This message is sent to you in response to an email that you sent to
       +the %RMN.
       +This automated reply was trigged by the subject "remailer-help"
       +contained in your email. If you did not send such an email, please
       +ignore this message.
       +
       +This remailer is a free service that allows individuals including crime
       +victims, domestic violence victims, persons in recovery, and others,
       +such as those living under oppressive regimes, to communicate
       +confidentially in a manner that ensures their privacy under even the
       +most adverse conditions.
       +
   DIR diff --git a/conf/mix.cfg b/conf/mix.cfg
       t@@ -0,0 +1,14 @@
       +######################## Client configuration: ##########################
       +REMAIL          n
       +
       +#NAME           your realname
       +#ADDRESS        user@host
       +
       +SENDPOOLTIME        0h
       +CHAIN                *,*,*,*
       +NUMCOPIES        1
       +DISTANCE        2
       +MINREL                98
       +RELFINAL        99
       +MAXLAT                36h
       +MINLAT                5m
   DIR diff --git a/conf/mix.cfg.ex b/conf/mix.cfg.ex
       t@@ -0,0 +1,192 @@
       +## mix.cfg - Mixmaster configuration file
       +## see mixmaster(1) for a description
       +##
       +## All paths relative to compile-time defined SPOOL (default: ~/Mix)
       +## Can be overriden by environment variable $MIXPATH 
       +##
       +## $Id: mix.cfg.ex,v 1.4 2003/09/03 16:46:04 packbart Exp $
       +
       +####################### Remailer configuration: ###########################
       +
       +## Enable remailer functionality
       +REMAIL              y
       +
       +SHORTNAME           foo
       +REMAILERNAME        Anonymous Remailer
       +REMAILERADDR        mix@example.net
       +ANONNAME            Anonymous
       +#ANONADDR            nobody@example.net
       +#COMPLAINTS          abuse@example.net
       +
       +## Additional capstring flags (e.g.: testing filter mon)
       +#EXTFLAGS           testing
       +
       +## Act as an intermediate hop only, forward anonymized messages to
       +## another remailer
       +MIDDLEMAN           n
       +
       +## Supported formats:
       +MIX                 y
       +PGP                 n
       +UNENCRYPTED         n
       +
       +## Only disable these if you really know what they do
       +#REMIX               y
       +#REPGP               y
       +
       +## In middleman mode, mail is randhopped through this chain
       +#FORWARDTO           *
       +
       +## Filter binaries and replace them with "[...]"
       +## Note: destroys even PGP messages sometimes
       +BINFILTER           n
       +
       +## Allow users to add their address to the dest.blk file by sending the
       +## remailer a message containing the line "destination-block"
       +## Note: as no challenge-response mechanisms are used (yet),
       +##       attackers could dest-block arbitrary addresses
       +AUTOBLOCK           y
       +
       +## Automatically respond to non-remailer mail and mail to COMPLAINTS address
       +AUTOREPLY           n
       +
       +## List statistics on intermediate vs. final delivery in remailer-stats.
       +STATSDETAILS        y
       +
       +## List known remailers and their keys in remailer-conf reply
       +LISTSUPPORTED       y
       +
       +## Maximum chain length for message forwarding requested by
       +## Rand-Hop and Remix-To directives
       +MAXRANDHOPS         5
       +
       +## Maximum size for Inflate: padding in kB.  0 means padding is not allowed
       +INFLATEMAX          50
       +
       +## Limits the number of allowed recipients in outgoing mail
       +## Anything that exceeds this number is dropped silently
       +MAXRECIPIENTS       5
       +
       +## Passphrase to protect secret keys
       +#PASSPHRASE          raboof
       +
       +## Maximum message size in kB (0 for no limit):
       +SIZELIMIT           0
       +
       +## Remailing strategy:
       +MAILINTIME          5m
       +SENDPOOLTIME        15m
       +POOLSIZE            45
       +RATE                65
       +
       +## Dummy generation probabilities
       +INDUMMYP            10
       +OUTDUMMYP           90 
       +
       +## How long to store packet IDs and incomplete message parts
       +IDEXP               7d
       +PACKETEXP           7d
       +
       +## Client settings for Rand-Hop: directives and dummy messages
       +CHAIN               *,*,*,*
       +DISTANCE            2
       +MINREL              98
       +RELFINAL            99
       +MAXLAT              36h
       +MINLAT              5m
       +
       +## This file lists remailers which should not be used in randomly generated
       +## remailer chains
       +STAREX              starex.txt
       +
       +## Path to inews, or address of mail-to-news gateway
       +## Leave empty to disable mix-post capability flag
       +## Add more mail2news gateways to increase posting reliability
       +## (and mail load on your MTA). Additional m2n include:
       +## mail2news@news.gradwell.net
       +#NEWS                mail2news@dizum.com,mail2news@anon.lcs.mit.edu
       +ORGANIZATION        Anonymous Posting Service
       +
       +## Anti-spam message IDs on Usenet (MD5 of message body)?
       +MID                 y
       +
       +## Precedence: header to set on remailed messages
       +#PRECEDENCE          anon
       +
       +## Enable either SENDMAIL/SENDANONMAIL (pipe into sendmail program)
       +## or SMTPRELAY (SMTP delivery over TCP)
       +SENDMAIL            /usr/lib/sendmail -t
       +#SENDANONMAIL        sendmessage.sh
       +
       +#SMTPRELAY           smtp.example.net
       +#SMTPUSERNAME        foo
       +#SMTPPASSWORD        bar
       +#HELONAME            example.net
       +#ENVFROM             mix-bounce@example.net
       +
       +## Where to log error messages:
       +ERRLOG              error.log
       +VERBOSE             2
       +
       +## Where to read mail messages from
       +## trailing "/" indicates maildir-style folder
       +## leave empty when you feed mixmaster through stdin (e.g. from procmail)
       +#MAILIN              /var/mail/mixmaster
       +
       +## POP3 configuration
       +POP3CONF            pop3.cfg
       +POP3TIME            1h
       +POP3SIZELIMIT       0
       +POP3DEL             y
       +
       +## Where to store non-remailed messages
       +## prefix with "|" to pipe into program
       +## treated as email address if it contains an "@"
       +MAILBOX             mbox
       +#MAILABUSE           mbox.abuse
       +#MAILBLOCK           mbox.block
       +#MAILUSAGE           /dev/null
       +#MAILANON            /dev/null
       +#MAILERROR           /dev/null
       +#MAILBOUNCE          mbox.bounce
       +
       +## Where to find variable remailer keyrings and statistics
       +PGPREMPUBASC        pubring.asc
       +PUBRING             pubring.mix
       +TYPE1LIST           rlist.txt
       +TYPE2REL            mlist.txt
       +TYPE2LIST           type2.list
       +
       +## If you run your own pinger, make stats/ a symlink to your results directory
       +## and enable these instead
       +#PGPREMPUBASC        stats/pgp-all.asc
       +#PUBRING             stats/pubring.mix
       +#TYPE1LIST           stats/rlist.txt
       +#TYPE2REL            stats/mlist.txt
       +#TYPE2LIST           stats/type2.list
       +
       +## Where to find various textfiles
       +DISCLAIMFILE        disclaim.txt
       +FROMDSCLFILE        fromdscl.txt
       +MSGFOOTERFILE       footer.txt
       +HELPFILE            help.txt
       +ADMKEY-FILE         adminkey.txt
       +ABUSEFILE           abuse.txt
       +REPLYFILE           reply.txt
       +USAGEFILE           usage.txt
       +BLOCKFILE           blocked.txt
       +
       +## List of blocked source addresses
       +SOURCE-BLOCK        source.blk
       +
       +## List of unwanted header fields
       +HDRFILTER           header.blk
       +
       +## List of blocked destination addresses
       +DESTBLOCK           dest.blk rab.blk
       +
       +## List of addresses to which Mixmaster will deliver, even in middleman mode
       +DESTALLOW           dest.alw
       +
       +## Pid file in daemon mode
       +PIDFILE             mixmaster.pid
   DIR diff --git a/conf/mix.hlp b/conf/mix.hlp
       t@@ -0,0 +1,45 @@
       +This independent remailer uses the Mixmaster remailer software. It is
       +highly recommended that you obtain a copy of the Mixmaster software to
       +utilize this remailer. This particular remailer may offer other means of
       +accessing the remailer service. If this remailer offers other means of
       +accessing the remailer service, the means will be described later in
       +this help file. However, only by using the Mixmaster client software
       +will you assure the highest level of security against third-parties
       +compromising your privacy.  How to obtain the Mixmaster software:
       +
       +Mixmaster source code for FreeBSD, Linux, other variants of UNIX, and
       +Win32:
       +
       +If your operating system is a UNIX derivative, simply download and
       +compile the client from the source code available at
       +http://prdownloads.sourceforge.net/mixmaster/
       +
       +Mixmaster clients binaries for Win32 (Windows 98, NT, 2000, XP)
       +
       +Win32 users may wish to try one of the GUI applications that interface with
       +Mixmaster:
       +Omnimix:                http://www.danner-net.de/om.htm
       +Quicksilver:                http://www.quicksilvermail.net/
       +Jack B. Nymble:                http://www.panta-rhei.eu.org/downloads/JBN/
       +These are all developed independently of the main Mixmaster distribution. Please
       +do not contact the Mixmaster development team or the Administrator of the
       +%RMN with questions about this software.
       +
       +For more information about Mixmaster or to contribute to the development
       +of Mixmaster, please see the following URL's:
       +
       +Official Mixmaster Project Site:
       +http://sourceforge.net/projects/mixmaster/
       +
       +General Information about Remailers and Remailer "how-to" Guides:
       +http://www.noreply.org/
       +http://www.faqs.org/faqs/privacy/anon-server/
       +http://www.andrebacard.com/remail.html
       +http://www.freehaven.net/
       +http://www.stack.nl/~galactus/remailers/
       +
       +Remailer Meta-Statistics:
       +http://stats.mixmin.net
       +
       +                                        ****
       +
   DIR diff --git a/conf/mlist.txt b/conf/mlist.txt
       t@@ -0,0 +1,48 @@
       +
       +Broken type-I remailer chains:
       +(austria borked)
       +(borked senshi)
       +(cyberiad borked)
       +(deuxpi senshi)
       +(dizum borked)
       +(frell senshi)
       +(george borked)
       +(senshi beton)
       +
       +Broken type-II remailer chains:
       +(austria borked)
       +(borked cyberiad)
       +(cthulu antani)
       +(deuxpi tonga)
       +(metacolo tonga)
       +(pobox tonga)
       +(winters tonga)
       +Last update: Sat 22 Dec 2007 14:50:04 GMT
       +mixmaster           history  latency  uptime
       +--------------------------------------------
       +cthulu                  +-- 12:23:02 100.00%
       +nymkey                  *-- 12:15:01 100.00%
       +cyberiad                *-- 12:10:30 100.00%
       +george                  *-- 11:53:04 100.00%
       +dizum                   +-- 11:43:56 100.00%
       +pboxmix                 *-- 11:27:59 100.00%
       +banana                  +-- 11:16:59 100.00%
       +borked                  *-- 11:13:06 100.00%
       +metacolo                *-- 11:01:08 100.00%
       +hermetix                *-- 10:35:00 100.00%
       +deuxpi                  *-- 10:25:01 100.00%
       +cside                   +-- 11:04:57  99.88%
       +antani                  +-- 13:38:02  99.49%
       +frell                   --- 16:59:02  99.03%
       +citrus                  +-- 14:20:01  98.42%
       +starwars                +-- 13:51:02  98.27%
       +kroken                  +-- 10:25:33  96.30%
       +pobox                   +-- 11:48:00  95.82%
       +eurovibes               +-- 11:33:00  92.45%
       +winters                 +--  9:52:06  89.99%
       +beton              ___  +-- 64:40:28  64.21%
       +austria              _  +-- 11:04:58  45.96%
       +tonga                   +--  4:48:00  30.70%
       +bunker                  +-- 14:50:01  24.07%
       +hastio                      99:59:59   0.00%
       +panta                       99:59:59   0.00%
   DIR diff --git a/conf/news.hlp b/conf/news.hlp
       t@@ -0,0 +1,59 @@
       +You can use this remailer to post messages to Usenet newsgroups. To send
       +a message to Usenet, insert the "Anon-post-to:" header as per the
       +examples below.
       +
       +==================================================================
       +To: %RMA
       +
       +::
       +Anon-Post-To: alt.test,misc.test
       +
       +##
       +Subject: An Anonymous Usenet Post
       +
       +This message is anonymous.
       +===================================================================
       +When posting test messages, please use the appropriate test newsgroups such
       +as alt.test and misc.test.
       +
       +The newsgroup alt.privacy.anon-server is not a test newsgroup. Please do
       +not use alt.privacy.anon-server for testing purposes.
       +
       +To post a follow-up to a Usenet article, you must insert a "References:"
       +header.
       +
       +Here is an example as to how to reply to a message that originally
       +contained the following headers:
       +
       +==================================================================
       +Newsgroups: soc.rights.human
       +Subject: Re: Are you a witness of torture in West Africa?
       +Message-ID: <6643215551.110344173@news.newssender_domain.com>
       +References: <19990101182004.17714.qmail@nym.some_nymserver.com>
       +==================================================================
       +
       +Your anonymous follow-up message should begin as follows. Note the
       +required blank line between the "To:" header and the double colon.
       +
       +================================================================== 
       +To %RMA 
       +
       +::
       +Anon-Post-To: soc.rights.human
       +
       +##
       +Subject: RE: Are you a witness of torture in West Africa? 
       +References: 19990101182004.17714.qmail@nym.some_nymserver.com
       +
       +Two weeks ago, soldiers came to our village. The soldiers all had
       +machine guns. Nobody in our village has any guns, since the police had
       +come by our village about a year ago and took away all of our guns to
       +protect us from bandits. There was nothing we could do to resist the
       +soldiers. The soldiers rounded up all the men, except young children and
       +the very old. Then the soldiers lead the men away from the village.
       +About half an hour later, we heard many shots in the distance. When we
       +went looking for our people, all men were dead. The soldiers had left.
       +The next day, they went to another village in the [. . .]
       +==================================================================
       +                                *****
       +
   DIR diff --git a/conf/pgp.hlp b/conf/pgp.hlp
       t@@ -0,0 +1,143 @@
       +You can use PGP to encrypt messages sent to this remailer if you for
       +some reason are unable to use the Mixmaster client software. However,
       +while PGP will securely encrypt the content of a message that you are
       +sending to the remailer, submitting messages to the remailer that are
       +merely PGP encrypted without the use of the Mixmaster client software
       +greatly increases the risk of third parties being able to determine the
       +identity of the sender (you).
       +
       +This remailer primarily supports the ability to submit messages for
       +remailing without requiring the Mixmaster client software for backwards
       +compatibility with older remailer client software.
       +
       +If you are able to use the Mixmaster software with your operating system
       +(chances are you can), it is highly recommended that you use the
       +Mixmaster client software instead. See the earlier section in this help
       +file on how to obtain a copy of the Mixmaster client software.
       +
       +If you cannot use the Mixmaster software, want to use an anonymous
       +remailer, and are willing to accept reduced security, you can do the
       +following:
       +
       +Send email with Subject: remailer-key to <%RMA> to obtain
       +a copy of the remailer's PGP key.
       +
       +Then do the following:
       +
       +1)        create a file containing your message
       +2)        insert a BLANK LINE as the first line of the file
       +3)        Insert a "::" as the second line of the file
       +4)        Insert "Anon-To: final_recipient@destination_domain.com" as the
       +        third line of the file.
       +
       +At this time, the file should look as follows:
       +
       +==================================================================
       +
       +::
       +Anon-To:  final_recipient@destination_domain.com 
       +
       +This is some anonymized email.
       +==================================================================
       +
       +5)        Now encrypt the file with the PGP key of this remailer.
       +
       +Finally, email the encrypted file to <%RMA> as
       +shown in the example below.
       +
       +The line "Encrypted: PGP" instructs the remailer to decrypt the message
       +and process its contents.
       +
       +==================================================================
       +From: remailer_user@sender_domain.com
       +To: %RMA
       +Subject: anonymous message
       +
       +::
       +Encrypted: PGP
       +
       +-----BEGIN PGP MESSAGE-----
       +Version: 2.6.3i
       +
       +owE1jMsNwjAUBH3gZMk9PClnUoBPUANpwElW2OBPZD8H0gd1UCP2gduuNDNfIcSH
       +T4zCbQmtlbzGFM9T0jSD7QVvEzaPcUlBSSWHQclbnR9YWJNp5BFSLdR9CijF3NGx
       +ybry/1Rsqn4la3a0JiIhLvnYGCu9HFtiC8oIxnlkeuIYe+EH =HgDq
       +-----END PGP MESSAGE-----
       +==================================================================
       +
       +Even though PGP encryption in itself is very secure, not using the
       +Mixmaster client exposes some information to parties desiring to
       +compromise your privacy. This information leakage permits what is known
       +as "traffic analysis". For example, if someone receives anonymous
       +messages soon after you sent encrypted messages to a remailer it is
       +likely that you are the sender of those messages.
       +
       +To partially compensate for this information leak, you can instruct the
       +remailer to delay your messages for some time or send the remailer empty
       +messages to make such analysis harder:
       +
       +If you use the line "Null:" instead of "Anon-To:", the remailer will
       +simply discard your message.
       +
       +You can add a "Latent-Time:" header to the remailer to retain your
       +message for some time before forwarding it.  "Latent-Time: +2:00" would
       +delay the message for two hours. You can use a random delay by adding
       +"r", for example "Latent-Time: +5:00r" would delay the message for up to
       +five hours. For example:
       +
       +==================================================================
       +
       +::
       +Anon-To:  final_recipient@destination_domain.com
       +Latent-Time: +2:00
       +
       +This is some anonymized email.
       +==================================================================
       +
       +
       +You can chain remailers by using another remailer to send the message to
       +<%RMA> anonymously. For example, take the message
       +
       +================================================================== 
       +
       +::
       +Anon-To: %RMA
       +
       +::
       +Encrypted: PGP
       +
       +-----BEGIN PGP MESSAGE-----
       +Version: 2.6.3i
       +
       +owE1jMsNwjAUBH3gZMk9PClnUoBPUANpwElW2OBPZD8H0gd1UCP2gduuNDNfIcSH
       +T4zCbQmtlbzGFM9T0jSD7QVvEzaPcUlBSSWHQclbnR9YWJNp5BFSLdR9CijF3NGx
       +ybry/1Rsqn4la3a0JiIhLvnYGCu9HFtiC8oIxnlkeuIYe+EH =HgDq
       +-----END PGP MESSAGE-----
       +==================================================================
       +
       +Next, encrypt the message with the PGP key of the %RMN
       +and send the twice-encrypted message to <%RMA>.
       +
       +Similar to a nested Russian matryoshka doll, containing increasingly
       +smaller dolls inside the each outer doll, you can layer multiple
       +encryption layers and remailer hops around your message. If this sounds
       +confusing, just use the Mixmaster client software instead.
       +
       +If you send your messages through a chain of several independent
       +remailers, it will be become increasingly difficult, though not
       +necessarily impossible, to trace the anonymous message back to you. A
       +vastly more secure solution is to use the Mixmaster client software to
       +send your anonymous mail.
       +
       +Some remailers supporting PGP encrypted messages offer pseudonymous
       +"nym" service that allow you to not only send emails privately, but also
       +receive emails without enabling the sender to determine your recipient
       +destination email address. For more information about such nym services,
       +see the following URLs.
       +
       +http://lexx.shinn.net/nym/ 
       +
       +http://riot.eu.org/anon/doc/nym.html
       +
       +                                *****
       +
   DIR diff --git a/conf/pgponly.hlp b/conf/pgponly.hlp
       t@@ -0,0 +1,144 @@
       +You can use PGP to encrypt messages sent to this remailer if you for
       +some reason are unable to use the Mixmaster client software. However,
       +while PGP will securely encrypt the content of a message that you are
       +sending to the remailer, submitting messages to the remailer that are
       +merely PGP encrypted without the use of the Mixmaster client software
       +greatly increases the risk of third parties being able to determine the
       +identity of the sender (you).
       +
       +This remailer primarily supports the ability to submit messages for
       +remailing without requiring the Mixmaster client software for backwards
       +compatibility with older remailer client software.
       +
       +If you are able to use the Mixmaster software with your operating system
       +(chances are you can), it is highly recommended that you use the
       +Mixmaster client software instead. See the earlier section in this help
       +file on how to obtain a copy of the Mixmaster client software.
       +
       +If you cannot use the Mixmaster software, want to use an anonymous
       +remailer, and are willing to accept reduced security, you can do the
       +following:
       +
       +Send email with Subject: remailer-key to <%RMA> to obtain
       +a copy of the remailer's PGP key.
       +
       +Then do the following:
       +
       +1)        create a file containing your message
       +2)        insert a BLANK LINE as the first line of the file
       +3)        Insert a "::" as the second line of the file
       +4)        Insert "Anon-To: final_recipient@destination_domain.com" as the
       +        third line of the file.
       +
       +At this time, the file should look as follows:
       +
       +==================================================================
       +
       +::
       +Anon-To:  final_recipient@destination_domain.com 
       +
       +This is some anonymized email.
       +==================================================================
       +
       +5)        Now encrypt the file with the PGP key of this remailer.
       +
       +Finally, email the encrypted file to <%RMA> as
       +shown in the example below.
       +
       +The line "Encrypted: PGP" instructs the remailer to decrypt the message
       +and process its contents.
       +
       +==================================================================
       +From: remailer_user@sender_domain.com
       +To: %RMA
       +Subject: anonymous message
       +
       +::
       +Encrypted: PGP
       +
       +-----BEGIN PGP MESSAGE-----
       +Version: 2.6.3i
       +
       +owE1jMsNwjAUBH3gZMk9PClnUoBPUANpwElW2OBPZD8H0gd1UCP2gduuNDNfIcSH
       +T4zCbQmtlbzGFM9T0jSD7QVvEzaPcUlBSSWHQclbnR9YWJNp5BFSLdR9CijF3NGx
       +ybry/1Rsqn4la3a0JiIhLvnYGCu9HFtiC8oIxnlkeuIYe+EH =HgDq
       +-----END PGP MESSAGE-----
       +==================================================================
       +
       +Even though PGP encryption in itself is very secure, not using the
       +Mixmaster client exposes some information to parties desiring to
       +compromise your privacy. This information leakage permits what is known
       +as "traffic analysis". For example, if someone receives anonymous
       +messages soon after you sent encrypted messages to a remailer it is
       +likely that you are the sender of those messages.
       +
       +To partially compensate for this information leak, you can instruct the
       +remailer to delay your messages for some time or send the remailer empty
       +messages to make such analysis harder:
       +
       +If you use the line "Null:" instead of "Anon-To:", the remailer will
       +simply discard your message.
       +
       +You can add a "Latent-Time:" header to the remailer to retain your
       +message for some time before forwarding it.  "Latent-Time: +2:00" would
       +delay the message for two hours. You can use a random delay by adding
       +"r", for example "Latent-Time: +5:00r" would delay the message for up to
       +five hours. For example:
       +
       +==================================================================
       +
       +::
       +Anon-To:  final_recipient@destination_domain.com
       +Latent-Time: +2:00
       +
       +This is some anonymized email.
       +==================================================================
       +
       +
       +You can chain remailers by using another remailer to send the message to
       +<%RMA> anonymously. For example, take the message
       +
       +================================================================== 
       +
       +::
       +Anon-To: %RMA
       +
       +::
       +Encrypted: PGP
       +
       +-----BEGIN PGP MESSAGE-----
       +Version: 2.6.3i
       +
       +owE1jMsNwjAUBH3gZMk9PClnUoBPUANpwElW2OBPZD8H0gd1UCP2gduuNDNfIcSH
       +T4zCbQmtlbzGFM9T0jSD7QVvEzaPcUlBSSWHQclbnR9YWJNp5BFSLdR9CijF3NGx
       +ybry/1Rsqn4la3a0JiIhLvnYGCu9HFtiC8oIxnlkeuIYe+EH =HgDq
       +-----END PGP MESSAGE-----
       +==================================================================
       +
       +Next, encrypt the message with the PGP key of the %RMN
       +and send the twice-encrypted message to <%RMA>.
       +
       +Similar to a nested Russian matryoshka doll, containing increasingly
       +smaller dolls inside the each outer doll, you can layer multiple
       +encryption layers and remailer hops around your message. If this sounds
       +confusing, just use the Mixmaster client software instead.
       +
       +If you send your messages through a chain of several independent
       +remailers, it will be become increasingly difficult, though not
       +necessarily impossible, to trace the anonymous message back to you. A
       +vastly more secure solution is to use the Mixmaster client software to
       +send your anonymous mail.
       +
       +Some remailers supporting PGP encrypted messages offer pseudonymous
       +"nym" service that allow you to not only send emails privately, but also
       +receive emails without enabling the sender to determine your recipient
       +destination email address. For more information about such nym services,
       +see the following URLs.
       +
       +http://lexx.shinn.net/nym/ 
       +
       +http://riot.eu.org/anon/doc/nym.html
       +
       +                                *****
       +
       +
   DIR diff --git a/conf/pubring.asc b/conf/pubring.asc
       t@@ -0,0 +1,544 @@
       +-----BEGIN PGP PUBLIC KEY BLOCK-----
       +Version: GnuPG v1.0.7 (GNU/Linux)
       +
       +mQCNA0CcFXkAAAEEAN/nFODxD0V/0zCy2bW7ZB6F+JS1sIegmejHK99x0FSzxmf/
       +dNwkMRcVec3SpA93a21fajj0KwJGc4F1NKCmK4J/70ObFlyPuvDdk+SDxFQPeoWs
       +GJUbHadsjVVMibplb9iY6HX17+YxjPgTHn9RyLmsBEwNDM44yjsxltkRUbsJAAUR
       +tDNib3JrZWQgcHNldWRvIHJlbWFpbGVyIDxyZW1haWxlckBwc2V1ZG8uYm9ya2Vk
       +Lm5ldD6JAJUDBRBAnBV5OzGW2RFRuwkBAb6KA/9xkvKXk++CBsSW3NR7N651/+bb
       +q9ndXb1IHYsa5pb/+AOyV77xF+wVkbBzLyvaJB27tAUNgDDSIfxmUysOIQjmkrTx
       +KXTgbCEnLX/I7Ty4bR8WWshfEdpique2W92A6znwS3xmMuJlK7CK1Ol3JVYDc4dD
       +l1Ot27AdFdQqQw9aXZkAjQNHVXFpAAABBADJ3G4IRz7DycRr/uPbwjFDYnRZQArI
       +7DxiBpf/Ipjho1Z6lOy+vIZYEK26MEHyehvlzSHNrlj36AbOEQlaGIX0psz6/S9k
       +avB3BTTbq+/BVPVgwatyJZQdapSMk7blqX4iZhpcyKow2E3JxXS+KTv/V9EgUHvO
       +0Jpfo6lTPtO8owAFEbQnIkNpdHJ1cyBHcm92ZSBSZW1haWxlciIgPG1peEBvdXRl
       +bC5vcmc+iQCVAwUQR1VxaV+jqVM+07yjAQHX5gQAl//kiAyy/QqbWNZNBiwhLjkk
       +dzBugAuovZ6Fgvd+IKcWtpxOhMwB39y4d0+Oha3/IcDbzV/orm24ktQHgb0JfkZ6
       +pUUrQEM/77zS+qAtQzq26+gic4MYU7mUwWaKTGPgiCWRoNZpZthPnfGR4VsvjJ/4
       +OLA9GCrbU0hFcsTfDcSZAQ0DR18qYQGBAQgArL/fnTilH33WQNLa7x6pEWuJUWne
       +tA8fP7Md18G//V3U/7Dl/kMptndnFjd7oHAjNmHT6O+e+SueYX6ld6r6Y+okpnXH
       +gxJitF0uaftrPyz0xOkJPjXHUhNdrENp4k5Td/Q3gYlCZchVvBJ5oydMJAqBAsAy
       +YR86lNM9X7rp9VadRnzTKkmQZHbB63a/Ps1OVulFiELZc103IEIO+cyAUA3t6Zgu
       +I9hnfZDSxSBLA+PSUTRZN67YSb3l7AlreLaFX9dErgKWxM3NC/o4ke/G9J66qtkJ
       +WcNJ6Z8dhLPZ8Wp1ZE1ki+6Gic4Qi/IZ3JPVozV1iLBNT+UaCibpLag1/QAFEbQn
       +U2Vuc2hpIFJlbWFpbGVyIDxzZW5zaGlyZW1haWxlckBnbXguZGU+iQEVAwUQR18q
       +YRoKJuktqDX9AQFZWwf/eNB2zMCs3H36XWP9V4R+2xT35wQm41cHv5Ad8FIa+9WN
       +0pULBovaIr+yjrUcF+HzTfBxrTkFGYLZyx0M5k9nlN6ybOhjPr3GJ0OYsAbSRyw0
       +6ive0N2E/ZBjIoHGBAlpTD7ixmWYrxzpsxjJDwt9f4bF1sGLtvOAP8pmvi04XZJH
       +MxajYjKzbIYnG+6l5M4zZLS0wv6rZCdYmgqWX5msntYwD93QHzwZdY/uVla/yqyL
       +t0Xiz4DQ2Xt/vWZ9Aqzj9TwOrTJsrA5jsX6Ea6mpxafyNGThd1obuppoXL59TDxI
       +MruM2k6n/XR7Elveucv59jfSoeVRu6Yj35usvpJR8okBFQMFEEdfKsJ2ULwyZWTT
       +8QEBmjgH/iIoLTEn3sr7AD4icOuQQmMfMCHgUsftWRpxvRd8PfbAvrxU72+wloPp
       +kPFkbLi95zfx42/JpVKbHEKwCMBAuaOX/tNKuzGI99y7+pNBCmVCXm57KLVJIeDy
       +Ltu00LuU28wam6FoE8S3gI/LEL4BwKq9i5ZVwMd6TdEkbGyLTjx9Qg6LofLTnY33
       +TGsm/L/W53KePlpfbgCMySsDzB7kfCIJtpLy62phXcd9sVoN6sNo1zV6d844ryXr
       +t8RPK48uiYHIxS/hRz0Z/tP8hu1a4zRXfxCyjq87BPBysYLEBIUqHr5v7f1/KfBF
       +P2dWzUzKn/5CN5GgN2h+35T1aR6uty2JARUDBRBHXyrrfCrtBQboJV8BASggCAC3
       +UyZO/Z2D0DHcXu29x1ETW11Nr+Aa93ya/6kZ9slqtpZ6fgtxHIzX+54nweC9pCr7
       +9II1VEXuyvmET4sbG9zIczQGCwYws5k60oeppFqPJg0dmh/d3w2mTCUhKSqtwKf6
       +h5gguNAguCSjOuRbRwZOeXS+VeMAeW4Tzg3hBY5D6WbtWbBvxUsjdu3GKulo66wr
       +e4oO9m5a3ZmJO6FrFPbb8Ssfck4i+mZptUiStEj5yeXr8sYfdHStPmwHoQiXq88s
       +25VFVU6A9WMM0FP2T64ltNEnaI1tnKAc+VqqZ+b7CWjl4CziZ9I32BJIcU86AWJv
       +UEii1sbhKTYen8VBkuaVtCpTZW5zaGkgUmVtYWlsZXIgPHJlbWFpbEBzZW5zaGku
       +aG9tZWlwLm5ldD6JARUDBRBHXyqQGgom6S2oNf0BAbZuB/9w7jK2sDtKDB+44hdq
       +WwPSUqh6nnM5LoZMXodHjmWHrHQbbQuluv03KPhyn1B/+rymiZYRdo4Z5K9+qj81
       +KFXl3jBEsWyCz9aukjhYC2ex8DJ96ME79WHCpDeYg4YsyTpmhy2MENz6MpqVOHiH
       +SolQcZVVgGeiVrLzBwB+quzkVnu/eChhAnQ/NmhPmeHxlS3vi3oPPkeoCuhuYnvs
       +pHVvmw94k+cjquW/BLZQ1ZDZ0bKaKo917WkGClVrKHNF8YzVoDQxgyOQp4VfAC4o
       +6wSTX290RER4PNo11JXgQUlSAlHQlDKAaLu5AYL6Te46UlHtUhrEO71jjvcF3PMb
       +h9UYiQEVAwUQR18q4HZQvDJlZNPxAQFuKwf/Tr1Iet2qR8BX//byDlk7XFsk3c9w
       ++zsDa4Z2Ug6VCEyZYJ+c5xeKm3aeuOjj5DHekrtIMTOKhTPPBOLmNih/149VDK6d
       +zg+h7XccjaUwwxo3zBuxQjhHwFom5vIzPFNLb2DLayOGQKWPFx/W3rKvgw0jErOj
       +8wLJDv27Lcul0BwaiMlAYjNmnc8qt5JoLub76do0oTU5juepJaTMwIYeYqd26ULq
       +GuOewSgZAQM5z1VVVMiADmZMCQteyHJRgNQveiTdCYeDi5R6nz0BUGPwijJhIOOG
       +w6YnEP+K36CJywRnPKjoRFEusSnnBZIEMLl0+a/Kxe74AAIXjY2l0UhGtIkBFQMF
       +EEdfKvN8Ku0FBuglXwEB6k8H/i9yWLTpI/rXOpHRsMeTc8gazMq5Iz2ByqNSowKS
       +8sxwoQcrFe1WGGAR2LKq3RMiEtW2caljol4GdamnTF8Wag1lmKglWSz0kCorvKOo
       +sd29opLlvGS1TTf8WE5oyXY0PP6UjGAadOIz049IOrkKhkXN97WrV29WTTNnYKyp
       +cL361NB6cOHr3YKJeygq/QO/Mo72wQrzyCuol3JEFVMZal9m3jgcujSYHzVjMlvn
       +55NKaLDeUqpX0lkQ1UZcBbxnIVQet1bdOcs98odTZTfOh1qzUbex1wbDA8DU2Rx0
       +4HXnGtB9K8WCUPNHzvUMqd5ovuWZzv1tPUFSgffHTRAEz5GZAI0DRm7N6wAAAQQA
       +rJRgeUcSlxVAJfnR1yLeGNpMs9iIkIhbuhbQS/G2kIYR8bHb1UaIFMD1zvXZ6s8/
       +JlUjGYA2tWPHr4RPrGI5Qpto3z51fivrq64//qUxUUwGTSpkuvxSgNLcWcz/KBw7
       +pPkgW93X2hHQY2kculc+uH8tbJvGSIFAx81oy6umu3EABRG0I0RldXhQaS5DQSBS
       +ZW1haWxlciA8YW5vbkBkZXV4cGkuY2E+iQCVAwUQRm7N68fNaMurprtxAQG9rwQA
       +mrpidD7nJr0y47IWtx18gZtZnQjzrfJM4QdaZHA9/zE/8kFWPozp6Ch5sDnpw0Rf
       +REss8iqdCXxcrr/n0btRGCeIkGAqUVMkhk39U379m+BIxyDiq3W0j+wGE1h6Y0vU
       +PyO4RUCFI3NZ141SfF5Ue60BwT1zumw4x098WnioJaKZAI0DOQQxMwAAAQQA5ru9
       +HgZkJFS6RqgGqUZluu7pzpSUCAs6zw53Yj5QXUpNjllcoKUorlRuUcOIWDMmT7Q3
       +FVHd4+Annowl4raIY9Vn+Ly2ELWBHpu2utI43N8ruuttbZoqUN+KHKPPp6Y9iQeo
       ++PSEDDEZCJMyQQ8XmOYR1Z5k3iSmHyroMjEjSzcAAgO0IU5vbWVuIE5lc2NpbyA8
       +cmVtYWlsZXJAZGl6dW0uY29tPokAlQMFEDkEMTMfKugyMSNLNwEBaoAEAL7q+gQO
       +ylINBSfRGYuPLXM+zKzHtl1zsn9zjSXqsZL2fW1lCLAJOkguKdeIIs/cj0+71PiS
       +XWAdVjIi7amp404kvRbPXDoeTBCMawZ3G0UPIUKZ/F5zSG0MzlZCfUOq0hob3yY1
       +xK2RjYHl7tU0/ZpV3rqhN4M8tgPhUKyshPQPmQCNA0Ti8ygAAAEEAKPnZOuQoP21
       +FXBmP4SjQVph1UeBktY6aa0H05pH+RFgVoF6AcF1bu++/QBwwK5jNtxMrGo//Rg6
       +HNfgFkMKMq/q/i7TlDRxSr9ccEflV3ngmv5PuVpMzh2U6STDWOjULz+e4YZdKQjP
       +lJbWMuhfcclyX0tbKpx7ldFMB6/2rSKZAAURtCxGcmVsbCBSZW1haWxlciA8Z29k
       +b3RAcmVtYWlsZXIuZnJlbGwuZXUub3JnPokAlQMFEETi8yjRTAev9q0imQEBrEwD
       +/RriA/AsacSS3Kg39I6DcBcIwO2yHAahZnUkG/4s5bhetd7S1Qodu3wLhU0BPnkA
       +LtIj9UDzDsiOKfUnbcE4h3Kg/HnVheu0NKorMm4SosBLrgzuRiOIUgE2KUKsNswi
       +fdQ8ZyFBpA6NiFCQV5pQn/F/nfepKADsKeKQc3VVpfbJiQCVAwUQROL2W5cXn3ji
       +i5ZVAQGMLAP8CXHziEo/eFv+HsFVESGEL+nkKdQm9P7lNEvseubzIV2f5A9oVolw
       +WEXpwDAaMbN1aPsfJKRI4qeJGGtL5+0wzHoobNaCtmucP4wqP6l6i2pCENQnCxtq
       +/J8hchcpOoxDFd+g2qUdVyv+CaJ5M8TB9vPb8SDlHMfz7yD4o7v2xUKZAI0DRlu+
       +NAAAAQQApjiOOKfbNFbawVcrLzTfKGQXJn7cfT39nSMCg6wc5c2iTkgblNq6AqLG
       +RiQx3Qs2VI/wh9qk6HGfYj3FPnWOTiftvGLpRD4V4Ado02iA7M+f1Jssg+Xg3WQX
       +KOR9YIZuhqw4nWFH4d2+FQQbo/t3mUwgVxP2uw6vXP+0XuBeRO0ABRG0OW1ldGFj
       +b2xvIEFub255bWl6aW5nIFJlbWFpbGVyIDxtaXhAcmVtYWlsZXIubWV0YWNvbG8u
       +Y29tPokAlQMFEEZbvjRc/7Re4F5E7QEBzQQD/RNAVwOQ7Vl34vG9RVO3I+sWL6q1
       +FbdNdFGLTTC8nriZko46/0Hk6mlbuV+dMuh02Unfic+4E9s1n107Gt22vOzDKhaO
       +qJAPxcyOyX3eyE96f/GQBjDUi+j85ioWgOJ/D7pJFasVgNdY8he1KLN6OXgI//E9
       +c8KMminqAkWIWCNFmQGiBEZbvk8RBADZzxbcMOS8lFAFdpgSNWox8gZpmSG8zJF0
       +wOkr/uoGnsFwCsNbFdmyuTVUm7BIE7WoLl0X1CfdVGcJHmF9RXiTNqN4Q/Da7+GP
       +AZXwLZwM++uVX8ddOXKtebgTCOVmmX4dM6am2qQHfIRFTO7Ht4uAIMlfNI8fy2e2
       +Dx0ij+w7cQCggzxIcCvtWbGLnx8la40RWYLyht0EAK+7LKyEXpycLcnt02eYe15t
       +/ZnDeysTZFeE4egzOZGq4bx1QQ9zIrIe9b50Xr/Ml0RBMJUaz+DVwLHAn45uVOzW
       +oToqeChs92duG1E4c/L58lSl7tzZP2LPzzY30UhsVRZx1GRCMIWarrsNafg3rd8x
       +Ru9O/80rb7hR8rBybyahA/oC3Y3sLlhA1Kqwvi9jRLRLBtRfGNFiK46DtRinvHBh
       +h6MNXtOJ9jarW/aSZ3CK8gmNaUZE/YcWUJ4T+GQDwZsEiHzVt/UCiruXZl7E/SAB
       +vPPnZqMClzjIxs8kHzPIk3W8HWc5Oi3hVwIgcuSnmjzJ1MgYQvLETfNKbjerqG5i
       +17Q5bWV0YWNvbG8gQW5vbnltaXppbmcgUmVtYWlsZXIgPG1peEByZW1haWxlci5t
       +ZXRhY29sby5jb20+iE0EEBECAA0FAkZbvk8DCwMCAh4BAAoJEPnXFQjuSKsvAREA
       +mgM2okQLJr3Co6QkFDWBAQWpSnK6AJ40Fk267AAJfjJbuGngqhb7FnAq3rkBDQRG
       +W75PEAQA0SCjhLqjqE0h4J+eOaA6/juj5MwKLCcr3OKy9B+ch0c6YFJOOYnpdTy1
       +uQV4yZpWG0cTTYZmcP6jDQi9LAFGoc6BWq6FHCt+9hNQTUEhtZ8SAevmeLLc3Um2
       +Dk5Qzi+VZzfU8oSIeDlTyWrCz90NzpmG+a/Cy/bobzc2RdQ5bI8AAwUD/2ss80PY
       +/r6MYKlX2m+aCEWz2YqRSZsc8rwiq/Y2RJ6bS1hJzs0fjc+rtgWOmMjAjHB7ks6+
       +mf0t/nEt0FTV9E3g5Q6z2A0ClKy5wjVA9F1wkBHa1vnekpPtvqjkmGbBZN/ciooK
       +trPZqvIXRcFSPjIS8pwCuBABTbt3P7eTHCn3iD8DBRhGW75P+dcVCO5Iqy8RAr5M
       +AJ9tph+Ek9HS2kvx4DU22WNZk/U9QQCfc/f/G73+73y9uLXE1ld4BZHeotGZAI0D
       +Rz2ECQAAAQQApvW2HDlBkMvdaBCGgGGtXK6kfnVU5/sDRgxv/W2v4sQF9B05nEGr
       +E9Z+dO5lZ73KpwGt9S1E7k778giN98s2l7Wr9Mt0nBrK40fjnAgeAcDy6Al7hkD2
       +RKw4fQf9lTEG3t/ORIavml++ffTZ5m25oG1EpLuE0pnRl03wDFSNbZsABRG0MWh5
       +cGVycmVhbC5pbmZvIHJlbWFpbGVyIDxyZW1haWxlckBoeXBlcnJlYWwuaW5mbz6J
       +AJUDBRBHPYQJl03wDFSNbZsBATiPA/49rE5gwLLPdN8TdmWMVCdYJbZn18oY9363
       +aMSE9L+W5VEms1WL3AiVVpOacSCEXbJx9aLPvDMT4PsVwj8eDOw4gZDnDogekXl9
       +KhCKjFEQ/T9uhf4VdRAXZqTror0vIml9gCnjwJ6p702JLr/NVANmpoET047u5h/3
       ++bU9O/QNtJkAjQM/aBqoAAABBADRmzLyRGqKmd6qtv1U5LwLtSJzmtTnoBOk9Azp
       +mLff6YgO4GNcbkzm4O++el0Kzz9d/+S+iYteCMtVkAXfkck97RbrxYVxIhAcXVuJ
       +Bnfn2wj5Orn9rCIPe57KaYnxJQDZrbANrOgrKVLLKoLbAmBAmh5/PbZjoFfS7ybg
       +UvWtwQAFEbQrR2VvcmdlIE9yd2VsbCdzIHJlbWFpbGVyIDxtaXhAbWl4bWFzdGVy
       +Lml0PokAlQMFED9oGqjS7ybgUvWtwQEBPUkEALPOXrPzDiBWuqOTe2qvNAJfREvd
       +2nIIavdRMESbD1UcYnf/7AfmqpsZpIIXW279PRq3r29IuNyLo/TAT0Cw2va9rP8I
       +6xfLsEsduH9Qjt0kC9NCOI/CCaXHgk1E09YL1iFbVSrDSq6vfVIknO+sTCjucUce
       +qwHXDRJZqiZ7QoGxmQCNA0UE/x4AAAEEAKe6Oc1dgcLcWgZW2CbxmoQWFoKeOAJO
       +wrjb5cYUv8+Q92h2og3uosjF8KvU/ilQ8tC2BHWavAh98+TxFVIhbgf7z160Z62R
       +ELZ0TUm3fuWv6lpNGGLLHuWtGRErN6P5j1n1eu1B9h4B9vQMWmIt8n9LccvMjkok
       +6HgrDDB9/sG5AAURtEFDeWJlcmlhZGUuaXQgQW5vbnltb3VzIFJlbWFpbGVyIDxt
       +aXhtYXN0ZXJAcmVtYWlsZXIuY3liZXJpYWRlLml0PokAlQMFEEUE/x54Kwwwff7B
       +uQEB7IMD+wb3UdB6vxsu4l8R62lPkPudu/pDfL8t+QZ3rd24UdjHvf2mF0/51cev
       +bfsP9c/AhfrnpvUYjpxZ5mrgCkkeNzknUnk1MF/L1UyHAkqKKnF2rw+voaOtkFjD
       +d1midf9aEWQ0wX/SDgDXkhxZ5wdAK8Jv7xhImHxn63adNsgUEE8+iQEcBBABAgAG
       +BQJFBQAiAAoJEHCkr+X+kMzIcDYIAJwJj/B7rB4RToF+yyYpTqkNQIHhyjji2G1a
       +3O1IbYV3Hhvhs8Cq0GzXNQ+My+tiNXKURa/ZeJekHwbEOPPT7uNAgsT9bW6CQF97
       +OhHoMBr6xkDRfU+Ne/FSQw9yqVaIRtT4SVDGQVTaF3s2PiTPyetrHsEDGFtA6Kay
       +YiJC+WXgZ1BEFGnVil1Qkc9DVYHNr/6RqCYSrm0xN1iOnOqb4ZPiSII7AZuOMO0B
       +huaQ7pH+OlcJ3p04KJ4R/hxgGf68wGGDwEvW/4h06n3wxpEb6eG1X6ezyH7xj8Bw
       +5B5SamBX7FNHa6UjHwIh4B1JVVfYk16nuhH2zDZalvudpferxquZAQ0DRMAP3AAA
       +AQgA1VNjOtnZJvPBrRKAlozOClwWXM1WhnMedu+zIwThDsWzFcqCRJSWmZG9sVba
       +GOiizeCh7jEaVqjM3TtoIn7HIXJf2PTvkLKW5HCO84S0Ox9EPsf7HXvuAIEWhBrY
       +IFemIhRmTCqnml1+vwLLue3LPAihVH/eexwXLaoCKwSWaBckaHZDX9IKjQZRFZPo
       +eEDnR2B8FVgHuIy3C9BszXadyhka9HPE1dPVufwQvUaz36Vi9JDJNazwJSJuMawN
       +R+qSjpEJNFDc3iPBSefyMQE6WSOTX10aFnN0q6yw9Al+IPBzkB3rb8tPQ1wASvcJ
       +WURhu/41xK2R/2SCVrhsnh3hzQAFEbQua3Jva2VuIFJlbWFpbGVyIDxyZW1haWxl
       +ckBrcm9rZW4uZHluYWxpYXMuY29tPokBFQMFEETAD/6CVrhsnh3hzQEBLIIIAJhx
       +1ItvHaEBjpo2IF69ojUoK3RmZokPnjKG4qdvrfAsyuMr6RR5YBI4h8cT8kUzc6fK
       +Qwnh+C3HW48kbJhzGpl3/pWlCUmPayGpffCYiSSya3tHf+Pk6ERHpXzxisSVDuwj
       +7KrbfIkKFybJ5ff7oQ/SaKahvC/NGWdq76dMxUFRHPsdpIocAiQgPJQqdBgYmMqW
       +TEnaqOOw+BBbRFX1eD813x0e6dG85zgEdVwUriQETu71UQgsmkT5atkffpYb0Bgy
       +5nk69bZVA2uc9lIegOdmRuT4RNT+XTqKRkRJq5YRudSaSu67P4VuzHb9SxGsfNbn
       +5s8peeH44/3x5zknC3SJAJUDBRBEwBMG/zD7JTVSjbsBAaIDA/4v8BWTSiO/+04f
       +D9RBUf4Hgspjm92J9+O9J10ZszRxqIzWbK6pimuKKw2zbptWWdIC9s6wPUslCL/C
       +yQ8qXGe9gyQEmIj4kDqvKnah4b7+wdSnJQfoRsHWJrXkRBz9wvkQUf44oGKOOjkf
       +ME+Fmn0ltf/wtjJo114bvv4HnRoFvZkAjQNGwlgBAAABBAC8m8QauNc/Y0T0l1tt
       +KbL8cflFx1rhSOx5t4AlB3CVFRfvs8Ub2r5PvSsUzbXKPJqMiAn004zueDuAzwLC
       +nGqHCEf289+Je2OGzWjOXWFpuFAGBLpw6PPmlOdz89ntN4RxFvEZtgMGD/dvU5bN
       +ScNJoG5L3j8ZzPFQDJ67q2wzzwAFEbQuSGVybWV0aXggQW5vbnltb3VzIFJlbWFp
       +bGVyIDxtaXhAaGVybWV0aXgub3JnPokAlQMFEEbCWAFQDJ67q2wzzwEBUPED/RhR
       +/1savSVewaruZvAyBcahQUh8gHPdZgqtA6DfycBj++A06gDQTfwsfilCJTMaBlhI
       +xeqo1z4O0JOXdNh6S6wxLv0SYJurm5h4ZjVjwVrmwYm2PxFAZarftvATLHbdBHFN
       +KGNIvnoGX8HkZItsgnPY7WwKZytZWXNNHO40oOEzmQCNA0U3lJ4AAAEEANskGthf
       +C90qEGEApWpNvswJhLxq6JwRB0PeRK83HRDAvr6LO/CdixTTNuww9kRpQEAg7yGq
       +qNezkfX29EnxlgQ6F+NyiK5yopgS8xEAYDOM/jewI4WlFr+xIuuy3910p0v5vT6I
       +qe07hgleD9TMo3OVsndALnEujaXEOfaGcw6lAAURtFkiU3RhcldhcnMsIGEgV2lu
       +c3RvbiBTbWl0aCBQcm9qZWN0IGFub255bW91cyByZW1haWxlciIgPG1peG1hc3Rl
       +ckB0YXRvb2luZS5ob21lbGludXgubmV0PokAlQMFEEU3lJ6lxDn2hnMOpQEB2GME
       +AK1DW3TOdeCSi7av/4kzogBfLKSKbf0UiNqJ2j3rskcjpSdcvVOzu2hwS0uxp0Kv
       +EiuMal2vsFDIAgXfaPr+makMjZJ/oM0T4ShCsLXbUe8FSSPRgsY0EJuXHkdyimQM
       +UKU9Co93NAM0B+CGpvMxh6XWvQFfZKvyzIeVSZ3ba20kmQGiBECcGcIRBACJFaub
       +w932lnpAIomVhqOWkAd+aVRCyhlBSm/VFu8pp5AbY90b9shb3Ux3VAmmRoypXSIs
       +HudOukLW4Sxsw5sw6cg8Hwhfe5PlbxYmhD2HGCx2JeSdRMiRkQ+9GFtWMKv+sZaN
       +U5jVI5lwUrIdSOwjjjt/l3qRkAW/ogwMuHzZowCghN2yzsbH3FPMGEnXpiicyqeh
       +Ed0D/26s4KpgBfbGq4bnfT/C1mnvmMM78bJtzlQHAkGEjNhWUxMLd/8Nyviqpc13
       ++XdA2DE3suJo7jOkBqXxArCcUlpRlTGyCqWQBF1Jilg+b6/qhlZ1jO1DGhPKFLGq
       +HyBdZSBYbMwF17PNXhISwjJtA0fuFsvbIm/ooRKVCI+iIXEFBACF+pN9nDaVCR+8
       +eGpR8/dAJ5wjFqgORi2++ig27SKNUe+uRxdGpeqTJ4XJS9jUuSnL+79k2WHM/xYZ
       ++lZtI/CA1AKFgGAKpVWzgCc7IxAq3oMrlLT7V7vv2ZPD16JtjVVh7OJtKbW/P1AZ
       +qSbB0v2CjRxkhbZV9a5CekKLLWOP7bQzYm9ya2VkIHBzZXVkbyByZW1haWxlciA8
       +cmVtYWlsZXJAcHNldWRvLmJvcmtlZC5uZXQ+iE0EEBECAA0FAkCcGcIDCwMCAh4B
       +AAoJEPAonIQhgrY3vkAAmwUwHiHXTq/JSqlGbCfGBJtf1RZPAJ9PjfyA3esM7y4J
       +0SNYu9+r2Fwb8LkBDQRAnBnCEAQAzxMSji6wQZjmoGvFLIj4Wk+vRZ9oAA3LGVsE
       +0j2r340KFZVWkKV4KEcn/Op2FC8xa1fpmnvYPQokZF5t4kmgzkMijbCzZnCv3fkd
       +2aput1GTU90VNIFtKLveyvKV7wrP4xCOekoDrIvVFs2+IvlDdUoUu1aMpOBsQLFc
       +VDatizsAAwUD/A9kCc529Ewp8+r7DPBcNCRt2/g57sk5Fcd83tJgiafDBFglVFZt
       +ion743jCLLMLZ4+HGTx/w2QGatgcvfG6msbj7BfC0NH8HI3ET5NByBhiu/MuaVa9
       +jXhpi/BeKCM/13CyrAn7Q4sBU+gI8t3iWLXmpvU0HMZgfFzsSbAkzgFviEYEGBEC
       +AAYFAkCcGcIACgkQ8CichCGCtjeK8QCbB+R+JRLB57uMpzxZs6HFM95j4s0Aniv+
       +GnX3Et2am5XnSTYavqjWjIbfmQGiBEdVcWkRBADgx4eCloI8lo7PkkKiLyTcnDYA
       +CiQFMGsPOTh0u6aSqPQF3qdOd1lFKvqoHCF51aQ+Vr5uEgRljhBbDOdDJ356idQm
       +FgQtvsnZe46TDgXDALZiOUv40zHelWJVW7L2H72bFbExL3VaV8SGm/oMXmZztyTs
       +pAbMvzUNOeaACJLq0wCgkU61NVIFhhJVJsMPkIth6OUc3kcEAKtTuVfQlpYPk/RC
       +t7D1zPdgKlaJZnJhCe+ftqQzmpht1L+1RaVtr+MDQnfNjsp/IWQahLjdUXFG2ahu
       +XGP60vv5rsm4cQyd1S0WmF40FYGM8xjy5V+Au08bumYbV6GwMIn0iJHhfUwIapMc
       +wbzEUwbgwvFnl7D6SZqLPwQLhhcdBACj2ELYK4PATET8IskNFJ6E/zF0sq/u59+4
       +EMl8FSe66uHgAd7LaDlsIAiXYzmuddS7m7ZO9zBC1SC79CDP18JPGy4SoWT1SKpQ
       +ruPgM6k+QzEjFrW7bYUo2bC3OfQ4PdC/gNbTCnsLqGwl5rCMEzs2a4dX011l4v2F
       +8UNMPxbWirQnIkNpdHJ1cyBHcm92ZSBSZW1haWxlciIgPG1peEBvdXRlbC5vcmc+
       +iE4EEBECAA4FAkdVcWkECwMHAgIeAQAKCRCvncB0LPbkeUNvAJ9v80Vg3f+5GbGK
       +DBDsfs2OzZq9WgCfQwpZrw96v8I6H0M/1rwBsVYqwmq5AQ0ER1VxaRAEAKZjv3f/
       +AVRbjJscHXS18QUSY6z39SfdJ5XV9yuAoyTd3x9nVNh/vtgssgZDSjvUUPoMBuIX
       +KmOJJFDgu9GkAzyGP3rExlQ8oHzVM2C+2SB/AwdCH0itFbwf3yi4DK786ilTCnVp
       +GlWM0FY3u0S91UrJkdPjzPG8LxHxT1GURUsPAAMFA/4kqVsLhb+VtHAiAJc+DHA3
       +8DSR71qzhgWSCg8K7eBTirVrmTsMGa2zZG/64OepBeXXTNt2aAceqFMFuOBhEiuo
       +s8TWuaem+QVeAWfO7eEQujweR2Zp5xIJrND0vwv7XRoy3t8b9FzNriCBIko7A3yc
       +ewm7vrxDad5MPD3tV5vp24hGBBgRAgAGBQJHVXFpAAoJEK+dwHQs9uR51zQAnjt2
       +GeW2Xrp2816Ph6rpMhiUratcAJ96402EavrqfUvLKEydcvlYbaCjjZkBogRFjmeq
       +EQQA/pG4abBbkIFOQ9eNhr4n5NleKYZg8LaNq2ual6DIn/0h59wZctx/U+eQJGCp
       +66AONlV8I1Jlls7Lovck2FZkVCWNYEOxS79x0BOFBJfVoF3Rx9LKGVLk5oBH7xYl
       +Yag9Th2N/z0WDCMd/lqBIE4t4iBO0qcc0PiYYhe71iVO6YsAoP9VSmV/d2DwE/wM
       +KZw9g3trJNhpBACPtlk03+jI/vZs8v9bFVcC2Ke2zkTnIR4/+a1VGAVKt/k1A7U3
       +74fg+IefAkRgEaARhT164EhF/WqHkj/ORc2iz8OH09/2hwfX8rcRHc2Y71g7OQVp
       +jPhoypGUF1Ma8t7hXQubQ4e0pwCck4CHnPkmEPY44Iu5HYNoPSazYQQnaAQAohoW
       +8NIjO5X3cfIvWKMfdaKKcE5Ia2lVYiBmouXK8/YoGCM9dTSUNzKi039HNFYE5+ky
       +mHHYDeHJ7gxM0SO6ZKtWeTyM+THi6hNzOsm1qIuYx81H/gYW6qhUWpH+B/ZrGEBZ
       +mnxx7AQHM3iNuavXEX5MzhbsvJlI0rsKAJK58m60J1NlbnNoaSBSZW1haWxlciA8
       +c2Vuc2hpcmVtYWlsZXJAZ214LmRlPohOBBARAgAOBQJFjmeqBAsDAgECGQEACgkQ
       +IKaR0R8KHBONPwCg7TkIDum2nhU/0EZUtYcCgA46RSwAn2h5Z21DXpYUPs68/jc+
       +j/HUNdR7iEYEEBECAAYFAkWOgzYACgkQTnBdlP84cennnwCg/DSORJEV+obL6dOT
       +aoV2EH78KlkAoM4yZZ/mdU7JLfIRF7OPhGNMxqiGiQEcBBABAQAGBQJFjoNMAAoJ
       +EHwq7QUG6CVf4iMH/jQoj57uWOZRlQdAB6XuZV20DzeJnAtF3pxwoRkfUvx8xO9v
       +JMP5zQ4ng98AaqATQXkZaPv2MOM9uum0eUgxbaW8h0u+ktfjZS11turKMiMTAeZl
       +vXSW+lGlw7GTZf4PuOSsug0frEclQb4/8CihD+UmlvVHA9R2/i32VytZf53SkCIk
       +DzZmtmoa+l1qvAeJhUcrpXv0Rm6lJA+HeZakhsIxQynDhStdMt0j4llHJFffKCY2
       +KMLG26WVpW4zBuU6I+8DkfMJVFYC0J9Q/GApVLUM2wrapJZqZJb+WfeIdL+u5xkJ
       +4JKf10luNwV5VzW+xvH92vlu/iHa2PTArXd8nc+0KlNlbnNoaSBSZW1haWxlciA8
       +cmVtYWlsQHNlbnNoaS5ob21laXAubmV0PohLBBARAgALBQJFjoMZBAsDAgEACgkQ
       +IKaR0R8KHBNIbQCfUhnrZxpSZILRGis9tSHoFi5pXWEAoMqQJ6cN2lk6MDflIzxd
       +rR1a5NDHiEYEEBECAAYFAkWOgz0ACgkQTnBdlP84cek+wwCfWRQ/RFV1NwsthY1I
       +cMkRLbT/LVYAoMruBdHtuDGuubonw8ab8h2/3CiRiQEcBBABAQAGBQJFjoNUAAoJ
       +EHwq7QUG6CVfYGQH/0ylaTvwkCtiWjdAFOsTZLPqPJIKVTmQ9ex9qfojfSWqbYwS
       +l04SIJK3Bu4w7Omcobi6c4n9Yas5on87LCUMqYbLj4uuNdao0WUy5ORLEnKVvJsA
       +2B6fJ24AZtINWxLl4y6JaadAXgyisf6bgD5VMjGXZabTllXndI588kvefY2wrxtR
       +tnIE0Ad1y9jqywVQQLw8h46ylrUq6iG5+7sUAePYS7Vp2jzZrdMw2mCXzJ/dkOqi
       +mZ7R2mMd8toVxjf5xgCBZi+xUZjZwP6MI5LDq2rwwY3SYuhhpABuwMxsvCg0cwEP
       +bzFFEvAYPvG1A6DIduez80KS1kpRGTRPv5Usl025BA0ERY2m4RAQAPkYoH5aBmF6
       +Q5CV3AVsh4bsYezNRR8O2OCjecbJ3HoLrOQ/40aUtjBKU9d8AhZIgLUV5SmZqZ8H
       +dNP/46HFliBOmGW42A3uEF2rthccUdhQyiJXQym+lehWKzh4XAvb+ExN1eOqRsz7
       +zhfoKp0UYeOEqU/Rg4Soebbvj6dDRgjGzB13VyQ4SuLE8OiOE2eXTpITYfbb6yUO
       +F/32mPfIfHmwch04dfv2wXPEgxEmK0Ngw+Po1gr9oSgmC66prrNlD6IAUwGgfNar
       +oxIe+g8qzh90hE/K8xfzpEDp19J3tkItAjbBJstoXp18mAkKjX4t7eRdefXUkk+b
       +GI78KqdLfDL2Qle3CH8IF3KiutapQvMF6PlTETlPtvFuuUs4INoBp1ajFOmPQFXz
       +0AfGy0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2Uk89PY3bzpnhV5JZzf24rnRP
       +xfx2vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa8L9GAFgr5fSI/VhOSdvN
       +ILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsYjY67VYy4XTjTNP18F1dD
       +ox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMI
       +PWakXUGfnHy9iUsiGSa6q6Jew1XrPdYXAAICD/40S6qQTAHhmKvhVWYkk+Kuqv1Q
       +ec1hz1rjr27yTMc/3Knx2lcCu43tEWUCA6H9Y7+GK7rmPr0pIAGIgZmHwifVVrdK
       +dFm7ftnLei06f1DAzCK3zD5I7oDKF0CgCdWQiOUDYUlZKzOtuSqIZm3GMl4SuRZb
       +Z7oRzyi9mulEFoEJLY5oPPUpVFl01z3wSjQPXIwMx7Ezptq2kOsI46w7IH0lW5/b
       +pTrXVZEcBGP/zLKj5qNA/4/1l8yCGbfKzPwli0bp/zjvf9TohEKalIQLQZbTbKv2
       +q3qpQMN3kpO85jdnWMYxJ7HVfkO4YbTLqcTKrOw5OWzVcMXyEm7WBWBiC090T9rH
       +J8/Vzwd4W3s0J/c1j77tDVMThsKvZyVBXnFOhUxnGaTORq6nB/7BiGy74FdPTYBB
       +LtQNGQWTYZUz0VAniZQpuRiIEDxStuC3SfWiAvmAM/KEPiYyAZ8/9OLQmqAyg/Xh
       +b7xhz1hpFPT9vcBIOVuON764tFpoUPwqMatjRCpa8Eb9JqRhPboesm9GtRdC4AKb
       +WdxpIoWpdb2aqc+GUu4BdqmsY1zcrIpzf8TB2E9l0+luVsr/nBrVknNKLcCKYr1h
       +UhrvuZuIMgfdnpKgKicmeDI4WiRQg0dJv3rj2PlC/Ou5ShLgm6RUVb9a4SZpV5P6
       +dGuWmFZb4aWvTTUapIhMBBgRAgAMBQJFjoLVBQkB6m4AAAoJECCmkdEfChwTM7cA
       +oJwEwI23LH3YZB99ugfba7KOvJCeAJ9O9aAr1mwc64End2HvZlaBxnRVv7kEDQRH
       +XwhhEBAA+RigfloGYXpDkJXcBWyHhuxh7M1FHw7Y4KN5xsncegus5D/jRpS2MEpT
       +13wCFkiAtRXlKZmpnwd00//jocWWIE6YZbjYDe4QXau2FxxR2FDKIldDKb6V6FYr
       +OHhcC9v4TE3V46pGzPvOF+gqnRRh44SpT9GDhKh5tu+Pp0NGCMbMHXdXJDhK4sTw
       +6I4TZ5dOkhNh9tvrJQ4X/faY98h8ebByHTh1+/bBc8SDESYrQ2DD4+jWCv2hKCYL
       +rqmus2UPogBTAaB81qujEh76DyrOH3SET8rzF/OkQOnX0ne2Qi0CNsEmy2henXyY
       +CQqNfi3t5F159dSST5sYjvwqp0t8MvZCV7cIfwgXcqK61qlC8wXo+VMROU+28W65
       +Szgg2gGnVqMU6Y9AVfPQB8bLQ6mUrfdMZIZJ+AyDvWXpF9Sh01D49Vlf3HZSTz09
       +jdvOmeFXklnN/biudE/F/Ha8g8VHMGHOfMlm/xX5u/2RXscBqtNbno2gpXI61Brw
       +v0YAWCvl9Ij9WE5J280gtJ3kkQc2azNsOA1FHQ98iLMcfFstjvbzySPAQ/ClWxiN
       +jrtVjLhdONM0/XwXV0OjHRhs3jMhLLUq/zzhsSlAGBGNfISnCnLWhsQDGcgHKXrK
       +lQzZlp+r0ApQmwJG0wg9ZqRdQZ+cfL2JSyIZJrqrol7DVes91hcAAgIP/ja7hTFA
       +iJcFdAyC4SYbKpXWGrE82LjEIrsThMUM5bOBc2k7HEMpvE3vcQRDZDacB24P7sVS
       +q0uGDqRuz0Uq8eZrY3CGHqV0VuxqQU4yftaJLz9rWIZxvBXxj4JQstDrv33yx+Oy
       +YA8qTiiHcIZSzbh724kjVyDIokVPCjE5djN+sRuzcp9LfPYmJyRCAh5F0kSGsmCQ
       +TR1Ula30uFOCLV8HXiux4InnhyZsou5LZgqWVqVptibpybmDwy9GGpeR7ZW01OGC
       +xzbccyAxKU0AlSw6ZwKzzYmxCb+p4poAZDl4pgeA+jOkCpGnrGTiSRG4GauPyz0S
       +0XovAabLj0gZVGRVal20vxMmKWyE40SKn+LDWS7gOgtkkn8RqkwtoGkMSpIuvMDZ
       +oq85iVQqtK1d2lGOCMYqj7t0RmOA5veSc0xsx1zAJZUxft3gB15a7uwVe1ocOiwU
       +fEpaNw4mA8bwawZlkMcBPaNPcJgRVnwB7O/Pn67alHrm+W1t8vCp5EDNBYvNEIBY
       +65TrzGXcNnvX/IM5EnptiJIhh6yrjczJ675a+Tl1Xbz7WES3yvd6L6xG+mPaLA7/
       +bztTgBty4Ud5vqS+jQ3GZzBxXIl1mmEfZ5teHx/nKV8bECc+BpNjI7ROuPCr5XtT
       +W07CFhEhlPswLTv65is3Gv5EOst/a9cfQzlciEwEGBECAAwFAkdfKXsFCQH7kYAA
       +CgkQIKaR0R8KHBMETwCgu0YZbg3AS4XR7AY6qh9AjSQwRPYAoPsQx3ErEsO28F5S
       +rfKzAqREndZVmQGiBEZuzf4RBACq0Xi/LlL+REsydXGvdXeac+O4Twc5cjBFxbzD
       ++eTW+XEA4mKHa5KygSSSjdj+M6drMsihAABxy7AA98qc4HsW0E+wumqqAHEn8JgU
       +rf7Ipufmg9+XnI+rzCcjDjIsvuViNS5lr9HwBrcX0kexxY3wDTR2YKMkKoZYHvS1
       +poVXvQCg4aIAzJlCj1KkQ4d2pQCzCk7C7jcD/RiYKUl0p5m2AoJRlMthnFbcGhEP
       +gX2HL2EL3AAKIUq9kaHvFbet371y/jWThwEMAx+PmvmEIQoBs4FoZJJgt3SA1bI8
       +aao1cxmypn1f6yus/ZdvRZ0mdrLdCyBOgPC+r/CZ0S57AUDWdma1dXWfVzJyINAr
       +YE5/vP1uz5ia1qQKA/9cD40Uxe+GjRc6gjOZHvlAF6xBvUzrmmXnWzBQKtyJHTaS
       +zVGh5EhvW+IUtVaCXwSqv8rbW1+kpHfPf8RhQ9vJWv/pPROhlVT96G24YJ+bMQ8t
       +sGBoN4MrM4D20c38MZRZ/fGjVNDV7K81fz1S+6lbOT0M06zmMHu2ZqLXyePe+7Qj
       +RGV1eFBpLkNBIFJlbWFpbGVyIDxhbm9uQGRldXhwaS5jYT6ITAQQEQIADQUCRm7N
       +/gMLAwICHgEACgkQWoWKXlScx32wzgCdFUHuXW5rc3OEq4CggvrDiaeqIRUAmNcD
       +I8geoVQ5SOP0+lX4sgcqz4+5AQ0ERm7N/hAEAISPDvKIGX82hL5xlbGz4W7Nvm+/
       +TsGXGrfFQtaOBltcomuypPWBkTwYuSGMEWeg7huKNxNvw4SnciXCqGwilQ7CMzyH
       +Hhz2EjqdYGuZp3zOF3vPB0wUkSva/48esjOONs5DWVrv2Ey4PUaoqLYLTH5+F2+E
       +S2BHGRIfEEGaJWPHAAMFA/443vwvDX1eArKmie1QrexenBH+tikwHrttIxB8+yhX
       +ni46cf472BHem00kE/oJZzX9vPouwVflj5ZYO2oulDNOfwCSoXHskTjIxDYVOSYE
       +hjrHxe1q3Y8F0ERhFmvDRSk6hJUJO9pwcBtd34iSdWBrF7qhHib2lfCqsYdFpE9s
       +NIhGBBgRAgAGBQJGbs3+AAoJEFqFil5UnMd9TVQAni0lynvEpQQV4Efdd3wqNScz
       +MajFAJ4kXFRvhmPzeYp84hMHvTNsgN6YwJkBogQ5BDEzEQQA6sGrQZoAv8rjpcqq
       +8xS9baAMw60oh9OnmZaPHgkY/lKsOpUrtEccYUmWgVCLLqqIERxYrsVPkalImtuN
       +bxI0jdMe2Vfi4qU2XNvNlW9D7g7+3y9i5RM/EBCTM/s6TIyAkRVTYBxkb4R1Brtf
       +IvQU5s4oKcrjKTMMJQdh70wTuAkAoMDT6QfyOOWuD2dvs5mclUFLgIflA/43ujnb
       +qE8MKute+m1H3LwrVR/Qz+A8KAoK1cHd3K/SqEfYTu0wBi+QIe3idRr53UR+yjwX
       +7hOof5DAqITYChpbj5+I3uryejdCfzt2r/oydZhzdkyJjqdPlRVxT5tQO86gPzFo
       +Dhuw1oIH5oLmfROk7gG3ziL8vyrKp47e9CcnpQP/WMih+eo7gBmB3R2z0EfzQBA9
       +1y1LnPFM1zbi+VTQA+NEn28VaTcCST2DN3wNkWNCG7DHnyr6LZV0ZCmR8xW49CnJ
       +5LxdHdFoV8woExHcGMIWkECc1s577lc6ptfBmaKJn7G7IH2B8Hw9Agk0qlY9xpTE
       +1xzuqJe0DsOvRxpTWWK0IU5vbWVuIE5lc2NpbyA8cmVtYWlsZXJAZGl6dW0uY29t
       +PohNBBARAgANBQI5BDEzAwsDAgIeAQAKCRBos3tosWhf52NaAKCjS4nyqFvmq85a
       +5HwGPHhTBhGPJwCdHrYGFeIVOh8OJJURvQiaIRNRG/W5AQ0EOQQxMxAEAL5wXBX5
       +gxZE4MDaUDE9TWRwo6VnE6dUvu6Ia45OhyAVDp5AoquHpJv7PvhA/nLiDFJspm2e
       +DdLglaUGcDIt6MJEbXV/I9v/qQ7qnjh/Cm84gsss+uKTWZjga2NRZ/Y4JGePImLW
       +BlmapwPoHBhJEXsdp1zl/0DiDGmHdV12xPHfAAMFBACB12J/HSJznAwpGsIB03Nr
       +Bz2Iw7NqrhepSfcExGiWrGMJnAjAd98IC84j5AYwMhGWMPmzcNqdcqWEI9Z2cWd0
       +nXndt8GJAUCpfEb5T2snTnoqaiIB4nYqvyG1HwBM7OMXw9k13smo+5PgE3EHyQ2p
       +vIuAMoOZz6o/zq6d0xH6Xog/AwUYOQQxM2ize2ixaF/nEQJVjQCglxecIdrIKQUA
       +TXtJdTfdxzdHWqcAoKlVmQpu5BKmFiAzjBFdyJhakCjLmQGiBETi83gRBACFpGxe
       +3jEId9+BxkDWr3JTQMtZkzfhN8gXxfSS0RJ6xkNVuTZTLevHXSJpd4/wW9rvI1nG
       +GAWjiFXFQf4z+ywdqtvLEgNX5raoE4YOS3vFXymLqImYpmUCtsQWV/VCg/dqAcB6
       +aoLjaxZwEyEymAA2aapdtGI99wOrW+8uD5HfswCg0u640iNKkt08KfFa/HAXT6DN
       ++iED/10fL154ikD6Alslh4qQ8sHa829Sukc26cPTKvTUk/qI0gJ+yHkwzMUM8tT7
       +C87+Wdl4suG5FxjC+oHSlOepkzAxTfktAK7WzFKMT+cD3VFhpe4t80JjQ0OvODA7
       +Gq5qDfWCvRMYIk1nWvQpW+lp8f9rgC1+nKMU9DXhusbBWRZNA/40D5q3VyH2FnH/
       +I91gvwo0G9bp1GW8fX2VUInFEcv6i9OzoUdNtORcpGkqa5lr2Ov2IvjftX8mflpi
       +3idzH7fWFJYmYEU4erpugYR6nBmesHH+3TARWrVJlZCj7AsHzzDBqgb7GMF8cFVo
       +OSpDHsGZAYpKmJBRrJpS4cv/5XcuErQsRnJlbGwgUmVtYWlsZXIgPGdvZG90QHJl
       +bWFpbGVyLmZyZWxsLmV1Lm9yZz6ITQQQEQIADQUCROLzeAMLAwICHgEACgkQIA9f
       +rhQCfW+j8wCgz5A/rl5hpISgJIJgMaNDSCrLYiAAnj+5gDv0SDPhnXMvhe2WcPiE
       +E8gXiEYEEBECAAYFAkTi9p8ACgkQCIuK77Iy/P2C5QCePXakj8AlSyvG2hmR7fux
       +AXFS9LUAoPY13UwP4f/xHNsNfUbyeogg1pJquQENBETi83gQBADtl6FCkJkfNEMQ
       +ER6ZomVaCh0qKH2Z6HIsk9c5F3VOCi1p8l7gdtYtSqjjl+NT3JYxuAcocnaYrlZh
       +KDYL5u5zZWlnlj+zGKAvZeJhb70IiKsvJDAw7FJoCXZAiKq7m4hVdf+jpCqlFAgn
       +zypZYeFjq+TMyUxorul1Xs0elUAurwADBQP+IS2UY3g/Ri7LjnxykgO+NIfYvklu
       +TP0PzWMUIdmFzOeaoZL96AxdCWId0R7VSJs4Lxt9w4ChbGsNO8vz8xVUQUaZQwQ4
       +beJJrdEuNNtRcc/DGgn6lVJIfdY86AEGAeg6T1hnfy3eLBlViLO8gaAxgd4zDjPP
       +VxWYaru79mq99ciIRgQYEQIABgUCROLzeAAKCRAgD1+uFAJ9b1XuAJ97sp7r3oVA
       +OXcWxwL4ToQfYvA6NwCcDPuO1I4Ibi3pZOU5ojHWwzf1mDeZAaIEQ70/UREEAPJ2
       +L1cm7UCWusKySO8hyKNFbEKFYsNE3OhGRbj0w3bf4byrcdw4iscim8q5dV8KlhQ6
       +r8ATQ0Qkl9ZvzSjonjcab8PZhEpooITHokGJtHoWvHIfTNsRnbLbp7FEbgAjq+k9
       +8fDVg6OoAd4p97x3foT0s4MPdM3iKZo0HG8VmvtTAKDbIMZPFfVVLjmPbRPRalbr
       +1ThgwwP/Y+U6v7LWNZgRcU2LmJfVnpGDN2PLpQkY4O+Fw/l2KOKsQU1uCR85iv2Q
       +wi7LI1bvm7PZOneIRnApaNPcv12nP162tyfyTQ8rWxxHxljFcGmga2CdChS8M+BE
       +Cyj25U+bcVHy/atzmUTuA8MmuTrM+3UzyFNS+Vde8wOJyFeEWsEEAKEw3n6599BP
       +8LOjrVb/cHmCb3Gy3B/tI872dlXD3dqIzNpYz1ogCswaWlNSqBOTX+bcV8Jk2Iq0
       +L9Mhhsv7kxtynkQRC5v1MnyhCd9GyMoiVa9H88pCS02kH6qdxqQlCrEjj1bHo8K5
       +G5z09EExoIq5lFxPm/GHY8CfCWQvt9QCtFsiUGJveG1peCwgYSBXaW5zdG9uIFNt
       +aXRoIFByb2plY3QgYW5vbnltb3VzIHJlbWFpbGVyIiA8bWl4bWFzdGVyQHBib3ht
       +aXgud2luc3RvbnNtaXRoLmluZm8+iE0EEBECAA0FAkO9P1EDCwMCAh4BAAoJECDk
       +l9qbPau2yUAAn1VJTyxqyH7LoevqOaoF8IEY47miAKC7Gg4b1/Vd+pDKpAoM2mQw
       +9UMxm7kBDQRDvT9REAQAn08QS3kGhMtImphzqL3gf7b5kng4N8cGMxsjRF2H9Kpl
       +kJ8TnG95TYVy9qHYqfTgXj/UY9esKdgJaezUCgs3C0rnWoIP2GJtok6KAJdq+p5Y
       +mvfCr3gr5MoAyIXpnbX9NVp4THbss+Pba9Js3d4B/3TO4UleZD8nx1msnrUovccA
       +AwUD/26y3qla6MofHPCLnTKnEluAATcBkW/vw0zOvD1MqUrTY3gSsLvX53Z3jSGR
       +Gy7UqcknnO2nA9lc80sIQH+sa0yelr7QuOa5UzNxWoB7alOLNqP/Di/zjTUD66f7
       +QgQ2yMmLqUYJlDTBWAJSd41GLHHjLcLfpahieV6Osd8yRpn5iEYEGBECAAYFAkO9
       +P1EACgkQIOSX2ps9q7aAAACgr2updzcFKIhEuw5V+iwXtyCbivAAnicgYFAoAVaU
       +uT4RV/La3pC7gKqQmQGiBEc9hAkRBADWqbf68PUU0mSUrAGmGDcFy4QHdTw+P1rE
       +qqG1cBZ+JKJlEDzTLR1wj/OdhFljfdzoHPDfIcj8U4Ii65qjeC5qsf2pfa3GVb5B
       +L1EB6vMx+KpOd33P9ntsnO7a22c1FQG6vxdtag9eCRs1IJ/22CKPhM+EQVZvr6Th
       +ANXBBv/iwQCg0pxL9GrCXsVOMy+IcDVt1qpQzxkEAKqi5BCW5xcIZsnaiiX9LnIW
       +iIpk59gt5lA1y/oMFHh7r3ZobG9Rtq5LYPGTjwhC0xHRR58rK6rQ1Up7atL0N2FA
       +k/4JI7GKqv0r0gaKEhD4U4GIHoopoYyVSFBMARcJ0ojOCI/39u67KgYF4W5DSlWy
       +qiECeusk4MPaHZa5UpucBACVNjH8PomcIPNaPIRCY5eOmLWyPD8MvY9wiDNOZwNt
       +ZcaZZ6HMv74dee1wvb3Vc+6fREkzixQoAEMLS8ykzeGPTJx6bDy9Aw40MCGQ3pxh
       +0hdIdNtVzP6AFfynOdyxlwiVOAMFlzZTRZDtSRzCSIwuA62kMGAMmIh4ED36zzHu
       +jbQxaHlwZXJyZWFsLmluZm8gcmVtYWlsZXIgPHJlbWFpbGVyQGh5cGVycmVhbC5p
       +bmZvPohOBBARAgAOBQJHPYQJBAsDBwICHgEACgkQBbYlqFcKhcDA0gCdEoMrBBTj
       +G60c8Y1ZC5tyQAkoJBsAn0GtiKLl2xw4XxRa4jki4jmeaHszuQENBEc9hAkQBACs
       +AiZmkzKMKAzE5544Ht5n+iJKRvoGvEt98XAH9m5Gsyqg0RG2YWVknkPmcn7Vi54X
       +AhIhikbGkzPadM4rKedWJEfhsqWot9i0voHWdnmsAVz57m+IVw1bFpaHNkUK93Va
       +OpTaed/OC9c2WjwgPKvqx0dazoQTIstBetmy2TCkYwADBQQAgI7qh2YefZCg5W6Y
       +bl4qCf29TbexTmv7zBS4LwP6WK2/hY/mgRseAooSSiTdH8H29E9caI7K+ab1GZ/o
       +xA5b8aujzemSblUIFPn+7yz/fRWa3ad/yp/2rW3woO9ZRzqns9KdzCrmaZzXCBRZ
       +ChdbeyN4WA9U4lb0u2MZrfWwbFOIRgQYEQIABgUCRz2ECQAKCRAFtiWoVwqFwEIj
       +AKDH1tGeBKFNFzrqnRcCxfvRpyG2VQCgqkVGJeKtBChwAv/VE4ioyytXSf+ZAaIE
       +RCMbPhEEAPkWuZjh9iiiHlpomYK9HpnwLcO+HEFeGaId6yyzC3oqjC/anm2Z1UaD
       +tcyOfN6HLWmSL1R8H5tJ1IWG840fs2cr1douWb2EnyF0I9IfkmD02UHqkw9/x0kU
       +E1Wh88BoTmxVMIZDQxrxb2MqHQtKkGDSmOSflv8+JNkMIqGlI3cJAKD8kOxIdHu9
       +4fpVjZF0xs/nCDtT+wQAjysF4J5zk84RDfVV6W/vToO/bhJMClahUw5xbTQoICNR
       +jnrBkpsz89r8CNr+3T7bWtiwPMvf6vZg91zr7/j0WC3K5aaUgmoCS/tqd+acc4Jq
       +ewle5KEotuzNgC6t88/qKBqH8rFgER9M+krrZMrCLGVQm+59blcU/30zScBtiWAD
       +/2VPlBOu0+G64NOWXOZoUGgjlAsiRg8WTGM/rT6K12EMnqwe0yxDhLTpt7MMkesS
       +qMnUpZ4qpb5lyddb86SVumYOsFGaF0xO4WZQ2Lnv2uRU93r3+ilvxZgKBeXNrvMd
       +Ot74dH4E/3lpBV1Jsk/BVhrPL7B48czK3urV810pcQyvtD8icHJpdmFjeS5hdCBB
       +bm9ueW1vdXMgUmVtYWlsZXIiIDxtaXhtYXN0ZXJAcmVtYWlsZXIucHJpdmFjeS5h
       +dD6IXgQTEQIAHgUCRDu9VAIbIwYLCQgHAwIDFQIDAxYCAQIeAQIXgAAKCRBBy0pV
       +rQZ29PcrAJ9INbYdyH/x2RN+/ngpXLI8q5DF7gCcCugv7jItThdGS19791urbRjo
       +2QC5AQ0ERCMbPhAEAPw2F8c5MYPI5XyNVqXhwdZBcqO8DusajQ8wsGEPqhJKxRwR
       +jW1TWFsbKLQeB9Bf/MEeTVdnoPmBT1ryJjKYVfwL9kFyNnOO+rP0jCSkZoUQvwGR
       +NfuQaSAyxAiRmS1oKQHCHc0wOMhtZGv+DfbnNrvExVSos/x1X/zOHGvT2AhnAAMF
       +A/0dqavSoWLEJ08kapY0V+Fk7p/vRjQqm+ZSfrW/XSeLCK2/Nu01WYpfy1JFdfgB
       +cgWg3hiEEWKwXRMfJ0qqxFYHTUU+8sbKzPK1fudnnPbQcj+oiI/WNXbDIX07/sk4
       +/0zCQpFUNymbhTiSho5uNiEwodWgdaMq0rLB/0iRdtecO4hGBBgRAgAGBQJEIxs+
       +AAoJEEHLSlWtBnb0zX8AoKVySJ+8vMzFEHnfzGIIsjwhvE9tAKC8L+1uaHatK9Ll
       +kJoShJi5A30v9ZkBogQ/aBriEQQA298FnqAxqYh8uBI8/CXP65q7x4TX3vIQQ6+m
       +nI3A3gQn6g4qbGl37AogfXFo36OFwyLXAdyG6bmBKLX8RSwdufFgFC5mIA0LW7Dt
       +Yz04OJY2Lp0XZj0x3qaRRbZ+KBniXCHf7a7OdMfh2XfcZJoOlXSzKWKSxzvDnBo+
       +A8wtd30AoJcGJBWhxdzP7/ePdiqaa0lHKSNXBAC+dFrw9L4GhQLAPxiNHEVIUh5y
       +3mDhQI8SFiF/fxIasDVBBDFnV1kK+JQcznT2mH1yaBEc7sNmxklYNWmGRWfox7dF
       +Pl40xKl9MiGLIis4MROdSJw377O3dOzYpywzEuam3u9umYbf1ZAyHWIgmzzjEcwe
       +GHjJU3TdGsZwdUnXVAP9E+KY7PJ0A0NTu+3PK5SWNdsVF0X0YmuIN+pXlYoPeXh6
       +cM3CJXOWt2h50IDx+ZDiFrXPSu/XxLeAJnguJEiay7YDDsAfutnqY/3NCQWQzqrH
       +tgvfZ+8A5Vu53UL65JHdQPiICjPzEL7ERXB4DCPVR1i4gxGXAtiiAfJo4M5BU060
       +K0dlb3JnZSBPcndlbGwncyByZW1haWxlciA8bWl4QG1peG1hc3Rlci5pdD6ITQQQ
       +EQIADQUCP2ga4gMLAwICHgEACgkQSno89sSngFWEPQCeKqWR/pOpohW5eTfvGFDp
       +jJFfGZ8AnjranywdJBamrX7qbjAe98r7ZkAIuQENBD9oGuIQBACe3WcjE7WI+Lai
       +yzpwVR9VPYaG23Cf0oVvvc4gnNRfSUr+4rW+NolIEsHQw2uZupidoFvTnnPhohQ9
       +gVf1gBzh3v8DotRpnOQML8vEx6D5yE4vmCv4kbLeZDUkLDnfYGvRZtZuwieGZOfX
       +zQtgVZbE1uI+2hSv5GwIOf7Cu/KGmwADBQP/Vz8tro5jzYeOIfUZQ4iFiaFt23Yo
       +IfhBrGkFH4hI9DKopbvOJJmX3pJ+rp5xQf4QVFZIXtGM7DEtd1WgXRBX1xWJuRCk
       +2b+Pq/3cRruM8dZhfuMWl5j+ArvxwH9iVaZ+FSaYPXTE50k96FwR/MIXWSOVLdlR
       +OBBTPlY4Oq/Tjv2IPwMFGD9oGuJKejz2xKeAVREC1cwAn0WD8tDCXsgosUSjjMlb
       +R9xlCbx7AKCTVxJxbxydsM8RW8cLudhJ5YeipZkBogRFBP8eEQQA5Paol0sUOnd+
       +U4+iJULxjGnZe8SgKC1OdQoYixZmoUopUE+526FZT6IUA56sVIT9fz+eo+TMHfQJ
       +QARhGLf40hy8FW/P1G/e6OrlUsb3DxuBQ7rQUwEdhZurP7/iOm7B12TySjYb+Bq0
       +bL7KX+pEFq2dAfznJzeRri/Dah9WmGMAoIaGa+mSr/b6HAImMTebqJjf2u9VA/sH
       +YMDSKt+YQHLVz7UBdCCY6YBMuRLHgtJfjLCrGYzuYKoe5gRYNc2aQY8j37S6rv9L
       +ZRcQLzNmjb1bZb10Jt9e2Z8KVWDwCjEqdkro16zk5jWHl9D3snBcnvz5x0o2krQg
       +LbbNnht/yQlKFPK7PKOUkSkUKabvfFzyzCtuYjjDoAP/eGhgXHtRAl+knslhDUNc
       +X1PMStO1JG7pms+JolPPJf9LpngINwSperiVD+BN34BLDsIHS6EAWhdZrx5HnHXj
       +2TjP6RS3QnNR0fBmgb+kPGntUufe7TkttpHIwJhTZcAcyOdGVEEFjW8fzjDpooSB
       +Rj2JmIF8xDCva9mPhQ5Jjmy0QUN5YmVyaWFkZS5pdCBBbm9ueW1vdXMgUmVtYWls
       +ZXIgPG1peG1hc3RlckByZW1haWxlci5jeWJlcmlhZGUuaXQ+iE0EEBECAA0FAkUE
       +/x4DCwMCAh4BAAoJEOupeiEdI0Q7IeEAn0MBQKjOxQoiL0W5L/JUE7OhYVDGAJ40
       +3dfPXmXz9FtGuzeFmr07/fQK+YkBHAQQAQIABgUCRQUAOAAKCRBwpK/l/pDMyJwy
       +B/4r//disrlTm8tl77uziehjfORaYxwIyeX8zHEzomYK1fYXjTJlBvTg+iyuwB6q
       +z/7RaWrLjaYSYlFFfMa97762T1/tee93KDr1RVuvXwISWJkAY3fyW2IrpiMaRh0s
       +ISZmWDWdEtZg0tqJMkSLXtGKuBNav87uU8YOsXJ66P1+uc0Ix4iK8V7NnpDA2o7H
       +SDY2nibimAk5J5FJ+Bp+wv33Tz4zWyy9kua/x9dT9+CCHY7+lEz88RQwdgee+EQl
       +icBr/sgFWNJwT/69AaiG+UrvnATP9CGjq9De/jI/mA0ISu+52DfE78GWcCSP3an7
       +lbnByMoIbT4h9sSAjnvlUKXduQENBEUE/x4QBADtMW1CP67iwt/gH18wYGsaPCM7
       +JlZ5r4R/VyjOU9mT56shVdlViaChc97S6Q80gAM5ywG0XlgEqKFKfiN3Dn/R/FKX
       +TFW6APCqsmJnn8yoI0CfA3u66/QDIUrDc2MCXpkn+U5md8/ZKTUuB48XTqNudtUl
       +V6Bq3MWoJQsYvs24ZwADBQQA1F6pX6xOlEJ+QOUhtDv9e2Osr3kAtjkE+hQ73Ft+
       +l9HunD6O6JEjNsf37Afa3h2LcLRhDgdaAHoNL7SPw748sg9VHqE+++6f+wR7+QVf
       +mNU73KWh7A5puL/Ve1P0fAEgImFB6sw+X8KgS/ipZ5JAMyCRMCmHiSlkW82wg6IU
       +Tf6IRgQYEQIABgUCRQT/HgAKCRDrqXohHSNEO3sLAKCFnkKjFSF8HkBtKDHxRDZv
       +BrqRkwCbBcoNd+kdamS9PX6VBnn7c65kXZ2ZAaIER0m/zxEEAPxcNvVbw81asXwq
       +wEZd2W6yT0DbVqQIk/xjjPacWtxi+vEUeD0uvVOo3J8KaOm0db3woFuvUEBGPY4X
       +UqJRf2RaI9zXZKmwbsIsP7KVtzfN9OS1HhYPbsTsXQ5GsueB3extAFlJqTuWp+Kx
       +sIrrZNxMifMA87ncorCFyOZ5jPpFAKDI1soBzzLfl5HP/4eoXgN1ggkOHQP/bMRl
       +tWzGM/7TpjXLnAKI3Cq2LWcayh6CaLOYD5XFAHN6xl6t6hmNL7ULhWiy/ZkJfc4x
       +5v+19y768QeVISSaLD0C4WLgjFcOxrfm6uu03ViBL/RHMvNJve0i/THChTxAroy3
       +/SDkH3F4IAiAz81w6blmcsIvs7uIAI4wFvkIycsD/iQAEuFEZdgEbSNYNHcfhDtd
       +Alr2/2e4PvWCjreawGBl4nZe/oF1UjDs1P2AQw2jwaIX7E/BXvEAFvJCHgR/S3wA
       +M0geho7LkvvqNceid4Rchl1JOY+aTFiN/2EZnk/NXBOCpoKL/QO34y73F4ANutOu
       +kMrKVw3nJg5j4Ubx1gp3tCZueW1rZXkgcmVtYWlsZXIgPG1peG1hc3RlckBueW1r
       +ZXkuY29tPohNBBARAgANBQJHSb/PAwsDAgIeAQAKCRBxbu59yvz6UutIAJ9jPbIN
       +wUk8Plr5giQzrKKXizAaXgCfbt5DZ0p5s9iRKOHB2+BqbwxpyZm5AQ0ER0m/zxAE
       +AMWRUGMNcP2OSV6u/jyThopfwRIfl93yqVI1kFmn3MIyD21TSNTB0tefeoBDpwoK
       +PLTm0SpD0oxkKBm50pS59hYM1CCFFAx8R3igbYI9L6E2nL0y+kmelF4Y1dXtSCk+
       +CZjQLRwETKNkx/QraKYDrLHtQB877so+ESrCuceCCF87AAMFA/95QxbHeGoUuQH7
       +Qsi//9kpn0F7KCNPN9fx1eAjlIudeEalBZMPlivOeVSi6O0L5nrk8BmoB+x8lWvD
       +pw7nNaCxS39HJk4Rc/5n+KHjp3M6otH4n7IFPZpgCoWeJdTaXd13Nu9jPi5BFvF2
       +yjjYcUNHs7zrOpe0X9Zj71g/Qa+xLYhGBBgRAgAGBQJHSb/PAAoJEHFu7n3K/PpS
       +p1IAmQEof35Bynpht4Pm2gACqjAoxPJYAJwJnnNnzu4CujMpz/AyPj9NbKPhQJkB
       +ogREwAIoEQQA7fqAAo1ZGj4SbrzFdDyd7j2WmDP4ZHzvw8p/QXArZc8u0ZDgBpbJ
       +4K1CsrG6dh5Gt+F2PXanDexgQ1UOnvRsIs/Q1l1k2uWRnkwprpAx+mRgNagyF4KU
       +s1gDTqkAEtzJo/cU+NUKVTWqPvcbWolbQPaDvNU+u2j5KpWdIxxvR70AoP+nBt3a
       +QDiyhIFPjubdlG3WIjFHA/0dhkp1FegFwRaJOLMxV3xd/tcalw1IVxiTnh+dGtFf
       +zNIZXeKjpCrjYpcJTCLvptnLKifAu+33WpyHbMpbqhW8/ZC6rQagEVB8PZK9YB3r
       +FXRMsrH//mSd+WSEF/esGLtnvGNnjSyzPTiSsHLt30AIrJMY4kyy2SmFFc+CwsOb
       +IQP/QHwc/bMh3HMtSkB8KSysC56U7tCY5sF2PWmzSF4mYTwJfgA4m+U7OOiu9vvj
       +kJNiP4Rr0dTCqNuEn7rOsrLBZU8sl3OuyAox27/VlSr5w043eQgdZTMZzgMeCRCz
       +rHdl0HbEFN9mLEoF8CT5zplsr18Nbn56kh8rT4JIK7Ajyva0Lmtyb2tlbiBSZW1h
       +aWxlciA8cmVtYWlsZXJAa3Jva2VuLmR5bmFsaWFzLmNvbT6ISwQQEQIACwUCRMAC
       +KAQLAwIBAAoJECVTGH79V6HZs18An1wwPLxz1JoHGrBw8wmUEKbTHZ2jAJ92rG+c
       +KzXqI0WQEPFRtMTPztXdTohGBBARAgAGBQJEwBLdAAoJEER6hf0IKQk9roIAoL7a
       +9JPQhJXsqj7QMdouKl1y1Ix9AJ0SBFDaYQSDZkGsucxCAW46kSqaBrkCDQREwAIo
       +EAgA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV89AHxstD
       +qZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50T8X8dryD
       +xUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknbzSC0neSR
       +BzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdXQ6MdGGze
       +MyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbTCD1mpF1B
       +n5x8vYlLIhkmuquiXsNV6TILOwACAgf/aTg+LDZH56vGAjYcR/fytFk/3hEQmUiD
       +LTE8LxVk8c6oY/Bxo+VScoDaQ5VwH+StXvZpkqVoBxGol//sgEhZzmR+tAGLGfPe
       +9b7TQ5QzRGJTZrScmbuJmLxlcLYDYTygFclOKH4A5UWqM1gjv8s4lctA0tsjmeni
       +WhpR7NBLQNF/ry6S2hIG09JccRUg2g8di0wyNq7a8ZxbZPcJtsyGtYYF4Uq6iHMv
       +NiNb6pn9WAGoJMviBoT+B8ig3lIcHyRzM+uZ3nvwtCNZ1YDcCGV4ofkcWbU8ze8b
       +ztaeiLuu95/lB18yG1Xt9CRtXMk4Lf4uk9EIIh6T0mJoz3U70W5K94hGBBgRAgAG
       +BQJEwAIoAAoJECVTGH79V6HZwwMAoIkmQE9NNwM7cufPcmNK6tzej6wVAKD1rJJ3
       +xP3mmfIVDZ4wHEI0PG8xL5kBogRGwlgzEQQAke/5iINeXh8E4uBzdBggay34oY6I
       +DNrwqtSdTmp/Ntsm1YuKrVgaBTZebUNa7yqmunO0HTDxlP2BP5DapfNgPDwZLfn0
       ++q7wPVDkQ7LiIQEgy8xpfpzMCiziz6Agd4JOJAIx6eZv415/A4ZtHZdtdsJcTb/m
       +tjQHimEIpO2AussAoOnSGQkq69Tc6islfT8RyDmzuNMhA/91KVudwzfr2DTNRDp2
       +uNtGXu5FB4uQXXyzDDzg4V/dRmM+VXU+iLSJyAKsl5tMAfte6P2A9ftvULKxc7Z+
       +CPnmYpm4Dv+1+Gs+ks2CVAjGMl8vWWBUPmdep/3mfc1GXAaMKZnTanE9rSgUn48M
       +XFSyMnOY0C7ggRGuvf6SvFxOwAP+OcaNJmGw2qYbNX8+4Yjhwbts0Fn2gTOpNdgR
       +3Za1Y9K2Bb6+5lEI5SmUqWcUEilSkPJdFzuKN+O4r951tbHIuVwWt6RTZv/Ad0eY
       +oTeRhp3oLN8AtWFf7YRyJyVh8GNYMOwM+rK8DoYF2xw5DV9S3W7juuQjzRFLFINv
       +TVq+9Sm0Lkhlcm1ldGl4IEFub255bW91cyBSZW1haWxlciA8bWl4QGhlcm1ldGl4
       +Lm9yZz6ITgQQEQIADgUCRsJYMwQLAwcCAh4BAAoJELMFl6twH9bPoeEAoNwVRp7k
       +GBM560viVT2odDatszwFAJ9P9a+enfJuU8ZYdO9lPbwGFKzC57kBDQRGwlgzEAQA
       +3zPltPrA0lt95bjMXOnoRc+sQdfry0n3XR0ZR3J0McvmoKnv4GrXs1IUJlwNNWLj
       +kOSDNHgWly/4ltRDBH0+PY5a+DN2cswmSD7gZSy2ZNTlXF9JIpSFoVQ4lle0SV4e
       +QQgepKvy0bQVbmxKix/QPt0gz0//m0081kbNaKK7tUcAAwUD/RJy5bIduvZmnZ02
       +2sPke12d2Vx7uQq7HSpJnzLSwTjsalenOIicOL3grqIh+fpQ3Iuo5ALX2nK+NimZ
       +GRRG/7vjCe+euaFjY64/l7KMrxN3ZLWMeGP7adrAnAMthocnE8AQd2I+MhD1KHkJ
       +nkczdPr4lOU4V1T64w1wCGTNvobqiEYEGBECAAYFAkbCWDMACgkQswWXq3Af1s/9
       +/QCgpIubBgnSZ/W9CMfHSXZ9f62FQAkAn2Ru6RFwflne/v1F/auPKxGqri7EmQGi
       +BELKVDERBACCXzXjRgJY6ZBZe1WJFBCX4Z5OrDhXJnu9fgb5H+WE8fPH9Q3z9M63
       +GulTIK5lyY1eI+IfTJK8slPTnkWpaPzr0zFTgVbfXci85ZzGzn3m94Gz4PTYJiZr
       +7SZ4k2UH0cPOSsOpRU01a9eiypB4o4pdf0ipeWG16cWRNraDSuFa5wCgwagHRCz/
       +ztNPWSr3yAB1GfgqK9UD/0m7QIVcf74FbAMwOxqMvYAS64QZMvtoXZ9Hh46oi32j
       +GK13ksxHxCFAUohKcFLrIIpdOO+GKMavh68kwbl8JgaDJiy+GLuSzX0K55Q7pkEq
       +3vB0dN7EPHuQM8vEcQz96fUKRq9JLpM5WCP7EmWTjARlMCJiYkffRdyFUK0Zh++c
       +A/4o+0smedWdD3Ld63bnUuKXfkx4V8GsqBvxlTCAeLkSzMKPPtYCheCG3+hPoE5K
       +iY4di5mEMO7uU3dwKkBodVKgrBwAmlgdhAoOIDAkguHatV7dIZunt6EPZ6oDTzmi
       +3phChQtofZdQJPdp6ifvCcYp69Yye3jQVrm2dlUAiFx6wbRRIkFudGFuaSwgYSBX
       +aW5zdG9uIFNtaXRoIFByb2plY3QgYW5vbnltb3VzIHJlbWFpbGVyIiA8bWl4bWFz
       +dGVyQGZpcmVuemUubGludXguaXQ+iE0EEBECAA0FAkLKVDEDCwMCAh4BAAoJEBkv
       +fZuzeVOj6xgAn21OWrlqTrR/CSnSw8BBB7ZP57xYAKCePTdohLH0kdkdh/psE+bb
       +N3WeL4hGBBARAgAGBQJCyrVnAAoJEKiDmQ0shi+XQkkAn0jqSjMz4+xMLuP2e4d7
       +2gd59JjTAJ48L33dqqcrhY3xmB9CP4yTkjL4MbkBDQRCylQxEAQA1cKAyq2FBK/B
       +L3siU3KJSUG3/ENGOuIEXc664NfmDPe2NPXOvLFsYo/333LY3Ziw2tPYpP59RJBe
       +Kj3YQr6f6MfaHX3U6RsblLUuR4a8gVDLPEU0MW+VdD0axP3ckz/F/CwmdRBOZiF9
       +HNlPMPhYD6MrhFk7QdTuLRxMFrPWrb8AAwUEAK5hVF+sq+5/2+5MP89CW9AdbnnQ
       +gdR0h8LCLQEVf+TC22Wd8b/Mrsh+EE+dNDPlIUXgv8icASUbmJD0QkJVGa/WqMtR
       +XXnxn4Rbx5X0SGhkHIrfwl+SvFVWu3AVeOgu/Z3I0KbnPEmvmSB4zLlcKH8/u2EN
       +RxXS8IynbZYeSK7LiEYEGBECAAYFAkLKVDEACgkQGS99m7N5U6NPVACgi7Jz3sVX
       +nUTjui7r+ZJj2TSNLGoAoMA+pbkWM/Hm097g/+G+bku+y3KBmQGiBEU3lJ4RBACS
       +DLJgTv2BVxCYQFPi9Pqu9n+rYrvbER26Vwg9BT6M1C28L2cnfSu3tOSD62gIfcUc
       +jR/1hFSm3t7f+xz/mhQPCj78qrxw+tWBIJcnk59ikfgqGA2uLGv9kfJmFSkrOOR0
       +chE4Z2uNnBWxHiJQXdMymx49DWSv5fnKPVMHkPgnZQCg041GhGzaqcaMYALfNEYc
       +hNWQeTMD/iqK1qryofG2mdKHWVKL8JRTvSoGMjSJmy0dTsJbZCpotXPrURErdQa5
       +2pdTIZQRJsbjnt1aBeWbdnhXOFzDT0io8DlAp1GfCN4IlvWBoZWJBx1amS2bfK2m
       +8IW0bhuosDC5AK+jvYfVzrlN26gJUITZwBXGJatIL3vqZlPkbrIRA/4+zs33MHYY
       ++R78yNwFEfp1mgy5W91VqGZPseY6y08QrPMHulpEUQxMM5h43f+GMrVCTtOSi0QR
       +M6vJXt9inFRaU13e7AZFDntTAgzLMPjGTSaLkB/VbGqg6FSjGfEhhtQT9PyVeAoV
       +7+S3NGqdgQyWtCLyOP8ZNKP3f27e5TSpjbRZIlN0YXJXYXJzLCBhIFdpbnN0b24g
       +U21pdGggUHJvamVjdCBhbm9ueW1vdXMgcmVtYWlsZXIiIDxtaXhtYXN0ZXJAdGF0
       +b29pbmUuaG9tZWxpbnV4Lm5ldD6ITQQQEQIADQUCRTeUngMLAwICHgEACgkQESyY
       +sVN72UpReQCgw814b7VTQ9kckGo9zEex+O380XoAoI7pIZZayY5WZqP3hDZHFjCm
       +UMcyuQENBEU3lJ4QBAD+zVrXjyET0A7heg/vV/WiVdKeC2k63EJScgY3rrlf4UQv
       +Km7FM5HwZfiJ/XsrCNBpaa00ZrVZUclNY7yDEvxKza3oksjBm0wOShs1McyaHAMz
       +vRT7oQtBbfR59F7jIY4nMvjh9IyhB50e1fWIf7ehopDTiPLvD111z4KeWC/b4wAD
       +BQQA+TIVXqbUpPYCWQ90s/j5W6pyoyU820gx4AdInkG1i17CghjySIlwgQHAAMPq
       +hlwPXsKBgC/9zarT8X2lm2C6SCZq5IFgddqM7dlWkr54z19uY94CTM616RGSxRay
       +tuadT3yhB0B785xuIh3r6LBf4LR0nOQqHCItAaLXctEtJzuIRgQYEQIABgUCRTeU
       +ngAKCRARLJixU3vZSonQAJ4ugjkexR7t9ux48cYs8mmahfgWEwCdHtQKayjicrqN
       +xohUuLs521kTqoY=
       +=NUVh
       +-----END PGP PUBLIC KEY BLOCK-----
   DIR diff --git a/conf/pubring.mix b/conf/pubring.mix
       t@@ -0,0 +1,384 @@
       +antani mixmaster@firenze.linux.it d178ebcb1b259970d8d224c1f53f69b7 2:3.0rc1 MCNm 2007-06-25 2008-07-19
       +
       +-----Begin Mix Key-----
       +d178ebcb1b259970d8d224c1f53f69b7
       +258
       +AAS3PnAAJxD4O8nW3xeTN29HQX9Yg3APRkrpukwC
       +3YxjiDhglUKnLkX+QxdS46IHf05d9ISJsF2c/M3i
       +1ftd4UdoJcRN4OgnQ9W0Qo/ZfnFDYEUNeXkra7XK
       +XftHkp+C2zAN7STWWuw/1YHsY6D5Hb0zOXTJvlA8
       +DBCxKxJmtlhAEwAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +austria mixmaster@remailer.privacy.at 1a48dd7e5f9740dfc174dacdcbc673e6 2:3.0b2 C 2007-03-18 2008-04-11
       +
       +-----Begin Mix Key-----
       +1a48dd7e5f9740dfc174dacdcbc673e6
       +258
       +AASxWLMGH4acTiKixL4effVMcfsP3d39INxJhrpH
       +xqStsBGAzFAdvURRyt3q3reYIMH/K4YBFwFM0nMm
       +I6egh9N+IaYmqck0A+GFxwBDDFdqFz2GNhdBqr+h
       +ahEv/BbNP3LBSIA31m4ElaYFfc7ebZqmAKIxUioh
       +pc+G6t6L9hgtlQAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +banana banana@mixmaster.mixmin.net 67e7628c4e8c10f4bce3da58bf2f8bb5 2:3.0rc1 CNm 2007-06-16 2008-07-10
       +
       +-----Begin Mix Key-----
       +67e7628c4e8c10f4bce3da58bf2f8bb5
       +258
       +AATDpYXFPE+/Zol2PDUS+Y4J2s6SbNSDpNpMT8GS
       +QeogwFBGS6FijkL1xWX8zGh5DE+VOLT+TgW6yBNV
       +ZB+VTLLmL1rrqeE/ZIP2mcL32bU3yVmaHCN38JYI
       +3CmBqhUMN2gTlhZF2MMP3mr79HmnCr8OwU2YrTjV
       +4WV96sbnRXc3OwAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +beton remailer@hyperreal.info bbcca4038804c8ebbb2b92038a412d8b 2:3.0rc1 MC 2007-11-11 2008-12-05
       +
       +-----Begin Mix Key-----
       +bbcca4038804c8ebbb2b92038a412d8b
       +258
       +AASuV2OX69CDrwpS/gJ+Jz871GnoyH6KK90dXz4i
       +DzDTZ1FZd5oNf3kT07DAaLRVUzodkMKHFbfMvqT/
       +/jjdVojbtntmNHOwkzKj9UMxu9v8XLB8+Lfw8Kqi
       +d3nLZyeTIRoVEP0Kl8bY+9hxKR91QBYhcdvAvn3j
       +XWhrzjnTB3fyIwAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +borked remailer@pseudo.borked.net 46e927c921aacce16986d5e0ec31ac4b 2:3.0b1 CNm 2007-04-20 2008-05-14
       +
       +-----Begin Mix Key-----
       +46e927c921aacce16986d5e0ec31ac4b
       +258
       +AASnFzxxJrV2CDkw0z1q3MNKx90nkI51y4ZEad4n
       +y42OkJmuW8y4uVfVNDc7SUMW6eQRISR0oRgWY0IQ
       +PyuGLLTZZg1BW429aUa0VqK5uwYWCcZEuiUkQLUK
       +AjMM+8rE834vuxWg1/K9zr3H3NJ2vMm8tHoHIqMK
       +/vf1Nq770RqjawAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +bunker mixmaster@mixmaster.thebunker.net 0bd3320d57af38db5ea3432df2bf1f9e 2.9b38 CNm
       +
       +-----Begin Mix Key-----
       +0bd3320d57af38db5ea3432df2bf1f9e
       +258
       +AASx+0mGBuPSJicU6ZauDWU0GClmHYbPY9EfF8pU
       +8P229q2NgUTok2052HLAIEKMpnS85gS1eHvTmOIi
       +1J368PRroRGD5HzX0fhXbkpzmp4we0IJeRIdMCNC
       +DIwnzu2wlXM+LSxYnXOKzIP8W9CL2PDYdyzJ/+/P
       +2X8l641JJniJoQAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +citrus mix@outel.org 310b8456beb23663965c6483fc45aab7 2:3.0b1 MC
       +
       +-----Begin Mix Key-----
       +310b8456beb23663965c6483fc45aab7
       +258
       +AASyTIuWDEit5JGL5mvdfU2tqaBQNU7Lr35PA0zE
       +yBr6T5Hz35/8ojQ4h00/hDdDS6D7196qb7k7p0Gs
       +HV4wGjjgOX4mTRKB7KU54DE++OUqXL7vSRrVlAXr
       +7vNDDRoPXfwRurR+umvwjrVaqNEIwgGi/aKOO3cH
       +chDXYzKwXJt/9QAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +cside cside@cside.dyndns.org 0a7c90daed1c97235e3b3f80b7a0c32f 2:3.0rc1 MC 2007-02-12 2008-03-08
       +
       +-----Begin Mix Key-----
       +0a7c90daed1c97235e3b3f80b7a0c32f
       +258
       +AATB3o78sdBFzcpZqYKizgveaSqUynPS3OObdWgX
       +27dzplSAV8smR/A55kAukgqKptlSAB6FxxbexapI
       +YXLz7p9cpH+vTWa6HdiWjORxD/bVEK7VghajRH3f
       +WXPhjD5npcYy6UhOFi3b045Sc1ddhtdBzJfUmZPB
       +q4aQIHqufTL/kQAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +cthulu mixmaster@cthulu.joatcrafts.org 03395f366dc6a70e673ac5d548ca8ec1 2.9beta32 MC
       +
       +-----Begin Mix Key-----
       +03395f366dc6a70e673ac5d548ca8ec1
       +258
       +AAS2XJa9bQHEjEb6FfSOaPnfk95nxQEVeAF5gpGA
       +b8Y9vr8z5qaoNasBmNctbVxL0MN4VmVxtpFje1pl
       +eB7BV7O76rH2c1InKLT3brSYUNGLWmFTqbwC3CQl
       +GaqUmmfJTG2g4OC3LvA+CS+1h5w5Lz7zQEsP6h7C
       +CrBg6fpWBXmYLQAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +cyberiad mixmaster@remailer.cyberiade.it dbf45caec67b765aac8d64f6ce5dd2d8 2:3.0b2 CNm 2007-11-07 2008-12-01
       +
       +-----Begin Mix Key-----
       +dbf45caec67b765aac8d64f6ce5dd2d8
       +258
       +AATfA1FNEh9K/bPsz+6xguyZXIQo1zzLw2/BXBvI
       +BehyJT5ay5AROUVFxsAxZJFiUXrOniSIzBt7l3Ac
       +vE2B4KTAf54ScJk87rSErY8iP4sQeMMZRSdU3Cof
       +9qVbdDQFoHPNJXotNCY8iuGA5wrxK/faMhq5KQcd
       +1uJzS0Pj02spkQAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +deuxpi anon@deuxpi.ca 43d6f1186c5193548c8b2b38fcc051a5 2:3.0b2 MCNm 2007-06-12 2008-07-06
       +
       +-----Begin Mix Key-----
       +43d6f1186c5193548c8b2b38fcc051a5
       +258
       +AAS7sg8J+q0svmNi6lbf8ywZZEWGG1cScSDQqDsy
       +NjgMAzj7nzfjdrNBXdxH6K+uJVT37xJ6TGELDMnA
       +WeBb6K1ICT5leFMzOnmO+ruzOCOTkFVXMXntbqz0
       +CLO+Wr6yw+BF6jYr2nNK1+phiF7zqa+2yDrihife
       +pYOJcTKFDJEZVwAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +dizum remailer@dizum.com 314d6e1d1482e73781925562ef41cb56 2:3.0rc1 CNm
       +
       +-----Begin Mix Key-----
       +314d6e1d1482e73781925562ef41cb56
       +258
       +AAS9utvoS0r+9TmLgXnh4Al6b4BYTL71JVIg6SJ/
       +RhE7KAJTxrQDV6JmTfTtE2IwvPiO6KbbzHk4LMwP
       +EkFfFi9sIE+N8Ced1QjfgWt5Kr7lrVARzIzUi9B4
       +q5Q7XxJ1ttS2d+di2CvuDbREjZfhN8d9cdrwElD6
       +tCWVa8GtwkrA7wAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +eurovibes mixmaster@eurovibes.org 9abe18b1fe9706f477214b6c25d815ce 2:3.0b2 MCNm 2007-09-01 2008-09-25
       +
       +-----Begin Mix Key-----
       +9abe18b1fe9706f477214b6c25d815ce
       +258
       +AASe1c2QOEZ1bGuHsez8/7Mh0uwT7nlVHua0byW9
       +2VfPQQOBH2WizhqEoBL17SaCXtDRWqmcWjscKAiu
       +9JKcMeV9doqJufyBSL72lMllZptHNa7NVeTz1ORd
       +RpKOFHiPPHosR6swoNnQx3rMQQ1UukqlOnWjrYuQ
       +rluhHsFfp+wsjwAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +frell godot@remailer.frell.eu.org 36a413ef0c5f70a40fa981a15a838d6d 2:3.0rc1 CNm 2007-09-12 2008-10-06
       +
       +-----Begin Mix Key-----
       +36a413ef0c5f70a40fa981a15a838d6d
       +258
       +AAS8atl2d209zkTZ0NYUOK3IUf547Wp3fy4X5xKC
       +NmHFrvwzN5MR6FWDmc+GxyYe2yfbguumMPpMxaPy
       +KKfsyxkdbkQltMPT7Klg2YXOIdcHjFOB+rDhgwaA
       +CE/6v+3oNSJLV4vynTO70VjlIeACTQB74dzDzlA5
       +P6PNWBpjFmRfwQAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +george mix@mixmaster.it ab3475256b54ca81e22654f3140059d1 2:3.0rc1 CNm
       +
       +-----Begin Mix Key-----
       +ab3475256b54ca81e22654f3140059d1
       +258
       +AATvwvPxB6WRF/M271TbI6kYo5o3Lex7slhid2me
       +ZhIYqD6/3oocuKAKjlcAuuNeHEYdODzBTOtT6q/e
       +6qJci0JTawm1N6wlQf7Ec4Cf9iHk/bDG9z8n3pUg
       +/pYPmXyTJhsUaev9G0pDmlm7hgfP8e/FU3b3rrAs
       +Cs7ICwKXsZHCMQAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +hermetix mix@hermetix.org 4abed36ded98d55cf314b4371d32e63b 2:3.0rc1 CNm 2007-08-06 2008-08-30
       +
       +-----Begin Mix Key-----
       +4abed36ded98d55cf314b4371d32e63b
       +258
       +AASvG7+cR8y22Q74hdeBa7H7xmEiN7hmhFTfkdvM
       +2szIAfEF4bt81vitMVfjlaeFOBCKdos6H01ku6Vl
       +YyFDAqc8UqUIaIpE12Gj0bzt7RaqiFHyBNSGPTzo
       +lD5t9TsIheqgZXBYfJYtdB20JCgg58trGR20EhKp
       +YEKl03Luw4hGDwAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +kroken remailer@kroken.dynalias.com dce5b28b21c0c4549dd2f60bd8e132bb 2:2.9.1 MC
       +
       +-----Begin Mix Key-----
       +dce5b28b21c0c4549dd2f60bd8e132bb
       +258
       +AATIsmPImwHWKUoZYEcmSG3mnVR1N8HBPTmgURMT
       +D7TEkm5Ft50lgUEa6so+mEybcKhDucS6a8ggWs0Z
       +dC+xd3V7fE/vkUrTz2y/agZUhxtg8Lli/JzU6/0T
       +DuXKCl/RPkk9TQjza2f/kONZ5g7SOEs001GpYWx6
       +m8nHp2St6CFjnQAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +metacolo mix@remailer.metacolo.com 134c535b461b5777fb77acf26c4fc344 2:2.9.1 CNm
       +
       +-----Begin Mix Key-----
       +134c535b461b5777fb77acf26c4fc344
       +258
       +AASxBgMo4LysBt8XcB3twGhd1VLbgMaIcjnxopYJ
       +Kf2yzon5oma+RcYLcZb4xkDPUOZurnt5QBQ9YlUt
       +EtfC8nKFlGY1bwAAFsa1+sne94U0kiwEqC85Y//3
       +BS0xJgUUYf45DqChbP67Y6WbVCbiWo9XBdB9s573
       +gC7o1+pcOCuX7wAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +nymkey mixmaster@nymkey.com e8c9e711fa87da8f2537ba4975015a21 2:3.0b2 CNm 2007-11-25 2008-12-19
       +
       +-----Begin Mix Key-----
       +e8c9e711fa87da8f2537ba4975015a21
       +258
       +AASsmXxFWovlEqSDF1lTLZOoFXBFDZegheR9iWGR
       +0d36yq1I/JpVKtVp1ZZr4Bs0ivjgtFiS8gDJOF7i
       +InukP7wBfNfPl2LPBAxpwmDbvt2wI2y44+0XloQQ
       +Y+hqiZnhkW0UA97IQ2UauIfKieQdJ2D1GBVR9+r5
       +dzQAgLqlBVIbuQAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +pboxmix mixmaster@pboxmix.winstonsmith.info 065247b5b9a598c3864169963ef7943e 2:3.0b2 CNm 2006-12-31 2008-01-25
       +
       +-----Begin Mix Key-----
       +065247b5b9a598c3864169963ef7943e
       +258
       +AATG36o9krh9bM4l8StENw9JTzIYJnA5xYvxbYJT
       +8MLIThhYtwn3KUhKM/J7ywsN3GOoqeuPu6bsSchc
       +3VOhEfh5mDX9Sk/LVplSRd0Rx2hr5Z1ws89Crk7d
       +ZHzgIZc4PXEShftuToWN9yEiznyFeW3Pr0TmcjPb
       +sistHq5vwSUVIQAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +pobox mix@antagonism.org 03447beb791e53062dbf6ce6b074bbb1 2:3.0rc1 MC 2007-11-21 2008-12-15
       +
       +-----Begin Mix Key-----
       +03447beb791e53062dbf6ce6b074bbb1
       +258
       +AASlYQieOuO/RjwF0kpFDtxm9ptnidj6d5eDKC9/
       +TJ4hYPa4I6koM/wRzTwDKyrEs8Q9SsbBouksvm4m
       +n/l24DWjWrBK4xpkg0aMduyXvw4NYK+tXmBt0acr
       +eSb9y4sBNoBF9I5b0mjMyAHPDhExp8bh9ytqZV9K
       +nFqtS0nDmkjenwAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +starwars mixmaster@tatooine.homelinux.net 912819a4f778f7ffd37dd6d1d96c3814 2:3.0rc1 MCNm
       +
       +-----Begin Mix Key-----
       +912819a4f778f7ffd37dd6d1d96c3814
       +258
       +AAS5rSbE3GryA6Ue5cokxi8yXY6STITER+Zfr8xq
       +LvKy+JD5fV4AYYMaN3dar9vjcA72JiBocWGDUcs2
       +qXUhmugghqsrPQOcWyY8Id9i1ww+00fEgaqD8pTe
       +TcX3pOBVbrp2nm6r0QsM+BekUY0CxlAedalFp3x6
       +j8m8hNRDOmyDLwAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +tonga remailer@cypherpunks.to 70d5742c277080317d4161f8c41b6592 2:3.0a3 MCNm 2002-09-12
       +
       +-----Begin Mix Key-----
       +70d5742c277080317d4161f8c41b6592
       +258
       +AASXcXjmf6JdlT28ivHvkgr+JYdtTBL2sBXa6YSv
       +sJ7usVBpgbdknuWcw7FC5kCqdyaaUd7s/y6dNqAu
       +/QuudS29RlochxJ5QqwUcFv/xNnej/flzVeEdfdU
       +McgYOUG4cBZ/D0X8lUqc85a31qeNvmIEU3RRaKPf
       +mgMEl6p5YropFwAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
       +winters mix@remailer.antagonism.org b5fa82ee0fb8c2a41b5a90c0983d8344 2:3.0rc1 MC 2007-07-05 2008-07-29
       +
       +-----Begin Mix Key-----
       +b5fa82ee0fb8c2a41b5a90c0983d8344
       +258
       +AATMBYHz/jt2yIGLfxNkA0g/ca1feheiOnuwE4uA
       +nZNL5mu5qbinV1aC0x1HwyRzuL+7rdCu5y9P+CvW
       +qRPxtoflkbfqthS/Su5smsn8kZHtdjwsIYUTjs5j
       +QBSDqsxKpfHHP0aQgBqvDtRRo4RH/00jG40YFyWD
       +tZPRXEDkxR7b5QAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
       +AAAAAAAAAAAAAAAAAAAAAQAB
       +-----End Mix Key-----
       +
   DIR diff --git a/conf/rab.blk b/conf/rab.blk
   DIR diff --git a/conf/reply.txt.in b/conf/reply.txt.in
       t@@ -0,0 +1,32 @@
       +This message is being sent to you automatically in response to an email
       +that you sent to <%RAA>.
       +
       +Most likely, you tried to reply to an email that has been sent through
       +this service. If you did not send an email to <%RAA>,
       +please ignore this message.
       +
       +The %RMN is a free service that
       +allows individuals including crime victims, domestic violence victims,
       +persons in recovery, and others, such as those living under oppressive
       +regimes, to communicate confidentially in a manner that ensures their
       +privacy under even the most adverse conditions.
       +
       +To block individuals using this remailer from sending email to your
       +address in the future, please send a message to <%RMA>
       +containing the line
       +
       +DESTINATION-BLOCK
       +
       +anywhere in the body text of the email.  You can simply forward this
       +entire email to <%RMA> using your email
       +program for your current email address to be permanently blocked
       +from users of the %RMN.
       +
       +For more information about the %RMN Administrator's
       +strict anti-abuse policy, please send a blank email to
       +<%CA>
       +
       +Sincerely,
       +
       +-- The %RMN Administrator
       +
   DIR diff --git a/conf/rlist.txt b/conf/rlist.txt
       t@@ -0,0 +1,61 @@
       +$remailer{"antani"} = "<mixmaster@firenze.linux.it> cpunk max mix middle pgp pgponly repgp remix latent hash cut test ekx inflt50 rhop5 reord post";
       +$remailer{"austria"} = "<mixmaster@remailer.privacy.at> cpunk max mix pgp pgponly repgp remix latent hash cut test ekx inflt50 rhop5 reord klen1024";
       +$remailer{"beton"} = "<remailer@hyperreal.info> cpunk max mix middle pgp repgp remix latent hash cut test ek ekx esub inflt50 rhop5 reord klen10000";
       +$remailer{"borked"} = "<remailer@pseudo.borked.net> cpunk max mix pgp pgponly repgp remix latent hash cut test ek ekx esub inflt50 rhop3 reord post klen1024";
       +$remailer{"citrus"} = "<mix@outel.org> cpunk max mix middle pgp pgponly repgp remix latent hash cut test ek ekx esub inflt50 rhop5 reord";
       +$remailer{"cyberiad"} = "<mixmaster@remailer.cyberiade.it> cpunk max mix pgp pgponly repgp remix latent hash cut test ek ekx esub inflt50 rhop5 reord post";
       +$remailer{"deuxpi"} = "<anon@deuxpi.ca> cpunk max mix middle pgp pgponly repgp remix latent hash cut test ekx inflt50 rhop5 reord post";
       +$remailer{"dizum"} = "<remailer@dizum.com> cpunk max mix pgp pgponly repgp remix latent hash cut test ek ekx esub inflt50 rhop5 reord post klen64";
       +$remailer{"frell"} = "<godot@remailer.frell.eu.org> cpunk max mix pgp pgponly repgp remix latent hash cut test ek ekx esub inflt50 rhop5 reord post klen1024";
       +$remailer{"george"} = "<mix@mixmaster.it> cpunk max mix pgp pgponly repgp remix latent hash cut test ek ekx esub inflt50 rhop5 reord post";
       +$remailer{"hastio"} = "<anon@remailer.hastio.org> cpunk mix hybrid pgp latent ek ekx esub cut hash repgp remix ext max test inflt75 rhop6 klen1000";
       +$remailer{"hermetix"} = "<mix@hermetix.org> cpunk max mix pgp pgponly repgp remix latent hash cut test ek ekx esub inflt50 rhop5 reord post klen5000";
       +$remailer{"kroken"} = "<remailer@kroken.dynalias.com> cpunk mix middle pgp pgponly repgp remix latent hash cut test ek ekx esub inflt50 rhop20 reord klen1024";
       +$remailer{"metacolo"} = "<mix@remailer.metacolo.com> cpunk mix pgp repgp remix latent hash cut test ek ekx esub inflt50 rhop20 reord post";
       +$remailer{"nymkey"} = "<mixmaster@nymkey.com> cpunk max mix pgp pgponly repgp remix latent hash cut test ekx inflt50 rhop5 reord post";
       +$remailer{"panta"} = "<remailer@panta-rhei.eu.org> cpunk mix hybrid hcnews pgp latent ek ekx esub cut hash post repgp remix reord ext max test inflt75 rhop5 klen1000";
       +$remailer{"pboxmix"} = "<mixmaster@pboxmix.winstonsmith.info> cpunk max mix pgp pgponly repgp remix latent hash cut test ekx inflt50 rhop5 reord post";
       +$remailer{"senshi"} = "<senshiremailer@gmx.de> cpunk middle pgp latent ek ekx esub cut hash repgp reord ext max test inflt10 rhop2 klen200";
       +$remailer{"starwars"} = "<mixmaster@tatooine.homelinux.net> cpunk max mix middle pgp pgponly repgp remix latent hash cut test ek ekx esub inflt50 rhop5 reord post";
       +
       +Broken type-I remailer chains:
       +(austria borked)
       +(borked senshi)
       +(cyberiad borked)
       +(deuxpi senshi)
       +(dizum borked)
       +(frell senshi)
       +(george borked)
       +(senshi beton)
       +
       +Broken type-II remailer chains:
       +(austria borked)
       +(borked cyberiad)
       +(cthulu antani)
       +(deuxpi tonga)
       +(metacolo tonga)
       +(pobox tonga)
       +(winters tonga)
       +
       +Last update: Sat 22 Dec 2007 14:50:04 GMT
       +remailer  email address                        history  latency  uptime
       +-----------------------------------------------------------------------
       +nymkey   mixmaster@nymkey.com                      *-- 12:06:55 100.00%
       +george   mix@mixmaster.it                          *-- 12:01:01 100.00%
       +kroken   remailer@kroken.dynalias.com              +-- 11:11:08 100.00%
       +cyberiad mixmaster@remailer.cyberiade.it           *-- 11:08:55 100.00%
       +hermetix mix@hermetix.org                          *-- 10:35:57 100.00%
       +borked   remailer@pseudo.borked.net                *-- 10:18:00 100.00%
       +dizum    remailer@dizum.com                        +-- 10:34:31  99.94%
       +metacolo mix@remailer.metacolo.com                 *-- 11:56:00  99.86%
       +antani   mixmaster@firenze.linux.it                +-- 13:52:33  99.83%
       +pboxmix  mixmaster@pboxmix.winstonsmith.i          *-- 11:49:00  99.80%
       +citrus   mix@outel.org                             +-- 14:16:05  98.71%
       +starwars mixmaster@tatooine.homelinux.net          +-- 11:44:55  97.44%
       +frell    godot@remailer.frell.eu.org               +-- 14:32:02  96.77%
       +senshi   senshiremailer@gmx.de                ___  +-- 16:50:04  76.28%
       +beton    remailer@hyperreal.info             ____  +-- 18:10:57  71.85%
       +deuxpi   anon@deuxpi.ca                            *-- 11:37:00  52.80%
       +austria  mixmaster@remailer.privacy.at          _  +-- 12:14:01  45.38%
       +hastio   anon@remailer.hastio.org                      99:59:59   0.00%
       +panta    remailer@panta-rhei.eu.org                    99:59:59   0.00%
   DIR diff --git a/conf/type1.hlp b/conf/type1.hlp
       t@@ -0,0 +1,100 @@
       +This remailer will permit you to remail messages without using the
       +Mixmaster client software or PGP. This mode of operation is known to be
       +insecure and should generally be used for testing purposes only. The
       +operator of this remailer, all system administrators of the many
       +machines through which your email will pass on the way to its
       +destination, and any 15-year-old-hacker that may have broken into any of
       +the many machines through which your email will pass may be able to
       +determine that you are the original sender of the email.
       +
       +However, you may find this insecure mode useful for testing and
       +debugging purposes or to just send a quick email without exposing your
       +real email address to spam harvesters gathering email addresses from
       +mailing lists. To use the insecure mode, send mail to <%RMA>. Place a
       +blank line into the first line, two colons in the second line of your
       +message, and the line "Anon-To: address" in the third line of your
       +message. Follow that with another blank line and begin your message. For
       +example:
       +
       +==================================================================
       +From: remailer_user@sender_domain.com
       +To: %RMA Subject: anonymous message
       +
       +::
       +Anon-To:  final_recipient@destination_domain.com 
       +
       +Dear Domestic Violence List Members,
       +My husband has physically abused me for most of the 18 years of our marriage.
       +I can't tell you how many times I had to come up with excuses as to why I had
       +those bruises or that black eye.  I stayed in the marriage for the sake of
       +our daughter.
       +But recently, my husband has started to touch our 14-year-old daughter.
       +I don't know what to do. I am afraid my husband will kill me if I say
       +something. I am even more afraid for my daughter. I have no money; my
       +husband controls all the bank accounts. What can I do?
       +
       +Please help,
       +-- Desperate.
       +==================================================================
       +
       +The remailer will remove all header lines, and forward the message to
       +the destination.  The following e-mail would be delivered to 
       +<final_recipient@destination_domain.com >:
       +
       +==================================================================
       +From: %RMN <%RAA>
       +Comments: This message did not originate from the Sender
       +address above.  It was remailed automatically by anonymizing remailer
       +software.  Please report problems or inappropriate use to the remailer
       +administrator at <%CA>.
       +To:  final_recipient@destination_domain.com 
       +
       +Dear Domestic Violence List Members,
       +My husband has physically abused me for most of the 18 years of our
       +marriage.
       +I can't tell you how many times I had to come up with excuses as to why
       +I had those bruises or that black eye.  I stayed in the marriage for
       +the sake of our daughter.
       +But recently, my husband has started to touch our 14-year-old daughter.
       +I don't know what to do. I am afraid my husband will kill me if I say
       +something. I am even more afraid for my daughter. I have no money; my
       +husband controls all the bank accounts. What can I do?
       +
       +Please help,
       +-- Desperate.
       +==================================================================
       +
       +You frequently will wish to include a Subject or other header lines in
       +your remailed email. You can insert header lines in the remailed message
       +by preceding them with a "##" line:
       +
       +==================================================================
       +From: remailer_user@sender_domain.com
       +To: %RMA
       +
       +::
       +Anon-To:  final_recipient@destination_domain.com 
       +
       +##
       +Subject: Re: Remailer Test Message 
       +In-Reply-To: Your message of "Tue, 12 Jan 1999 22:47:04 EST." 
       +<199901130247.WAA02761@destiation_domain.com>
       +
       +Dear Desperate,
       +Just like you, I was stuck in an abusive marriage for
       +many years. I don't need to tell you what you already know: if not for
       +your sake, for the sake of your daughter, you need to get away from your
       +husband immediately. At the moment, you may think your husband has all
       +the power and that you are powerless. You are not powerless. Contact the
       +National Center against Domestic Violence today and ask about the
       +address and phone number of a women's shelter near where you live. The
       +people there will show you how you can free yourself from the yoke of
       +brutality and protect your daughter from the worst.
       +
       +Please post another anonymous email to this list if you are having any
       +difficulties in locating a women's shelter.
       +
       +-- Broken Free
       +==================================================================
       +                                ****
       +
   DIR diff --git a/conf/usage.txt.in b/conf/usage.txt.in
       t@@ -0,0 +1,24 @@
       +Subject: Your email to %RMA
       +Reply-To: <%RMA>
       +
       +This message is being sent to you automatically in response to an email
       +that you sent to <%RMA>.
       +If you did not send such an email, please ignore this message.
       +
       +This remailer is a free service that allows individuals including crime
       +victims, domestic violence victims, persons in recovery, and others,
       +such as those living under oppressive regimes, to communicate
       +confidentially in a manner that ensures their privacy under even the
       +most adverse conditions.
       +
       +To obtain information on how you can use this service, please send an
       +email with subject "remailer-help" to <%RMA>.
       +
       +Should you have received an unwelcome message through this service or to
       +report problems with this service, please contact the Administrator at
       +<%CA>.
       +
       +Thank you for your interest in secure and private communications,
       +
       +-- The %RMN Administrator
       +
   DIR diff --git a/idea.txt b/idea.txt
       t@@ -0,0 +1,34 @@
       +This Software/Hardware product contains the algorithm IDEA(TM) as
       +described and claimed in US Patent No. 5,214,703, EPO Patent
       +No. 0482154 and filed Japanese Patent Application No. 508119/1991
       +"Device for the conversion of a digital block and use of same"
       +(hereinafter referred to as "Algorithm"). Any use of the Algorithm for
       +Commercial Purposes is thus subject to a license from Ascom Systec
       +Ltd. of CH-5506 Mägenwil (Switzerland), being the patentee and sole
       +owner of all rights, including the term IDEA(TM). Commercial Purposes
       +shall mean any revenue generating purpose including but not limited to
       +
       +i) using the Algorithm for company internal purposes (subject to a
       +Site License).
       +
       +ii) incorporating an application software containing the Algorithm
       +into any hardware and/or software and distributing such hardware
       +and/or software and/or providing services related thereto to others
       +(subject to a Product License).
       +
       +iii) using a product containing an application software that uses the
       +Algorithm (subject to an End-User License), except in case where such
       +End-User has acquired an implied license by purchasing the said
       +product from an authorized licensee or where the End-User has already
       +signed up for a Site License.
       +All such commercial license agreements are available exclusively from
       +Ascom Systec Ltd. and may be requested via the Internet World Wide Web
       +at http://www.ascom.ch/systec/infosec.html or by sending an electronic
       +mail to IDEA@ascom.ch. Any misuse will be prosecuted.
       +
       +Use other than for Commercial Purposes is strictly limited to data
       +transfer between private individuals and not serving Commercial
       +Purposes. The use by government agencies, non-profit organizations
       +etc. is considered as use for Commercial Purposes but may be subject
       +to special conditions. Requests for waivers for non-commercial use
       +(e.g. by software developers) are welcome.
   DIR diff --git a/mixmaster.1 b/mixmaster.1
       t@@ -0,0 +1,1136 @@
       +.TH MIXMASTER 1 "Mixmaster Version 3.0"
       +.\" $Id: mixmaster.1 974 2008-03-03 17:40:11Z rabbi $
       +.SH NAME
       +mixmaster \- anonymous remailer software
       +.SH SYNOPSIS
       +.B mixmaster
       +[\fB\-hpmdSvT\fR]
       +[\fB\-t \fIuser@host\fR]
       +[\fB\-g \fInewsgroup\fR]
       +[\fB\-s \fIsubject\fR]
       +[\fB\-a \fIfilename\fR]
       +[\fB\-l \fImix1,mix2,mix3,...\fR]
       +[\fB\-c \fInum\fR]
       +[\fIuser@host\fR]
       +[\fIfilename\fR]
       +.PP
       +.B mixmaster
       +[\fB\-f\fR[\fBrfg\fR] \fIfilename\fR]
       +.PP
       +.B mixmaster \fR[\fB\-RGKSP\fR]
       +.SH DESCRIPTION
       +Mixmaster is an anonymous remailer. Remailers provide protection
       +against traffic analysis and allow sending mail anonymously or
       +pseudonymously.
       +.PP
       +In the non-interactive mode, Mixmaster reads a message from its
       +standard input or from a file.  Destination address and input file can
       +be specified in the command line.  If no address is given in the
       +command line, the input file is expected to contain a message complete
       +with mail headers.
       +.SH OPTIONS
       +.TP
       +.B "\-h, \-\-help"
       +Print a summary of command line options.
       +.TP
       +.B "\-V, \-\-version"
       +Print version information.
       +.TP
       +.B "\-\-about"
       +Print authorship and copyright information.
       +.TP
       +.B "\-\-config=\fIfilename"
       +Read configuration from an alternate file.
       +.TP
       +.B "\-t, \-\-to=\fIuser@host"
       +Add the destination address(es) to the message header. The input file
       +contains the message body without headers.
       +.TP
       +.B "\-g, \-\-post-to=\fInewsgroup"
       +Add the newsgroup(s) to the message header. The input file
       +contains the message body without headers.
       +.TP
       +.B
       +\-p, \-\-post
       +Post the message to Usenet.
       +.TP
       +.B
       +\-m, \-\-mail
       +Send the message as electronic mail. (This is the default.)
       +.TP
       +.B "\-s, \-\-subject=\fIsubject"
       +Add the
       +.I subject
       +to the message header.
       +.TP
       +.B "\-\-header=\fI'Header: text'
       +Add the header line to the message header.
       +.TP
       +.B "\-a, \-\-attachment=\fIfilename"
       +Attach
       +.I file
       +to the message.
       +.TP
       +.B \-\-encrypt
       +Encrypt the message using the OpenPGP format.
       +.TP
       +.B \-\-sign
       +Sign the message using the OpenPGP format.
       +.TP
       +.B "\-l, \-\-chain=\fImix1,mix2,mix3,..."
       +Use this remailer chain to send the message. Alternatively, the input
       +message may contain a pseudo-header
       +.BR Chain: .
       +If no chain is specified, Mixmaster will use a chain of four random
       +remailers.
       +.TP
       +.B "\-T, \-\-type\-list"
       +Display the contents of the
       +.BR type2.list
       +file.
       +.TP
       +.B "\-c, \-\-copies=\fInum"
       +Send
       +.I num
       +copies of the message to increase reliability.
       +.TP
       +.B \-d, \-\-dummy
       +Generate a dummy message as protection against traffic analysis.
       +.TP
       +.B \-S, \-\-send
       +Send the message(s) from the pool.
       +.TP
       +.B \-v, \-\-verbose
       +Output informational messages.
       +.TP
       +.B "\-f\fR [\fIfile\fR]"
       +Read a mail folder or news article. This function requires ncurses support.
       +.TP
       +.B "\-fr\fR [\fIfile\fR]"
       +Reply to a message.
       +.TP
       +.B "\-ff\fR [\fIfile\fR]"
       +Post a follow-up to a message.
       +.TP
       +.B "\-fg\fR [\fIfile\fR]"
       +Send a group reply to a message.
       +.TP
       +.B "\-\-update-pinger-list"
       +Download an updated all pingers list file.
       +.TP
       +.B "\-\-update-stats\fI[=source\fR]"
       +Download updated stats.
       +.SS Remailer options:
       +.TP
       +.B "\-\-config=\fIfilename"
       +Read configuration from an alternate file.
       +.TP
       +.B \-R, \-\-read\-mail
       +Read a remailer message from standard input and store it in the pool.
       +.TP
       +.B \-I, \-\-store\-mail
       +Read a remailer message from standard input and store it in the pool
       +without decrypting it immediately. It will be processed the next time
       +Mixmaster processes the queue (called with \fP-M\fP or in daemon mode).
       +.TP
       +.B \-P, \-\-pop-mail
       +Read mail from the POP3 servers listed in
       +.BR pop3.cfg .
       +.TP
       +.B \-M, \-\-remailer
       +Check if it is time to perform the regular remailer actions:
       +Send messages from the pool, get mail from POP3 servers and keep the
       +internal files up\-to\-date.
       +.TP
       +.B \-D, \-\-daemon
       +Detach from the console and process the pool, get mail and update the
       +internal files at regular intervals.
       +.TP
       +.B \-\-no-detach
       +Run as daemon but do not detach from the terminal (This option is
       +only useful together with \fB--daemon\fP).
       +.TP
       +.B -G, \-\-generate\-key
       +Generate a new remailer key.
       +.TP
       +.B \-K, \-\-update\-keys
       +Generate remailer keys if necessary.
       +.TP
       +.B \-S, \-\-send
       +Force sending the message(s) from the pool.
       +.TP
       +.B \-\-install\-svc
       +Install the Mixmaster Service on Win32.
       +.TP
       +.B \-\-remove\-svc
       +Remove the Mixmaster Service on Win32.
       +.TP
       +.B \-\-run\-svc
       +Run the Mixmaster Service on Win32.
       +.TP
       +.B \-\-redirect
       +Read a Mixmaster packet from stdin and route it through a chain given with
       +.B \-\-no\-ask\-passphrase
       +Do not ask for the remailer passphrase even if we don't have it compiled in,
       +don't have it in the config file, don't have it in the environment and we are
       +on a tty.
       +\fB\-\-chain\fP.
       +Note that this may corrupt the packet if there is not enough space in the
       +headers (that is, if there are more than 20 hops total).  This function is
       +not normally needed but may come in handy in certain cases.
       +.SH CONFIGURATION
       +Mixmaster reads its configuration from the file
       +.B mix.cfg
       +in its working directory.  The configuration file consists of lines of
       +the type
       +.PP
       +.I VARIABLE       values
       +.PP
       +and of comments, which begin with a
       +.B #
       +character.  The variables have reasonable default values, but it is
       +useful to create a configuration file using the
       +.B Install
       +script when setting up a remailer.
       +.PP
       +All configuration variables can be overridden from the command line,
       +e.g.
       +.B mixmaster -S --POOLSIZE=0 --RATE=100
       +will send all messages currently in the message pool.
       +.SS Client configuration:
       +.TP
       +.B ADDRESS
       +Your address for sending non-anonymous messages.
       +.TP
       +.B NAME
       +Your real name (used for sending non-anonymous messages).
       +.TP
       +.B MAILtoNEWS
       +Address of a mail-to-news gateway. Default:
       +.BR mail2news@nym.alias.net .
       +.TP
       +.B CHAIN
       +Default chain for anonymous messages to be sent.
       +.B CHAIN
       +is a comma-separated list of remailer names or addresses.
       +A
       +.B *
       +represents a random reliable remailer. Default:
       +.BR *,*,*,* .
       +.TP
       +.B NUMCOPIES
       +Number of redundant copies of an anonymous message to be
       +sent, unless specified otherwise on the command line.
       +Default:
       +.BR 1 .
       +.TP
       +.B DISTANCE
       +When selecting random remailers, the chain will contain
       +.I DISTANCE
       +other remailers between two occurrences of the
       +same remailer in the chain. Default:
       +.BR 2 .
       +.TP
       +.B MINREL
       +Only select remailers with a reliability of at least
       +.IR MINREL %.
       +Default:
       +.BR 98 .
       +.TP
       +.B RELFINAL
       +Only select a remailer with a reliability of at least
       +.IR RELFINAL %
       +as the final remailer. Default:
       +.BR 99 .
       +.TP
       +.B MAXLAT
       +Only select remailers with a latency of at most
       +.IR MAXLAT .
       +Default:
       +.BR 36h .
       +.TP
       +.B MINLAT
       +Only select remailers with a latency of at least
       +.IR MINLAT .
       +Default:
       +.BR 5m .
       +.TP
       +.B PGPPUBRING
       +Path to your public PGP key ring. Default:
       +.BR ~/.pgp/pubring.pkr .
       +(Windows default: PGP registry value.)
       +.TP
       +.B PGPSECRING
       +Path to your secret PGP key ring. Default:
       +.BR ~/.pgp/secring.skr .
       +(Windows default: PGP registry value.)
       +.TP
       +.B CLIENTAUTOFLUSH
       +If 
       +.B REMAIL
       +is set to
       +.BR n
       +automatically flush the pool every time Mixmaster is run. Default:
       +.BR n .
       +.TP
       +.B SENDMAIL
       +Path to the
       +.BR sendmail (1)
       +program. If set to
       +.BR outfile ,
       +Mixmaster will create text files named
       +.BI out * .txt
       +in the
       +.B pool
       +directory instead of sending mail.
       +Default:
       +.BR "/usr/lib/sendmail -t" .
       +.TP
       +.B SMTPRELAY
       +Name of SMTP relay. If set, mail will be delivered to the relay
       +rather than by
       +.BR sendmail (1).
       +.TP
       +.B HELONAME
       +Host name used in the SMTP dialogue.
       +Default: The
       +.I ENVFROM
       +host name or the current network name associated with the socket.
       +.TP
       +.B SMTPUSERNAME
       +Some mail servers require authentication for sending mail. This is
       +the authenticated SMTP user name.
       +.B SMTPPASSWORD
       +Password for authenticated SMTP.
       +.TP
       +.B ENVFROM
       +Envelope from address used in the SMTP dialogue. (When the client is
       +used to send non-anonymous messages,
       +.I ADDRESSS
       +is used instead.)
       +Default:
       +.IR ANONADDR .
       +.TP
       +.B ALLPINGERSURL
       +URL from which to download the 
       +.IR ALLPINGERSFILE .
       +Default:
       +.BR http://www.noreply.org/allpingers/allpingers.txt .
       +.TP
       +.B WGET
       +Define the http protocol download tool. Default:
       +.BR wget .
       +.SS Remailer configuration:
       +.TP
       +.B NEWS
       +Path to the news posting program, or address of a
       +mail-to-news gateway. Default: no news posting.
       +(When using a news posting program,
       +.I ORGANIZATION
       +contains
       +an Organization line for anonymous messages. Default:
       +.BR "Anonymous Posting Service" .)
       +.TP
       +.B SENDANONMAIL
       +Path to a program for sending anonymous mail. Default:
       +.IR SENDMAIL .
       +.B SENDANONMAIL
       +can be used to invoke an external mail filter for anonymized messages.
       +.TP
       +.B SHORTNAME
       +A short name for the remailer to be used in lists. Defaults to the host name.
       +.TP
       +.B REMAILERADDR
       +The remailer mail address.
       +.TP
       +.B ANONADDR
       +An address to be inserted in the
       +.B From:
       +line of anonymous messages. Default:
       +.IR REMAILERADDR .
       +.TP
       +.B REMAILERNAME
       +A name to be inserted in the
       +.B From:
       +line of remailer status
       +messages. Default:
       +.BR "Anonymous Remailer" .
       +.TP
       +.B ANONNAME
       +A name to be inserted in the
       +.B From:
       +line of anonymous messages.
       +Default:
       +.BR "Anonymous" .
       +.TP
       +.B COMPLAINTS
       +An address for complaints to be sent to. Default:
       +.IR REMAILERADDR .
       +.TP
       +.B ERRLOG
       +Name of a file to log error messages, or
       +.B stdout
       +or
       +.BR stderr .
       +Default:
       +.BR stderr .
       +(When run from a tty, Mixmaster will always print a copy of error
       +messages to
       +.BR stderr .)
       +.TP
       +.B MAILBOX
       +A generic mail folder for non-remailer messages that are not stored in
       +any of the following folders.
       +If
       +.B MAILBOX
       +begins with a
       +.BR | ,
       +it specifies the path to a program. If it contains an
       +.B @
       +sign, the message is forwarded to the given address (with an
       +.B X-Loop:
       +header to prevent mail loops). If it ends with a
       +.B /
       +it is treated as a Maildir, otherwise the message is appended
       +to the given file name or written to standard output if
       +.B MAILBOX
       +is
       +.BR stdout .
       +Default:
       +.BR mbox .
       +.TP
       +.B MAILABUSE
       +Mail folder for messages sent to the
       +.I COMPLAINTS
       +address.
       +Default:
       +.IR MAILBOX .
       +.TP
       +.B MAILBLOCK
       +Mail folder for messages sent to the remailer address with a
       +.B DESTINATION-BLOCK
       +line.
       +Default:
       +.IR MAILBOX .
       +.TP
       +.B MAILUSAGE
       +Mail folder for messages sent to the remailer address that do not
       +contain any valid remailer commands. Default:
       +.BR /dev/null .
       +.TP
       +.B MAILANON
       +Mail folder for replies sent to the
       +.I ANONADDR
       +address.
       +Default:
       +.BR /dev/null .
       +.TP
       +.B MAILERROR
       +Mail folder for messages that cannot be decrypted or contain other
       +errors. Default:
       +.BR /dev/null .
       +.TP
       +.B MAILBOUNCE
       +Mail folder for bounce messages. Default:
       +.IR MAILBOX .
       +.TP
       +.B MAILIN
       +If defined an additional mail folder where Mixmaster should read messages from
       +when processing its pool. If it ends with a
       +.B /
       +it is treated as a Maildir, otherwise a standard mbox format file
       +is expected. All messages are removed from the folder after reading.
       +.B MAILIN
       +is not set by default.
       +It is an incredibly bad idea to set this the same as \fBMAILBOX\fP.
       +.TP
       +.B VERBOSE
       +If
       +.B VERBOSE
       +is set to
       +.BR 0 ,
       +Mixmaster will log error
       +messages only. If it is set to
       +.BR 1 ,
       +error messages and warnings are logged. If
       +.B VERBOSE
       +is set to
       +.BR 2 ,
       +successful operation is logged as well.
       +If set to
       +.BR 3 ,
       +a log file entry is created whenever a message
       +enters or leaves the pool.  Default:
       +.BR 2 .
       +.TP
       +.B PASSPHRASE
       +A passphrase used to protect the remailer secret keys from
       +casual attackers. This setting overrides the compile-time
       +defined
       +.B COMPILEDPASS
       +which is now deprecated.
       +This should
       +.I not
       +be the same as the client passphrase.
       +.TP
       +.B EXTFLAGS
       +Additional flags you want to set in the remailer's capabilities string.
       +Defaults to the empty string, which means none.  Example:
       +.BR testing .
       +.TP
       +.B PRECEDENCE
       +Sets the header Precedence: to this value for all outgoing mail.
       +Defaults to the empty string, which means no such header is added.
       +Example: 
       +.BR anon .
       +If you use this you might want to block user supplied precedence
       +headers in your header block file.
       +.PP
       +The following variables can be set to
       +.B y
       +or
       +.BR n :
       +.TP
       +.B REMAIL
       +Enable remailer functionality. Default:
       +.BR n .
       +.TP
       +.B MIDDLEMAN
       +Act as an intermediate hop only, forward anonymized
       +messages to another remailer. This mode can be used
       +where complaints about anonymous messages must be
       +avoided. (The variable
       +.B FORWARDTO
       +specifies the remailer
       +chain to be used; default:
       +.BR * .)
       +Default:
       +.BR n .
       +.TP
       +.B AUTOREPLY
       +Send help files in response to non-remailer messages. Explicit
       +.B remailer-help
       +requests are always served.
       +Default:
       +.BR n .
       +.TP
       +.B MIX
       +Accept Mixmaster messages. Default:
       +.BR y .
       +.TP
       +.B PGP
       +Accept OpenPGP-encrypted Cypherpunk remailer messages.
       +Default:
       +.BR n .
       +.TP
       +.B UNENCRYPTED
       +Accept unencrypted Cypherpunk remailer messages.
       +Default:
       +.BR n .
       +.TP
       +.B REMIX
       +Re-encrypt Type I messages to other remailers in the Mixmaster format
       +.RB ( x
       += only when requested by user explicitly).
       +Default:
       +.BR y .
       +.TP
       +.B BINFILTER
       +Filter out binary attachments. Default:
       +.BR n .
       +.TP
       +.B LISTSUPPORTED
       +List known remailers and their keys in remailer-conf reply. Default:
       +.BR y .
       +.TP
       +.B MID
       +Use a hash of the message body as Message-ID, to avoid
       +Usenet spam. Default:
       +.BR y .
       +If
       +.B MID
       +is set to a string
       +beginning with
       +.BR @ ,
       +that string is used as the domain part of the message ID.
       +.TP
       +.B AUTOBLOCK
       +Allow users to add their address to the
       +.B dest.blk
       +file by sending the remailer a message containing the line
       +.BR destination-block .
       +Default:
       +.BR y .
       +.TP
       +.B STATSDETAILS
       +List statistics on intermediate vs. final delivery in remailer-stats.
       +Default:
       +.BR y .
       +.PP
       +The following variables have numeric values:
       +.TP
       +.B POOLSIZE
       +The size of the Mixmaster reordering pool. Larger sizes
       +imply higher security and longer delays. Remailer default:
       +.BR 45 .
       +Client default:
       +.BR 0 .
       +.TP
       +.B RATE
       +Percentage of messages from the pool to be sent. Remailer default:
       +.BR 65 .
       +Client default:
       +.BR 100 .
       +Lower values cause the pool to increase in size when
       +many messages are received at a time, reducing the effect
       +of flooding attacks.
       +.TP
       +.B INDUMMYP
       +Probability that Mixmaster will generate dummy messages upon
       +receipt of incoming mail. Larger numbers mean more dummy
       +messages on average. For instance,
       +.B 10
       +means that on average one in nine incoming messages will trigger
       +a dummy generation, and
       +.B 20
       +means that one in four will.
       +.B 0
       +means no dummy messages. Remailer default:
       +.BR 10 .
       +Client default:
       +.BR 3 .
       +.TP
       +.B OUTDUMMYP
       +Probability that Mixmaster will generate dummy messages at
       +.B SENDPOOL
       +time. If the pool is processed frequently, this should be a lower value
       +than if there are long intervals between pool processing. Examples:
       +.B 50
       +means on average, one dummy message will be generated per pool
       +processing.
       +.B 80
       +means four will be generated.
       +.B 0
       +means no dummy messages. Remailer default:
       +.BR 90 .
       +Client default:
       +.BR 3 .
       +.TP
       +.B SIZELIMIT
       +Maximum size for anonymous messages in kB.
       +.B 0
       +means no limit.
       +Default:
       +.BR 0 .
       +.TP
       +.B POP3SIZELIMIT
       +Maximum size for incoming messages in kB when using POP3.
       +.B 0
       +means no limit.
       +Default:
       +.BR 0 .
       +Larger messages are deleted unread if
       +.B POP3DEL
       +is set to
       +.BR y ,
       +and left on the server otherwise.
       +.TP
       +.B INFLATEMAX
       +Maximum size for
       +.B Inflate:
       +padding in kB.
       +.B 0
       +means padding is not allowed.
       +Default:
       +.B 50
       +.BR kB .
       +.TP
       +.B MAXRANDHOPS
       +Maximum chain length for message forwarding requested by
       +.B Rand-Hop
       +directives.
       +Default:
       +.BR 4 .
       +.TP
       +.B MAXRECIPIENTS
       +limits the number of allowed recipients in outgoing mail.  Anything that exceeds this
       +number is dropped silently.  Default:
       +.BR 5 .
       +.TP
       +.B TEMP_FAIL
       +exit with this exit code when a timeskew problem is suspected.  Also see
       +.BR TIMESKEW_BACK
       +and
       +.BR TIMESKEW_FORWARD .
       +The default of
       +.B 75
       +should cause your MTA to requeue the message if you are running
       +mixmaster from a
       +.BR .forward
       +file.
       +.TP
       +.B STATSAUTOUPDATE
       +Set non-zero to enable Daemon stats download mode. Default: 
       +.BR 0 .
       +.PP
       +The following are time variables. They can be given as years (
       +.BR y
       +), months (
       +.BR b
       +), days (
       +.BR d
       +), hours (
       +.BR h
       +), minutes (
       +.BR m
       +), or seconds (
       +.BR s
       +).
       +.TP
       +.B SENDPOOLTIME
       +How often Mixmaster should check the pool for messages
       +to be sent. Remailer default:
       +.BR 15m .
       +Client default:
       +.BR 0h .
       +.TP
       +.B POP3TIME
       +How often Mixmaster should check the POP3 accounts
       +listed in
       +.B pop3.cfg
       +for new mail.
       +Default:
       +.BR 1h .
       +.TP
       +.B MAILINTIME
       +How often Mixmaster should read mail from
       +.BR MAILIN
       +and process mails fetched via POP3. Processing here means to
       +answer remailer-xxx requests and decrypt messages to the Mixmaster
       +and place them in the pool. No other processing of the pool is
       +done. This action is always performed sending out messages from the pool (at
       +.BR SENDPOOLTIME
       +intervals) or receiving mail via POP3 (at
       +.BR POP3TIME
       +intervals). Default:
       +.BR 5m .
       +.TP
       +.B PACKETEXP
       +How long to store parts of incomplete multipart messages and other
       +temporary pool files.
       +Default:
       +.BR 7d .
       +.TP
       +.B IDEXP
       +Mixmaster keeps a log of packet IDs to prevent replay
       +attacks.
       +.B IDEXP
       +specifies after which period of time old
       +IDs are expired. Default:
       +.BR 7d ,
       +minimum:
       +.BR 5d .
       +If set to
       +.BR 0 ,
       +no log is kept.
       +.TP
       +.B KEYLIFETIME
       +Mixmaster sets an expiration date on its remailer keys 
       +.B KEYLIFETIME
       +after the key creation date. Default:
       +.BR 13b .
       +.TP
       +.B KEYGRACEPERIOD
       +Mixmaster will continue to decrypt messages encrypted to an expired key 
       +for
       +.B KEYGRACEPERIOD 
       +period of time after the expiration. This is done to ensure that messages
       +already injected into the network are allowed to exit. Do not change this
       +value unless you know what you are doing, or you will risk partitioning
       +attacks. Default:
       +.BR 7d . 
       +.TP
       +.B KEYOVERLAPPERIOD
       +Mixmaster will generate and advertise a new key 
       +.BR KEYOVERLAPPERIOD
       +period of time before the expiration of the key. Clients should always use 
       +the most recently created valid key. Clients that deviate from this 
       +recommended behavior risk partitioning attacks. Default:
       +.BR 7d .
       +.TP
       +.B TIMESKEW_BACK
       +Allow going back up to
       +.BR TIMESKEW_BACK
       +in time.  If the time moved further back mixmaster will assume
       +there is a problem with your clock and refuse to start as a remailer.
       +This is done by comparing the latest timestamp in 
       +.BR time.log
       +with the current timestamp.  If set to
       +.BR 0
       +then this test is skipped.  If the system time is indeed correct, simply
       +remove
       +.BR time.log .
       +Default: 
       +.BR 12h .
       +.TP
       +.B TIMESKEW_FORWARD
       +Similar to
       +.BR TIMESKEW_BACK
       +but allow jumping this far into the future.
       +Default: 
       +.BR 2w .
       +.TP
       +.B STATSINTERVAL
       +Time interval between daemon downloads of stats files. Enabled by
       +.BR STATSAUTOUPDATE .
       +Default: 
       +.BR 2h .
       +.PP
       +The following strings must be specified at compile-time in
       +.BR config.h .
       +It is not usually necessary to modify any of these:
       +.TP
       +.B
       +DISCLAIMER
       +A default string to be inserted in the header of all anonymous
       +messages if no
       +.B disclaim.txt
       +file is available. If
       +.B DISCLAIMER
       +contains the substring
       +.BR "%s" ,
       +it will be substituted with the
       +.I COMPLAINTS
       +address.
       +.TP
       +.B FROMDISCLAIMER
       +A default string to be inserted at the top of the message body
       +if an anonymous message contains a user-supplied
       +.B From:
       +line and no
       +.B fromdscl.txt
       +file is available.
       +.TP
       +.B MSGFOOTER
       +A default string to be inserted at the bottom of the message body
       +of all anonymous messages if no
       +.B footer.txt
       +file is available.
       +.TP
       +.B BINDISCLAIMER
       +A string to replace the body of a binary attachment when
       +the remailer is configured to filter out binaries.
       +.TP
       +.B CHARSET
       +The character set used for MIME-encoded header lines.
       +.TP
       +.B DESTBLOCK
       +A quoted list of files that contain blocked addresses.
       +Files must be separated by one space. Mixmaster will choose
       +the first file for writing if
       +.B AUTOBLOCK
       +is enabled.
       +.PP
       +The following variables can be set in the
       +.B Makefile
       +or in
       +.BR config.h :
       +.TP
       +.B COMPILEDPASS
       +A passphrase used to protect the remailer secret keys from
       +casual attackers. You can use
       +.B `make PASS="\fIyour passphrase\fB"'
       +to set a passphrase. This should
       +.I not
       +be the same as the client passphrase. This option is now deprecated in
       +favor of the configuration file option
       +.BR PASSPHRASE .
       +.TP
       +.B SPOOL
       +Set
       +.B SPOOL
       +if you want to use a default directory other than
       +.B ~/Mix
       +or if Mixmaster is run in an environment where
       +.B $HOME
       +is not set, e.g. when invoked via
       +.BR .forward .
       +This value can be overridden by use of the environment variable
       +.BR $MIXPATH .
       +.TP
       +.B USE_SSLEAY
       +Use the SSLeay/OpenSSL cryptographic library. Currently this is the
       +only cryptographic library supported by Mixmaster.
       +.TP
       +.B USE_IDEA
       +Use the IDEA encryption algorithm. A license is required to use IDEA
       +for commercial purposes. See file
       +.B idea.txt
       +for details.
       +.TP
       +.B USE_PGP
       +Support the OpenPGP encryption format. Mixmaster does not call any
       +external encryption program.
       +.TP
       +.B USE_PCRE
       +Use the regular expression library.
       +.TP
       +.B USE_ZLIB
       +Use the
       +.B zlib
       +compression library.
       +.TP
       +.B USE_NCURSES
       +Use the
       +.B ncurses
       +library.
       +.TP
       +.B USE_SOCK
       +Use sockets to transfer mail by POP3 and SMTP.
       +.TP
       +.B USE_WINGUI
       +Use the
       +.B Win32
       +GUI.
       +.TP
       +.B HAVE_GETDOMAINNAME
       +The
       +.BR getdomainname (2)
       +function is available.
       +.SH FILES
       +These filenames can be overridden by setting the corresponding configuration
       +option (given in parentheses).
       +.TP
       +.B mix.cfg
       +Mixmaster configuration file.
       +.TP
       +.B pubring.asc
       +Type 1 remailer keys (\fBPGPREMPUBASC\fP).
       +.TP
       +.B pubring.mix
       +Type 2 remailer keys (\fBPUBRING\fP).
       +.TP
       +.B rlist.txt
       +List of reliable type 1 remailers (\fBTYPE1LIST\fP).
       +.TP
       +.B mlist.txt
       +List of reliable type 2 remailers (\fBTYPE2REL\fP).
       +.TP
       +.B type2.list
       +List of known type 2 remailers (optional) (\fBTYPE2LIST\fP).
       +.TP
       +.B starex.txt
       +List of remailers which should not be used in randomly generated
       +remailer chains (\fBSTAREX\fP).
       +.SS Remailer files:
       +.TP
       +.B disclaim.txt
       +A string to be inserted in the header of all anonymous
       +messages (\fBDISCLAIMFILE\fP).
       +.TP
       +.B fromdscl.txt
       +A string to be inserted at the top of the message body
       +if an anonymous message contains a user-supplied
       +.B From:
       +line (\fBFROMDSCLFILE\fP).
       +.TP
       +.TP
       +.B footer.txt
       +A string to be inserted at the bottom of the message body
       +of all anonymous messages (\fBMSGFOOTERFILE\fP).
       +.TP
       +.B help.txt
       +Help file sent in response to
       +.B remailer-help
       +requests (\fBHELPFILE\fP).
       +.TP
       +.B adminkey.txt
       +The PGP key of the remailer operator sent in response to
       +.B remailer-adminkey
       +requests (\fBADMKEYFILE\fP).
       +.TP
       +.B abuse.txt
       +File sent in response to mail to the
       +.I COMPLAINTS
       +address if
       +.B AUTOREPLY
       +is set (\fBABUSEFILE\fP).
       +.TP
       +.B reply.txt
       +Help file sent in response to replies to anonymous messages if
       +.B AUTOREPLY
       +is set (\fBREPLYFILE\fP).
       +.TP
       +.B usage.txt
       +Help file sent in response to non-remailer message sent to
       +.I REMAILERADDR
       +if
       +.B AUTOREPLY
       +is set. If
       +.B usage.log
       +exists, recipients are logged and a reply is sent only once to avoid
       +mail loops (\fBUSAGEFILE\fP).
       +.TP
       +.B blocked.txt
       +Information sent in response to automatically processed blocking requests if
       +.B AUTOREPLY
       +is set (\fBBLOCKFILE\fP).
       +.TP
       +.B pop3.cfg
       +List of POP3 accounts with lines of the form
       +.I account@host.domain password
       +to get remailer messages from. The lines may optionally contain the
       +keyword "apop" or "pass" to select an authentication method (\fBPOP3CONF\fP).
       +.TP
       +.B dest.alw
       +List of addresses to which Mixmaster will deliver, even in middleman mode (\fBDESTALLOW\fP).
       +.TP
       +.B dest.alw.nonpublished
       +Similar to
       +.BR dest.alw ,
       +with the only difference that this list is not published in remailer-conf replies (\fBDESTALLOW2\fP).
       +.TP
       +.B dest.blk
       +List of blocked destination addresses.
       +Mixmaster does not send mail to the blocked addresses listed in this file (\fBDESTBLOCK\fP).
       +.TP
       +.B rab.blk
       +Identical to
       +.BR dest.blk ,
       +except Mixmaster will not write to this file.
       +For use with external remailer abuse blocklists.
       +.TP
       +.B source.blk
       +List of blocked source addresses.  If an incoming message originates
       +from an address or IP in this list, it will be ignored. This
       +feature can be used to avoid spam and other abusive mail (\fBSOURCEBLOCK\fP).
       +.TP
       +.B header.blk
       +List of unwanted header fields. The file is used to delete unwanted
       +header lines (e.g. lines that indicate a false identity, or Usenet
       +control messages), and do other header filtering (\fBHDRFILTER\fP).
       +
       +A destination address or header line is left out if it contains a
       +search string or matches a regular expression specified in the block
       +file. Lines in the block file that begin and end with a slash
       +.RB ( /\fIregexp\fB/ )
       +are interpreted as regular expressions. Lines without
       +slashes are used for case-independent substring search.
       +
       +If a message contains a header line that matches a
       +.B /\fIregexp\fB/q
       +entry in
       +.BR header.blk ,
       +the entire message is deleted.
       +
       +In addition, regular expressions can be substituted. Back-references
       +are supported. For example
       +
       + /^From: *([^@]*) <.*>/From: $1/
       + /^From:.* \\(([^@]*)\)/From: $1/
       + /^From: *([^@]*).*$/From: $1 <\fInobody@remailer.domain\fR>/
       +
       +would allow user-defined names in the
       +.B From:
       +line, while replacing any given address with the remailer address.
       +.TP
       +.B allpingers.txt
       +Information on all known pingers (\fBALLPINGERSFILE\fP).
       +.SS
       +Mixmaster uses the following files internally:
       +.TP
       +.B mixrand.bin
       +Random seed file (\fBMIXRAND\fP).
       +.TP
       +.B secring.pgp
       +Remailer type 1 secret keys (\fBPGPREMSECRING\fP).
       +.TP
       +.B secring.mix
       +Remailer type 2 secret keys (\fBSECRING\fP).
       +.TP
       +.B pgpkey.txt
       +The public type 1 remailer key (\fBPGPKEY\fP).
       +.TP
       +.B key.txt
       +The public type 2 remailer key (\fBKEYFILE\fP).
       +.TP
       +.B id.log
       +Log file of messages already processed (\fBIDLOG\fP).
       +.TP
       +.B stats.log
       +Log file for remailer statistics (\fBSTATS\fP).
       +.TP
       +.B stats-src.txt
       +File for name of most recent statistics source (\fBSTATSSRC\fP).
       +.TP
       +.B pgpmaxcount.log
       +Log file for PGP Max-Count statistics (\fBPGPMAXCOUNT\fP).
       +.TP
       +.B time.log
       +Time for periodic remailer actions (\fBREGULAR\fP).
       +.TP
       +.B dhparam.mix
       +Public Diffie-Hellman parameters used for El-Gamal key generation (\fBDHPARAMS\fP).
       +.TP
       +.B dsaparam.mix
       +Public DSA parameters used for DSA key generation (\fBDSAPARAMS\fP).
       +.TP
       +.B mixmaster.pid
       +Pid file in daemon mode (\fBPIDFILE\fP).
       +.TP
       +.BI pool/
       +Message pool directory (\fBPOOL\fP).
       +.TP
       +.BI pool/m *
       +Message pool files.
       +.TP
       +.BI pool/p *
       +Partial messages.
       +.TP
       +.BI pool/l *
       +Latent messages.
       +.TP
       +.BI pool/s *
       +Messages to be sent.
       +.TP
       +.BI pool/t *
       +Temporary files.
       +.SH ENVIRONMENT
       +.TP
       +.I MIXPATH
       +The path to the Mixmaster directory. The default is
       +.BR ~/Mix .
       +.TP
       +.I MIXPASS
       +The passphrase used to protect your nyms and PGP keys.
       +(The remailer uses a different passphrase.) If
       +.I MIXPASS
       +is not set, the client will ask for a passphrase.
       +.SH SEE ALSO
       +.BR mpgp (1),
       +.BR pgp (1),
       +.BR procmail (1),
       +.BR sendmail (8).
       +.SH HISTORY
       +Mixmaster is an implementation of a Chaumian mix-net system.
       +Versions 1.0 through 2.0.3 of the 
       +.BR mixmaster
       +remailer were originally written by Lance Cottrell. Mixmaster was first 
       +released in 1995. Ulf Moeller collaborated on version 2.0.4, and began an 
       +entire rewrite of
       +.BR mixmaster
       +in 1999. This rewrite was released in 2002 as version 2.9.0, with major 
       +contributions from Janis Jagars, Peter Palfrader, and Len Sassaman.
       +Mixmaster 3.0 is based on the 2.9 codebase. Peter Palfrader and Len 
       +Sassaman were the principal maintainers until 2006. Since then, Steve 
       +Crook, Len Sassaman, and Colin Tuckley have filled the role of 
       +principal maintaners. For more information on contributing authors, 
       +please see the file THANKS for details.
       +.SH COPYRIGHT
       +Copyright 1999 - 2008 Anonymizer Inc., The Mixmaster Development Team, 
       +and others.
       +
       +Mixmaster may be redistributed and modified under certain conditions.
       +This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
       +ANY KIND, either express or implied. See the file COPYRIGHT for
       +details.
   DIR diff --git a/mpgp.1 b/mpgp.1
       t@@ -0,0 +1,121 @@
       +.TH MPGP 1 "Mixmaster Version 3.0"
       +.\" $Id: $
       +.SH NAME
       +mpgp \- Mixmaster OpenPGP Module
       +.SH SYNOPSIS
       +.B mpgp \fB\-e\fR [\fB\-b\fR] \fIkeyname\fR [\fIfilename\fR]
       +.PP
       +.B mpgp \fB\-s\fR [\fB\-b\fR] [\fIkeyname\fR [\fIfilename\fR]]
       +.PP
       +.B mpgp \fB\-c\fR [\fB\-b\fR] [\fIfilename\fR]
       +.PP
       +.B mpgp \fB\-C\fR [\fB\-b\fR] [\fIfilename\fR]
       +.PP
       +.B mpgp \fB\-d\fR [\fB\-b\fR] [\fIpassphrase\fR [\fIfilename\fR]]
       +.PP
       +.B mpgp \fB\-g\fR[\fBr\fR] \fIkeyname\fR [\fIbits\fR]
       +.PP
       +.B mpgp \fB\-a\fR[\fB+\-\fR] [\fB\-b\fR] [\fIfilename\fR]
       +.PP
       +.B mpgp \fB\-V\fR
       +.SH DESCRIPTION
       +Mixmaster is an anonymous remailer. mpgp is a light-weight OpenPGP
       +implementation, primarily used to diagnose issues with OpenPGP keys and
       +messages handled by the Mixmaster remailer software.
       +.PP
       +mpgp can encrypt, decrypt and sign a message using the Mixmaster 
       +OpenPGP library. The message is read from the standard input or the 
       +specified \fIfilename\fR. The output will be written to the standard 
       +output. When called without arguments mpgp decrypts from the standard 
       +input. It asks for a passphrase when needed.
       +.SH OPTIONS
       +.TP
       +.B "\-h"
       +Print a summary of command line options.
       +.TP
       +.B "\-V"
       +Print the current version, authorship and copyright information.
       +.TP
       +.B "\-e"
       +Encrypt a message with the first OpenPGP key from the public key ring 
       +whose contains \fIkeyname\fR as a substring.
       +.TP
       +.B "\-s"
       +Make a signature of the message with the first OpenPGP key from the secret
       +key ring, or the first key whose contains \fIkeyname\fR as a substring if
       +specified.
       +.TP
       +.B "\-c"
       +Encrypt with symmetric cipher only.
       +.TP
       +.B "\-C"
       +Encrypt with symmetric cipher only using the new OpenPGP format.
       +.TP
       +.B "\-d"
       +Decrypt a message using \fIpassphrase\fR if specified or asking for it if
       +needed. It also verifies its signature.
       +.TP
       +.B "\-g\fR[\fBr\fR]"
       +Generate new OpenPGP key pair with the given \fIkeyname\fR as user ID. If
       +\fBr\fR is specified the OpenPGP key will be created using the RSA 
       +algorithm, otherwise the ElGamal algorithm will be used. \fIbits\fR is the 
       +key length and its default value is 1024.
       +.TP
       +.B "\-a\fR[\fB+\-\fR]"
       +Create an ASCII OpenPGP armored message. If \fB\-\fR is specified mpgp 
       +will remove ASCII armor.
       +.TP
       +.B "\-b"
       +Specifies that the message is in binary format.
       +.SH CONFIGURATION
       +The Mixmaster OpenPGP module reads its configuration from the file
       +.B mix.cfg
       +in its working directory.  The configuration file consists of lines of
       +the type
       +.PP
       +.I VARIABLE       values
       +.PP
       +and of comments, which begin with a
       +.B #
       +character.
       +.PP
       +.TP
       +.B PGPPUBRING
       +Path to your public OpenPGP key ring. Default:
       +.BR ~/.pgp/pubring.pgp .
       +(Windows default: PGP registry value.)
       +.TP
       +.B PGPSECRING
       +Path to your secret OpenPGP key ring. Default:
       +.BR ~/.pgp/secring.pgp .
       +(Windows default: PGP registry value.)
       +.SH FILES
       +These filenames can be overridden by setting the corresponding configuration
       +option (given in parentheses).
       +.TP
       +.B mix.cfg
       +Mixmaster configuration file.
       +.TP
       +.B pubring.pgp
       +OpenPGP public keys (\fBPGPPUBRING\fP).
       +.TP
       +.B secring.pgp
       +OpenPGP secret keys (\fBPGPSECRING\fP).
       +.SH SEE ALSO
       +.BR mixmaster (1),
       +.BR pgp (1),
       +.BR gpg (1).
       +.SH HISTORY
       +The
       +.BR mpgp 
       +command was written by Ulf Moeller as a test suite for Mixmaster 
       +2.9's internal OpenPGP support. It was enhanced and debugged primarily
       +by Janis Jagars for use as a light-weight stand-alone OpenPGP application.
       +.SH COPYRIGHT
       +(C) 1999-2006 Ulf Moeller and others.
       +Mixmaster and 
       +.BR mpgp 
       +may be redistributed and modified under certain
       +conditions. This software is distributed on an "AS IS" basis, WITHOUT
       +WARRANTY OF ANY KIND, either express or implied. See the file COPYRIGHT
       +for details.
   DIR diff --git a/win32/installer/mixinstall.nsi b/win32/installer/mixinstall.nsi
       t@@ -0,0 +1,70 @@
       +Name "Mixmaster"
       +
       +OutFile "Mixmaster-Setup.exe"
       +
       +InstallDir $PROGRAMFILES\Mixmaster
       +
       +; Registry key to check for directory (so if you install again, it will 
       +; overwrite the old one automatically)
       +InstallDirRegKey HKLM "Software\Mixmaster" "Install_Dir"
       +
       +;--------------------------------
       +
       +; Pages
       +
       +Page components
       +Page directory
       +Page instfiles
       +
       +UninstPage uninstConfirm
       +UninstPage instfiles
       +
       +;--------------------------------
       +
       +Section "Mixmaster"
       +  SectionIn RO
       +  SetOutPath $INSTDIR
       +  File "..\release\mix.exe"
       +  File "..\release\mixlib.dll"
       +  File "..\..\Src\openssl\out32dll\libeay32.dll"
       +  File "c:\winnt\system32\msvcr71.dll"
       +
       +  WriteRegStr HKLM SOFTWARE\Mixmaster "Install_Dir" "$INSTDIR"
       +
       +  ; Write the uninstall keys for Windows
       +  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mixmaster" "DisplayName" "Mixmaster"
       +  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mixmaster" "UninstallString" '"$INSTDIR\uninstall.exe"'
       +  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mixmaster" "NoModify" 1
       +  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mixmaster" "NoRepair" 1
       +  WriteUninstaller "uninstall.exe"
       +SectionEnd
       +
       +Section "Start Menu Shortcuts (All Users)"
       +  SetShellVarContext all
       +  CreateDirectory "$SMPROGRAMS\Mixmaster"
       +  CreateShortCut "$SMPROGRAMS\Mixmaster\Mixmaster.lnk" "$INSTDIR\mix.exe" "" "$INSTDIR\mix.exe" 0
       +  CreateShortCut "$SMPROGRAMS\Mixmaster\Uninstall Mixmaster.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
       +SectionEnd
       +
       +Section "Create Desktop Item (All Users)"
       +  SetShellVarContext all
       +  CreateShortCut "$DESKTOP\Mixmaster.lnk" "$INSTDIR\mix.exe" "" "$INSTDIR\mix.exe" 0
       +SectionEnd
       +
       +Section "Uninstall"
       +  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mixmaster"
       +  DeleteRegKey HKLM SOFTWARE\Mixmaster
       +
       +  Delete $INSTDIR\mix.exe
       +  Delete $INSTDIR\mixlib.dll
       +  Delete $INSTDIR\libeay32.dll
       +  Delete $INSTDIR\msvcr71.dll
       +  Delete $INSTDIR\uninstall.exe
       +
       +  SetShellVarContext all
       +  Delete "$SMPROGRAMS\Mixmaster\*.*"
       +  RMDir "$SMPROGRAMS\Mixmaster"
       +  Delete "$DESKTOP\Mixmaster.lnk"
       +
       +  RMDir "$INSTDIR"
       +SectionEnd
   DIR diff --git a/win32/mix.sln b/win32/mix.sln
       t@@ -0,0 +1,79 @@
       +Microsoft Visual Studio Solution File, Format Version 8.00
       +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mix", "mix.vcproj", "{075AD568-26A6-4C0F-9D78-60E6BA2FD7CC}"
       +        ProjectSection(ProjectDependencies) = postProject
       +                {BE1E2A5D-7460-4F06-AEEB-9443B1EE1844} = {BE1E2A5D-7460-4F06-AEEB-9443B1EE1844}
       +        EndProjectSection
       +EndProject
       +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mixlib", "mixlib.vcproj", "{BE1E2A5D-7460-4F06-AEEB-9443B1EE1844}"
       +        ProjectSection(ProjectDependencies) = postProject
       +                {FC9B2030-6750-4272-87C9-6E46AB029F69} = {FC9B2030-6750-4272-87C9-6E46AB029F69}
       +                {F587947F-949D-4AD6-A527-3A34918741B5} = {F587947F-949D-4AD6-A527-3A34918741B5}
       +                {6A9ECAB3-1CA6-4E2A-8A15-F8AE459BB174} = {6A9ECAB3-1CA6-4E2A-8A15-F8AE459BB174}
       +        EndProjectSection
       +EndProject
       +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcre", "Pcre.vcproj", "{FC9B2030-6750-4272-87C9-6E46AB029F69}"
       +        ProjectSection(ProjectDependencies) = postProject
       +                {63F7F010-3302-4329-A9AC-9739FC57EC51} = {63F7F010-3302-4329-A9AC-9739FC57EC51}
       +        EndProjectSection
       +EndProject
       +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcre_chartables", "Pcre_Chartables.vcproj", "{63F7F010-3302-4329-A9AC-9739FC57EC51}"
       +        ProjectSection(ProjectDependencies) = postProject
       +        EndProjectSection
       +EndProject
       +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib.vcproj", "{6A9ECAB3-1CA6-4E2A-8A15-F8AE459BB174}"
       +        ProjectSection(ProjectDependencies) = postProject
       +        EndProjectSection
       +EndProject
       +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pdcurses", "pdcurses.vcproj", "{F587947F-949D-4AD6-A527-3A34918741B5}"
       +        ProjectSection(ProjectDependencies) = postProject
       +        EndProjectSection
       +EndProject
       +Global
       +        GlobalSection(SolutionConfiguration) = preSolution
       +                Debug = Debug
       +                Release = Release
       +                Release Static = Release Static
       +        EndGlobalSection
       +        GlobalSection(ProjectConfiguration) = postSolution
       +                {075AD568-26A6-4C0F-9D78-60E6BA2FD7CC}.Debug.ActiveCfg = Release Static|Win32
       +                {075AD568-26A6-4C0F-9D78-60E6BA2FD7CC}.Debug.Build.0 = Release Static|Win32
       +                {075AD568-26A6-4C0F-9D78-60E6BA2FD7CC}.Release.ActiveCfg = Release|Win32
       +                {075AD568-26A6-4C0F-9D78-60E6BA2FD7CC}.Release.Build.0 = Release|Win32
       +                {075AD568-26A6-4C0F-9D78-60E6BA2FD7CC}.Release Static.ActiveCfg = Release Static|Win32
       +                {075AD568-26A6-4C0F-9D78-60E6BA2FD7CC}.Release Static.Build.0 = Release Static|Win32
       +                {BE1E2A5D-7460-4F06-AEEB-9443B1EE1844}.Debug.ActiveCfg = Release|Win32
       +                {BE1E2A5D-7460-4F06-AEEB-9443B1EE1844}.Debug.Build.0 = Release|Win32
       +                {BE1E2A5D-7460-4F06-AEEB-9443B1EE1844}.Release.ActiveCfg = Release|Win32
       +                {BE1E2A5D-7460-4F06-AEEB-9443B1EE1844}.Release.Build.0 = Release|Win32
       +                {BE1E2A5D-7460-4F06-AEEB-9443B1EE1844}.Release Static.ActiveCfg = Release|Win32
       +                {BE1E2A5D-7460-4F06-AEEB-9443B1EE1844}.Release Static.Build.0 = Release|Win32
       +                {FC9B2030-6750-4272-87C9-6E46AB029F69}.Debug.ActiveCfg = Release|Win32
       +                {FC9B2030-6750-4272-87C9-6E46AB029F69}.Debug.Build.0 = Release|Win32
       +                {FC9B2030-6750-4272-87C9-6E46AB029F69}.Release.ActiveCfg = Release|Win32
       +                {FC9B2030-6750-4272-87C9-6E46AB029F69}.Release.Build.0 = Release|Win32
       +                {FC9B2030-6750-4272-87C9-6E46AB029F69}.Release Static.ActiveCfg = Release|Win32
       +                {FC9B2030-6750-4272-87C9-6E46AB029F69}.Release Static.Build.0 = Release|Win32
       +                {63F7F010-3302-4329-A9AC-9739FC57EC51}.Debug.ActiveCfg = Release|Win32
       +                {63F7F010-3302-4329-A9AC-9739FC57EC51}.Debug.Build.0 = Release|Win32
       +                {63F7F010-3302-4329-A9AC-9739FC57EC51}.Release.ActiveCfg = Release|Win32
       +                {63F7F010-3302-4329-A9AC-9739FC57EC51}.Release.Build.0 = Release|Win32
       +                {63F7F010-3302-4329-A9AC-9739FC57EC51}.Release Static.ActiveCfg = Release|Win32
       +                {63F7F010-3302-4329-A9AC-9739FC57EC51}.Release Static.Build.0 = Release|Win32
       +                {6A9ECAB3-1CA6-4E2A-8A15-F8AE459BB174}.Debug.ActiveCfg = Release|Win32
       +                {6A9ECAB3-1CA6-4E2A-8A15-F8AE459BB174}.Debug.Build.0 = Release|Win32
       +                {6A9ECAB3-1CA6-4E2A-8A15-F8AE459BB174}.Release.ActiveCfg = Release|Win32
       +                {6A9ECAB3-1CA6-4E2A-8A15-F8AE459BB174}.Release.Build.0 = Release|Win32
       +                {6A9ECAB3-1CA6-4E2A-8A15-F8AE459BB174}.Release Static.ActiveCfg = Release|Win32
       +                {6A9ECAB3-1CA6-4E2A-8A15-F8AE459BB174}.Release Static.Build.0 = Release|Win32
       +                {F587947F-949D-4AD6-A527-3A34918741B5}.Debug.ActiveCfg = Release|Win32
       +                {F587947F-949D-4AD6-A527-3A34918741B5}.Debug.Build.0 = Release|Win32
       +                {F587947F-949D-4AD6-A527-3A34918741B5}.Release.ActiveCfg = Release|Win32
       +                {F587947F-949D-4AD6-A527-3A34918741B5}.Release.Build.0 = Release|Win32
       +                {F587947F-949D-4AD6-A527-3A34918741B5}.Release Static.ActiveCfg = Release|Win32
       +                {F587947F-949D-4AD6-A527-3A34918741B5}.Release Static.Build.0 = Release|Win32
       +        EndGlobalSection
       +        GlobalSection(ExtensibilityGlobals) = postSolution
       +        EndGlobalSection
       +        GlobalSection(ExtensibilityAddIns) = postSolution
       +        EndGlobalSection
       +EndGlobal
   DIR diff --git a/win32/mix.vcproj b/win32/mix.vcproj
       t@@ -0,0 +1,193 @@
       +<?xml version="1.0" encoding="Windows-1252"?>
       +<VisualStudioProject
       +        ProjectType="Visual C++"
       +        Version="7.10"
       +        Name="mix"
       +        SccProjectName=""
       +        SccLocalPath="">
       +        <Platforms>
       +                <Platform
       +                        Name="Win32"/>
       +        </Platforms>
       +        <Configurations>
       +                <Configuration
       +                        Name="Release|Win32"
       +                        OutputDirectory=".\Release"
       +                        IntermediateDirectory=".\mix_intermediate"
       +                        ConfigurationType="1"
       +                        UseOfMFC="0"
       +                        ATLMinimizesCRunTimeLibraryUsage="FALSE"
       +                        CharacterSet="2">
       +                        <Tool
       +                                Name="VCCLCompilerTool"
       +                                Optimization="2"
       +                                InlineFunctionExpansion="1"
       +                                AdditionalIncludeDirectories="../Src/openssl/inc32"
       +                                PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_WIN32;IBMPC_SYSTEM;_MSC;MSC"
       +                                StringPooling="TRUE"
       +                                RuntimeLibrary="2"
       +                                EnableFunctionLevelLinking="TRUE"
       +                                PrecompiledHeaderFile=".\mix_intermediate/mix.pch"
       +                                AssemblerListingLocation=".\mix_intermediate/"
       +                                ObjectFile=".\mix_intermediate/"
       +                                ProgramDataBaseFileName=".\mix_intermediate/"
       +                                WarningLevel="3"
       +                                SuppressStartupBanner="TRUE"/>
       +                        <Tool
       +                                Name="VCCustomBuildTool"/>
       +                        <Tool
       +                                Name="VCLinkerTool"
       +                                AdditionalDependencies="wsock32.lib"
       +                                OutputFile=".\Release/mix.exe"
       +                                LinkIncremental="1"
       +                                SuppressStartupBanner="TRUE"
       +                                SubSystem="1"
       +                                TargetMachine="1"/>
       +                        <Tool
       +                                Name="VCMIDLTool"
       +                                PreprocessorDefinitions="NDEBUG"
       +                                MkTypLibCompatible="TRUE"
       +                                SuppressStartupBanner="TRUE"
       +                                TargetEnvironment="1"
       +                                TypeLibraryName=".\Release/mix.tlb"
       +                                HeaderFileName=""/>
       +                        <Tool
       +                                Name="VCPostBuildEventTool"/>
       +                        <Tool
       +                                Name="VCPreBuildEventTool"/>
       +                        <Tool
       +                                Name="VCPreLinkEventTool"/>
       +                        <Tool
       +                                Name="VCResourceCompilerTool"
       +                                PreprocessorDefinitions="NDEBUG"
       +                                Culture="2057"/>
       +                        <Tool
       +                                Name="VCWebServiceProxyGeneratorTool"/>
       +                        <Tool
       +                                Name="VCXMLDataGeneratorTool"/>
       +                        <Tool
       +                                Name="VCWebDeploymentTool"/>
       +                        <Tool
       +                                Name="VCManagedWrapperGeneratorTool"/>
       +                        <Tool
       +                                Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
       +                </Configuration>
       +                <Configuration
       +                        Name="Release Static|Win32"
       +                        OutputDirectory=".\Release"
       +                        IntermediateDirectory=".\mix_Release"
       +                        ConfigurationType="1"
       +                        UseOfMFC="0"
       +                        ATLMinimizesCRunTimeLibraryUsage="FALSE"
       +                        CharacterSet="2">
       +                        <Tool
       +                                Name="VCCLCompilerTool"
       +                                Optimization="2"
       +                                InlineFunctionExpansion="1"
       +                                AdditionalIncludeDirectories="../../src/zlib-1.1.4,../../src/pcre-2.08"
       +                                PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_WIN32;IBMPC_SYSTEM;_MSC;MSC"
       +                                StringPooling="TRUE"
       +                                RuntimeLibrary="2"
       +                                EnableFunctionLevelLinking="TRUE"
       +                                PrecompiledHeaderFile=".\mix_Release/mix.pch"
       +                                AssemblerListingLocation=".\mix_Release/"
       +                                ObjectFile=".\mix_Release/"
       +                                ProgramDataBaseFileName=".\mix_Release/"
       +                                WarningLevel="3"
       +                                SuppressStartupBanner="TRUE"
       +                                CompileAs="0"/>
       +                        <Tool
       +                                Name="VCCustomBuildTool"/>
       +                        <Tool
       +                                Name="VCLinkerTool"
       +                                AdditionalDependencies="wsock32.lib libeay32.lib $(OutDir)\pcre.lib $(OutDir)\zlib.lib $(OutDir)\mixlib_static.lib"
       +                                OutputFile=".\Release/mix.exe"
       +                                LinkIncremental="1"
       +                                SuppressStartupBanner="TRUE"
       +                                SubSystem="1"
       +                                TargetMachine="1"/>
       +                        <Tool
       +                                Name="VCMIDLTool"
       +                                PreprocessorDefinitions="NDEBUG"
       +                                MkTypLibCompatible="TRUE"
       +                                SuppressStartupBanner="TRUE"
       +                                TargetEnvironment="1"
       +                                TypeLibraryName=".\Release/mix.tlb"
       +                                HeaderFileName=""/>
       +                        <Tool
       +                                Name="VCPostBuildEventTool"/>
       +                        <Tool
       +                                Name="VCPreBuildEventTool"/>
       +                        <Tool
       +                                Name="VCPreLinkEventTool"/>
       +                        <Tool
       +                                Name="VCResourceCompilerTool"
       +                                PreprocessorDefinitions="NDEBUG"
       +                                Culture="2057"/>
       +                        <Tool
       +                                Name="VCWebServiceProxyGeneratorTool"/>
       +                        <Tool
       +                                Name="VCXMLDataGeneratorTool"/>
       +                        <Tool
       +                                Name="VCWebDeploymentTool"/>
       +                        <Tool
       +                                Name="VCManagedWrapperGeneratorTool"/>
       +                        <Tool
       +                                Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
       +                </Configuration>
       +        </Configurations>
       +        <References>
       +        </References>
       +        <Files>
       +                <Filter
       +                        Name="Source Files"
       +                        Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
       +                        <File
       +                                RelativePath="..\Src\main.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                                <FileConfiguration
       +                                        Name="Release Static|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\service.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                                <FileConfiguration
       +                                        Name="Release Static|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                </Filter>
       +                <Filter
       +                        Name="Header Files"
       +                        Filter="h;hpp;hxx;hm;inl">
       +                </Filter>
       +                <Filter
       +                        Name="Resource Files"
       +                        Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
       +                </Filter>
       +        </Files>
       +        <Globals>
       +        </Globals>
       +</VisualStudioProject>
   DIR diff --git a/win32/mixlib.vcproj b/win32/mixlib.vcproj
       t@@ -0,0 +1,459 @@
       +<?xml version="1.0" encoding="Windows-1252"?>
       +<VisualStudioProject
       +        ProjectType="Visual C++"
       +        Version="7.10"
       +        Name="mixlib"
       +        SccProjectName=""
       +        SccLocalPath="">
       +        <Platforms>
       +                <Platform
       +                        Name="Win32"/>
       +        </Platforms>
       +        <Configurations>
       +                <Configuration
       +                        Name="Release|Win32"
       +                        OutputDirectory=".\Release"
       +                        IntermediateDirectory=".\mixlib_intermediate"
       +                        ConfigurationType="2"
       +                        UseOfMFC="0"
       +                        ATLMinimizesCRunTimeLibraryUsage="FALSE"
       +                        CharacterSet="2">
       +                        <Tool
       +                                Name="VCCLCompilerTool"
       +                                Optimization="2"
       +                                InlineFunctionExpansion="1"
       +                                AdditionalIncludeDirectories="&quot;../src/pcre-2.08&quot;;../Src/openssl/inc32;&quot;../src/zlib-1.1.4&quot;;../src/pdcurses"
       +                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_WIN32;IBMPC_SYSTEM;_MSC;MSC"
       +                                StringPooling="TRUE"
       +                                RuntimeLibrary="2"
       +                                EnableFunctionLevelLinking="TRUE"
       +                                PrecompiledHeaderFile=".\mixlib_intermediate/mixlib.pch"
       +                                AssemblerListingLocation=".\mixlib_intermediate/"
       +                                ObjectFile=".\mixlib_intermediate/"
       +                                ProgramDataBaseFileName=".\mixlib_intermediate/"
       +                                WarningLevel="3"
       +                                SuppressStartupBanner="TRUE"
       +                                CompileAs="0"/>
       +                        <Tool
       +                                Name="VCCustomBuildTool"/>
       +                        <Tool
       +                                Name="VCLinkerTool"
       +                                AdditionalDependencies="wsock32.lib ../src/openssl/out32dll/libeay32.lib release/pdcurses.lib"
       +                                OutputFile=".\Release/mixlib.dll"
       +                                LinkIncremental="1"
       +                                SuppressStartupBanner="TRUE"
       +                                ModuleDefinitionFile="..\Src\mixlib.def"
       +                                ImportLibrary=".\Release/mixlib.lib"
       +                                TargetMachine="1"/>
       +                        <Tool
       +                                Name="VCMIDLTool"
       +                                PreprocessorDefinitions="NDEBUG"
       +                                MkTypLibCompatible="TRUE"
       +                                SuppressStartupBanner="TRUE"
       +                                TargetEnvironment="1"
       +                                TypeLibraryName=".\Release/mixlib.tlb"
       +                                HeaderFileName=""/>
       +                        <Tool
       +                                Name="VCPostBuildEventTool"
       +                                Description="Build static library"
       +                                CommandLine="lib.exe /nologo /out:&quot;$(OutDir)&quot;\mixlib_static.lib &quot;$(IntDir)&quot;\*.obj"/>
       +                        <Tool
       +                                Name="VCPreBuildEventTool"/>
       +                        <Tool
       +                                Name="VCPreLinkEventTool"/>
       +                        <Tool
       +                                Name="VCResourceCompilerTool"
       +                                PreprocessorDefinitions="NDEBUG"
       +                                Culture="2057"/>
       +                        <Tool
       +                                Name="VCWebServiceProxyGeneratorTool"/>
       +                        <Tool
       +                                Name="VCXMLDataGeneratorTool"/>
       +                        <Tool
       +                                Name="VCWebDeploymentTool"/>
       +                        <Tool
       +                                Name="VCManagedWrapperGeneratorTool"/>
       +                        <Tool
       +                                Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
       +                </Configuration>
       +        </Configurations>
       +        <References>
       +        </References>
       +        <Files>
       +                <Filter
       +                        Name="Source Files"
       +                        Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
       +                        <File
       +                                RelativePath="..\Src\buffers.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\chain.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\chain1.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\chain2.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\compress.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\crypto.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\dllmain.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\keymgt.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\mail.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\maildir.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\menu.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\menunym.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\menusend.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\menustats.c">
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\menuutil.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\mime.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\mix.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\mixlib.def">
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\nym.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\parsedate.tab.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pgp.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pgpcreat.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pgpdata.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pgpdb.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pgpget.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pool.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\random.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\rem.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\rem1.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\rem2.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\rfc822.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\rndseed.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\stats.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\util.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions="_USRDLL;MIXLIB_EXPORTS;WIN32;NDEBUG;_WINDOWS;_MBCS;_WIN32;IBMPC_SYSTEM;_MSC;MSC;$(NoInherit)"/>
       +                                </FileConfiguration>
       +                        </File>
       +                </Filter>
       +                <Filter
       +                        Name="Header Files"
       +                        Filter="h;hpp;hxx;hm;inl">
       +                        <File
       +                                RelativePath="..\Src\config.h">
       +                        </File>
       +                </Filter>
       +                <Filter
       +                        Name="Resource Files"
       +                        Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
       +                </Filter>
       +        </Files>
       +        <Globals>
       +        </Globals>
       +</VisualStudioProject>
   DIR diff --git a/win32/pcre.vcproj b/win32/pcre.vcproj
       t@@ -0,0 +1,117 @@
       +<?xml version="1.0" encoding="Windows-1252"?>
       +<VisualStudioProject
       +        ProjectType="Visual C++"
       +        Version="7.10"
       +        Name="pcre"
       +        SccProjectName=""
       +        SccLocalPath="">
       +        <Platforms>
       +                <Platform
       +                        Name="Win32"/>
       +        </Platforms>
       +        <Configurations>
       +                <Configuration
       +                        Name="Release|Win32"
       +                        OutputDirectory=".\Release"
       +                        IntermediateDirectory=".\pcre_intermediate"
       +                        ConfigurationType="4"
       +                        UseOfMFC="0"
       +                        ATLMinimizesCRunTimeLibraryUsage="FALSE"
       +                        CharacterSet="2">
       +                        <Tool
       +                                Name="VCCLCompilerTool"
       +                                Optimization="2"
       +                                InlineFunctionExpansion="1"
       +                                PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
       +                                StringPooling="TRUE"
       +                                RuntimeLibrary="2"
       +                                EnableFunctionLevelLinking="TRUE"
       +                                PrecompiledHeaderFile=".\pcre_intermediate/pcre.pch"
       +                                AssemblerListingLocation=".\pcre_intermediate/"
       +                                ObjectFile=".\pcre_intermediate/"
       +                                ProgramDataBaseFileName=".\pcre_intermediate/"
       +                                WarningLevel="3"
       +                                SuppressStartupBanner="TRUE"/>
       +                        <Tool
       +                                Name="VCCustomBuildTool"/>
       +                        <Tool
       +                                Name="VCLibrarianTool"
       +                                OutputFile=".\Release\pcre.lib"
       +                                SuppressStartupBanner="TRUE"/>
       +                        <Tool
       +                                Name="VCMIDLTool"/>
       +                        <Tool
       +                                Name="VCPostBuildEventTool"/>
       +                        <Tool
       +                                Name="VCPreBuildEventTool"/>
       +                        <Tool
       +                                Name="VCPreLinkEventTool"/>
       +                        <Tool
       +                                Name="VCResourceCompilerTool"
       +                                PreprocessorDefinitions="NDEBUG"
       +                                Culture="2057"/>
       +                        <Tool
       +                                Name="VCWebServiceProxyGeneratorTool"/>
       +                        <Tool
       +                                Name="VCXMLDataGeneratorTool"/>
       +                        <Tool
       +                                Name="VCManagedWrapperGeneratorTool"/>
       +                        <Tool
       +                                Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
       +                </Configuration>
       +        </Configurations>
       +        <References>
       +        </References>
       +        <Files>
       +                <Filter
       +                        Name="Source Files"
       +                        Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
       +                        <File
       +                                RelativePath="..\Src\pcre-2.08\get.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pcre-2.08\maketables.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pcre-2.08\pcre.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pcre-2.08\study.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                </Filter>
       +                <Filter
       +                        Name="Header Files"
       +                        Filter="h;hpp;hxx;hm;inl">
       +                </Filter>
       +        </Files>
       +        <Globals>
       +        </Globals>
       +</VisualStudioProject>
   DIR diff --git a/win32/pcre_chartables.vcproj b/win32/pcre_chartables.vcproj
       t@@ -0,0 +1,100 @@
       +<?xml version="1.0" encoding="Windows-1252"?>
       +<VisualStudioProject
       +        ProjectType="Visual C++"
       +        Version="7.10"
       +        Name="pcre_chartables"
       +        SccProjectName=""
       +        SccLocalPath="">
       +        <Platforms>
       +                <Platform
       +                        Name="Win32"/>
       +        </Platforms>
       +        <Configurations>
       +                <Configuration
       +                        Name="Release|Win32"
       +                        OutputDirectory=".\../src/pcre-2.08"
       +                        IntermediateDirectory=".\chartables_intermediate"
       +                        ConfigurationType="1"
       +                        UseOfMFC="0"
       +                        ATLMinimizesCRunTimeLibraryUsage="FALSE"
       +                        CharacterSet="2">
       +                        <Tool
       +                                Name="VCCLCompilerTool"
       +                                Optimization="2"
       +                                InlineFunctionExpansion="1"
       +                                PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
       +                                StringPooling="TRUE"
       +                                RuntimeLibrary="2"
       +                                EnableFunctionLevelLinking="TRUE"
       +                                PrecompiledHeaderFile=".\chartables_intermediate/pcre_chartables.pch"
       +                                AssemblerListingLocation=".\chartables_intermediate/"
       +                                ObjectFile=".\chartables_intermediate/"
       +                                ProgramDataBaseFileName=".\chartables_intermediate/"
       +                                WarningLevel="3"
       +                                SuppressStartupBanner="TRUE"/>
       +                        <Tool
       +                                Name="VCCustomBuildTool"/>
       +                        <Tool
       +                                Name="VCLinkerTool"
       +                                OutputFile="../src/pcre-2.08/dftables.exe"
       +                                LinkIncremental="1"
       +                                SuppressStartupBanner="TRUE"
       +                                SubSystem="1"
       +                                TargetMachine="1"/>
       +                        <Tool
       +                                Name="VCMIDLTool"
       +                                TypeLibraryName=".\../src/pcre-2.08/pcre_chartables.tlb"
       +                                HeaderFileName=""/>
       +                        <Tool
       +                                Name="VCPostBuildEventTool"
       +                                Description="Creating chartables.c"
       +                                CommandLine="&quot;$(TargetDir)&quot;dftables.exe &gt; &quot;$(TargetDir)&quot;chartables.c"/>
       +                        <Tool
       +                                Name="VCPreBuildEventTool"/>
       +                        <Tool
       +                                Name="VCPreLinkEventTool"/>
       +                        <Tool
       +                                Name="VCResourceCompilerTool"
       +                                PreprocessorDefinitions="NDEBUG"
       +                                Culture="2057"/>
       +                        <Tool
       +                                Name="VCWebServiceProxyGeneratorTool"/>
       +                        <Tool
       +                                Name="VCXMLDataGeneratorTool"/>
       +                        <Tool
       +                                Name="VCWebDeploymentTool"/>
       +                        <Tool
       +                                Name="VCManagedWrapperGeneratorTool"/>
       +                        <Tool
       +                                Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
       +                </Configuration>
       +        </Configurations>
       +        <References>
       +        </References>
       +        <Files>
       +                <Filter
       +                        Name="Source Files"
       +                        Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
       +                        <File
       +                                RelativePath="..\Src\pcre-2.08\dftables.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                </Filter>
       +                <Filter
       +                        Name="Header Files"
       +                        Filter="h;hpp;hxx;hm;inl">
       +                </Filter>
       +                <Filter
       +                        Name="Resource Files"
       +                        Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
       +                </Filter>
       +        </Files>
       +        <Globals>
       +        </Globals>
       +</VisualStudioProject>
   DIR diff --git a/win32/pdcurses.vcproj b/win32/pdcurses.vcproj
       t@@ -0,0 +1,607 @@
       +<?xml version="1.0" encoding="Windows-1252"?>
       +<VisualStudioProject
       +        ProjectType="Visual C++"
       +        Version="7.10"
       +        Name="pdcurses"
       +        ProjectGUID="{F587947F-949D-4AD6-A527-3A34918741B5}"
       +        SccProjectName=""
       +        SccLocalPath="">
       +        <Platforms>
       +                <Platform
       +                        Name="Win32"/>
       +        </Platforms>
       +        <Configurations>
       +                <Configuration
       +                        Name="Release|Win32"
       +                        OutputDirectory=".\Release"
       +                        IntermediateDirectory=".\pdcurses_intermediate"
       +                        ConfigurationType="4"
       +                        UseOfMFC="0"
       +                        ATLMinimizesCRunTimeLibraryUsage="FALSE"
       +                        CharacterSet="2">
       +                        <Tool
       +                                Name="VCCLCompilerTool"
       +                                Optimization="2"
       +                                InlineFunctionExpansion="1"
       +                                AdditionalIncludeDirectories="../src/pdcurses"
       +                                PreprocessorDefinitions="WIN32;NDEBUG;_LIB;PDC_STATIC_BUILD"
       +                                StringPooling="TRUE"
       +                                RuntimeLibrary="2"
       +                                EnableFunctionLevelLinking="TRUE"
       +                                PrecompiledHeaderFile=".\pdcurses_intermediate/pdcurses.pch"
       +                                AssemblerListingLocation=".\pdcurses_intermediate/"
       +                                ObjectFile=".\pdcurses_intermediate/"
       +                                ProgramDataBaseFileName=".\pdcurses_intermediate/"
       +                                WarningLevel="3"
       +                                SuppressStartupBanner="TRUE"
       +                                CompileAs="0"/>
       +                        <Tool
       +                                Name="VCCustomBuildTool"/>
       +                        <Tool
       +                                Name="VCLibrarianTool"
       +                                OutputFile=".\Release\pdcurses.lib"
       +                                SuppressStartupBanner="TRUE"/>
       +                        <Tool
       +                                Name="VCMIDLTool"/>
       +                        <Tool
       +                                Name="VCPostBuildEventTool"/>
       +                        <Tool
       +                                Name="VCPreBuildEventTool"/>
       +                        <Tool
       +                                Name="VCPreLinkEventTool"/>
       +                        <Tool
       +                                Name="VCResourceCompilerTool"
       +                                PreprocessorDefinitions="NDEBUG"
       +                                Culture="2057"/>
       +                        <Tool
       +                                Name="VCWebServiceProxyGeneratorTool"/>
       +                        <Tool
       +                                Name="VCXMLDataGeneratorTool"/>
       +                        <Tool
       +                                Name="VCManagedWrapperGeneratorTool"/>
       +                        <Tool
       +                                Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
       +                </Configuration>
       +        </Configurations>
       +        <References>
       +        </References>
       +        <Files>
       +                <Filter
       +                        Name="Source Files"
       +                        Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\addch.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\addchstr.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\addstr.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\attr.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\beep.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\bkgd.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\border.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\clear.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\color.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\delch.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\deleteln.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\getch.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\getstr.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\getyx.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\inch.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\inchstr.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\initscr.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\inopts.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\insch.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\insstr.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\instr.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\kernel.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\mouse.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\move.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\outopts.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\overlay.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\pad.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\win32\pdcclip.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\pdcdebug.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\win32\pdcdisp.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\win32\pdcgetsc.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\win32\pdckbd.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\win32\pdcprint.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\win32\pdcscrn.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\win32\pdcsetsc.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\win32\pdcurses.rc">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCResourceCompilerTool"
       +                                                PreprocessorDefinitions=""
       +                                                AdditionalIncludeDirectories="\Mixmaster\trunk\Mix\Src\pdcurses\win32"/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\pdcutil.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\pdcwin.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\printw.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\refresh.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\scanw.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\scroll.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\slk.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\termattr.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\terminfo.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\touch.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\util.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\pdcurses\pdcurses\window.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                AdditionalIncludeDirectories=""
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                </Filter>
       +                <Filter
       +                        Name="Header Files"
       +                        Filter="h;hpp;hxx;hm;inl">
       +                </Filter>
       +        </Files>
       +        <Globals>
       +        </Globals>
       +</VisualStudioProject>
   DIR diff --git a/win32/zlib.vcproj b/win32/zlib.vcproj
       t@@ -0,0 +1,217 @@
       +<?xml version="1.0" encoding="Windows-1252"?>
       +<VisualStudioProject
       +        ProjectType="Visual C++"
       +        Version="7.10"
       +        Name="zlib"
       +        SccProjectName=""
       +        SccLocalPath="">
       +        <Platforms>
       +                <Platform
       +                        Name="Win32"/>
       +        </Platforms>
       +        <Configurations>
       +                <Configuration
       +                        Name="Release|Win32"
       +                        OutputDirectory=".\Release"
       +                        IntermediateDirectory=".\zlib_intermediate"
       +                        ConfigurationType="4"
       +                        UseOfMFC="0"
       +                        ATLMinimizesCRunTimeLibraryUsage="FALSE"
       +                        CharacterSet="2">
       +                        <Tool
       +                                Name="VCCLCompilerTool"
       +                                Optimization="2"
       +                                InlineFunctionExpansion="1"
       +                                PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
       +                                StringPooling="TRUE"
       +                                RuntimeLibrary="2"
       +                                EnableFunctionLevelLinking="TRUE"
       +                                PrecompiledHeaderFile=".\zlib_intermediate/zlib.pch"
       +                                AssemblerListingLocation=".\zlib_intermediate/"
       +                                ObjectFile=".\zlib_intermediate/"
       +                                ProgramDataBaseFileName=".\zlib_intermediate/"
       +                                WarningLevel="3"
       +                                SuppressStartupBanner="TRUE"/>
       +                        <Tool
       +                                Name="VCCustomBuildTool"/>
       +                        <Tool
       +                                Name="VCLibrarianTool"
       +                                OutputFile=".\Release\zlib.lib"
       +                                SuppressStartupBanner="TRUE"/>
       +                        <Tool
       +                                Name="VCMIDLTool"/>
       +                        <Tool
       +                                Name="VCPostBuildEventTool"/>
       +                        <Tool
       +                                Name="VCPreBuildEventTool"/>
       +                        <Tool
       +                                Name="VCPreLinkEventTool"/>
       +                        <Tool
       +                                Name="VCResourceCompilerTool"
       +                                PreprocessorDefinitions="NDEBUG"
       +                                Culture="2057"/>
       +                        <Tool
       +                                Name="VCWebServiceProxyGeneratorTool"/>
       +                        <Tool
       +                                Name="VCXMLDataGeneratorTool"/>
       +                        <Tool
       +                                Name="VCManagedWrapperGeneratorTool"/>
       +                        <Tool
       +                                Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
       +                </Configuration>
       +        </Configurations>
       +        <References>
       +        </References>
       +        <Files>
       +                <Filter
       +                        Name="Source Files"
       +                        Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\adler32.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\compress.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\crc32.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\deflate.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\gzio.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\infblock.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\infcodes.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\inffast.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\inflate.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\inftrees.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\infutil.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\trees.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\uncompr.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                        <File
       +                                RelativePath="..\Src\zlib-1.1.4\zutil.c">
       +                                <FileConfiguration
       +                                        Name="Release|Win32">
       +                                        <Tool
       +                                                Name="VCCLCompilerTool"
       +                                                Optimization="2"
       +                                                PreprocessorDefinitions=""/>
       +                                </FileConfiguration>
       +                        </File>
       +                </Filter>
       +                <Filter
       +                        Name="Header Files"
       +                        Filter="h;hpp;hxx;hm;inl">
       +                </Filter>
       +        </Files>
       +        <Globals>
       +        </Globals>
       +</VisualStudioProject>