gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r6676 - in libmicrohttpd: . doc src src/daemon src/examples


From: gnunet
Subject: [GNUnet-SVN] r6676 - in libmicrohttpd: . doc src src/daemon src/examples src/testcurl src/testzzuf
Date: Sat, 12 Apr 2008 14:45:58 -0600 (MDT)

Author: grothoff
Date: 2008-04-12 14:45:58 -0600 (Sat, 12 Apr 2008)
New Revision: 6676

Added:
   libmicrohttpd/src/examples/
   libmicrohttpd/src/examples/Makefile.am
   libmicrohttpd/src/examples/fileserver_example.c
   libmicrohttpd/src/examples/minimal_example.c
   libmicrohttpd/src/testcurl/
   libmicrohttpd/src/testcurl/Makefile.am
   libmicrohttpd/src/testcurl/daemontest.c
   libmicrohttpd/src/testcurl/daemontest_get.c
   libmicrohttpd/src/testcurl/daemontest_get_chunked.c
   libmicrohttpd/src/testcurl/daemontest_large_put.c
   libmicrohttpd/src/testcurl/daemontest_long_header.c
   libmicrohttpd/src/testcurl/daemontest_put.c
   libmicrohttpd/src/testcurl/daemontest_put_chunked.c
   libmicrohttpd/src/testzzuf/
   libmicrohttpd/src/testzzuf/Makefile.am
   libmicrohttpd/src/testzzuf/daemontest.c
   libmicrohttpd/src/testzzuf/daemontest_get.c
   libmicrohttpd/src/testzzuf/daemontest_get_chunked.c
   libmicrohttpd/src/testzzuf/daemontest_large_put.c
   libmicrohttpd/src/testzzuf/daemontest_long_header.c
   libmicrohttpd/src/testzzuf/daemontest_put.c
   libmicrohttpd/src/testzzuf/daemontest_put_chunked.c
Removed:
   libmicrohttpd/src/daemon/daemontest.c
   libmicrohttpd/src/daemon/daemontest_get.c
   libmicrohttpd/src/daemon/daemontest_get_chunked.c
   libmicrohttpd/src/daemon/daemontest_large_put.c
   libmicrohttpd/src/daemon/daemontest_long_header.c
   libmicrohttpd/src/daemon/daemontest_put.c
   libmicrohttpd/src/daemon/daemontest_put_chunked.c
   libmicrohttpd/src/daemon/fileserver_example.c
   libmicrohttpd/src/daemon/minimal_example.c
Modified:
   libmicrohttpd/configure.ac
   libmicrohttpd/doc/texinfo.tex
   libmicrohttpd/src/Makefile.am
   libmicrohttpd/src/daemon/Makefile.am
Log:
moving stuff around

Modified: libmicrohttpd/configure.ac
===================================================================
--- libmicrohttpd/configure.ac  2008-04-12 10:43:20 UTC (rev 6675)
+++ libmicrohttpd/configure.ac  2008-04-12 20:45:58 UTC (rev 6676)
@@ -134,7 +134,13 @@
  AC_DEFINE([HAVE_MESSAGES],[1],[Include error messages])
 fi
 
+# optional: have zzuf, socat?
+AC_CHECK_PROG([HAVE_ZZUF],[zzuf], 1, 0)
+AC_CHECK_PROG([HAVE_SOCAT],[socat], 1, 0)
 
+AM_CONDITIONAL(HAVE_ZZUF, test 0 != $HAVE_ZZUF)
+AM_CONDITIONAL(HAVE_SOCAT, test 0 != $HAVE_SOCAT)
+
 AC_SUBST(CPPFLAGS)
 AC_SUBST(LIBS)
 AC_SUBST(LDFLAGS)
@@ -147,7 +153,10 @@
 m4/Makefile
 src/Makefile
 src/include/Makefile
-src/daemon/Makefile])
+src/daemon/Makefile
+src/examples/Makefile
+src/testcurl/Makefile
+src/testzzuf/Makefile])
 AC_OUTPUT
 
 if test "$curl" != 1

Modified: libmicrohttpd/doc/texinfo.tex
===================================================================
--- libmicrohttpd/doc/texinfo.tex       2008-04-12 10:43:20 UTC (rev 6675)
+++ libmicrohttpd/doc/texinfo.tex       2008-04-12 20:45:58 UTC (rev 6676)
@@ -3,16 +3,16 @@
 % Load plain if necessary, i.e., if running under initex.
 \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
 %
-\def\texinfoversion{2006-10-04.17}
+\def\texinfoversion{2007-12-02.17}
 %
-% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
-% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free
-% Software Foundation, Inc.
+% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, 2007,
+% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+% 2007 Free Software Foundation, Inc.
 %
-% This texinfo.tex file is free software; you can redistribute it and/or
+% This texinfo.tex file is free software: you can redistribute it and/or
 % modify it under the terms of the GNU General Public License as
-% published by the Free Software Foundation; either version 2, or (at
-% your option) any later version.
+% published by the Free Software Foundation, either version 3 of the
+% License, or (at your option) any later version.
 %
 % This texinfo.tex file is distributed in the hope that it will be
 % useful, but WITHOUT ANY WARRANTY; without even the implied warranty
@@ -20,9 +20,7 @@
 % General Public License for more details.
 %
 % You should have received a copy of the GNU General Public License
-% along with this texinfo.tex file; see the file COPYING.  If not, write
-% to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-% Boston, MA 02110-1301, USA.
+% along with this program.  If not, see <http://www.gnu.org/licenses/>.
 %
 % As a special exception, when this file is read by TeX when processing
 % a Texinfo source document, you may use the result without
@@ -67,7 +65,7 @@
 \everyjob{\message{[Texinfo version \texinfoversion]}%
   \catcode`+=\active \catcode`\_=\active}
 
-\message{Basics,}
+
 \chardef\other=12
 
 % We never want plain's \outer definition of \+ in Texinfo.
@@ -279,6 +277,50 @@
 \newdimen\cornerthick \cornerthick=.3pt
 \newdimen\topandbottommargin \topandbottommargin=.75in
 
+% Output a mark which sets \thischapter, \thissection and \thiscolor.
+% We dump everything together because we only have one kind of mark.
+% This works because we only use \botmark / \topmark, not \firstmark.
+%
+% A mark contains a subexpression of the \ifcase ... \fi construct.
+% \get*marks macros below extract the needed part using \ifcase.
+%
+% Another complication is to let the user choose whether \thischapter
+% (\thissection) refers to the chapter (section) in effect at the top
+% of a page, or that at the bottom of a page.  The solution is
+% described on page 260 of The TeXbook.  It involves outputting two
+% marks for the sectioning macros, one before the section break, and
+% one after.  I won't pretend I can describe this better than DEK...
+\def\domark{%
+  \toks0=\expandafter{\lastchapterdefs}%
+  \toks2=\expandafter{\lastsectiondefs}%
+  \toks4=\expandafter{\prevchapterdefs}%
+  \toks6=\expandafter{\prevsectiondefs}%
+  \toks8=\expandafter{\lastcolordefs}%
+  \mark{%
+                   \the\toks0 \the\toks2
+      \noexpand\or \the\toks4 \the\toks6
+    \noexpand\else \the\toks8
+  }%
+}
+% \topmark doesn't work for the very first chapter (after the title
+% page or the contents), so we use \firstmark there -- this gets us
+% the mark with the chapter defs, unless the user sneaks in, e.g.,
+% @setcolor (or @url, or @link, etc.) between @contents and the very
+% first @chapter.
+\def\gettopheadingmarks{%
+  \ifcase0\topmark\fi
+  \ifx\thischapter\empty \ifcase0\firstmark\fi \fi
+}
+\def\getbottomheadingmarks{\ifcase1\botmark\fi}
+\def\getcolormarks{\ifcase2\topmark\fi}
+
+% Avoid "undefined control sequence" errors.
+\def\lastchapterdefs{}
+\def\lastsectiondefs{}
+\def\prevchapterdefs{}
+\def\prevsectiondefs{}
+\def\lastcolordefs{}
+
 % Main output routine.
 \chardef\PAGE = 255
 \output = {\onepageout{\pagecontents\PAGE}}
@@ -296,7 +338,9 @@
   %
   % Do this outside of the \shipout so @code etc. will be expanded in
   % the headline as they should be, not taken literally (outputting ''code).
+  \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi
   \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
+  \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi
   \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}%
   %
   {%
@@ -375,7 +419,7 @@
 % marginal hacks, address@hidden (Juha Takala)
 \ifvoid\margin\else % marginal info is present
   \rlap{\kern\hsize\vbox address@hidden \vss}}\fi
address@hidden \unvbox#1
address@hidden \unvbox#1\relax
 \ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
 address@hidden \kern-\dimen@ \vfil \fi}
 }
@@ -1225,8 +1269,9 @@
 
 % To handle parens, we must adopt a different approach, since parens are
 % not active characters.  hyperref.dtx (which has the same problem as
-% us) handles it with this amazing macro to replace tokens.  I've
-% tinkered with it a little for texinfo, but it's definitely from there.
+% us) handles it with this amazing macro to replace tokens, with minor
+% changes for Texinfo.  It is included here under the GPL by permission
+% from the author, Heiko Oberdiek.
 % 
 % #1 is the tokens to replace.
 % #2 is the replacement.
@@ -1255,13 +1300,83 @@
   \HyPsdSubst{)}{\realbackslash)}{#1}%
 }
 
+\newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images
+with PDF output, and none of those formats could be found.  (.eps cannot
+be supported due to the design of the PDF format; use regular TeX (DVI
+output) for that.)}
+
 \ifpdf
-  \input pdfcolor
-  \pdfcatalog{/PageMode /UseOutlines}%
+  %
+  % Color manipulation macros based on pdfcolor.tex.
+  \def\cmykDarkRed{0.28 1 1 0.35}
+  \def\cmykBlack{0 0 0 1}
+  %
+  \def\pdfsetcolor#1{\pdfliteral{#1 k}}
+  % Set color, and create a mark which defines \thiscolor accordingly,
+  % so that \makeheadline knows which color to restore.
+  \def\setcolor#1{%
+    \xdef\lastcolordefs{\gdef\noexpand\thiscolor{#1}}%
+    \domark
+    \pdfsetcolor{#1}%
+  }
+  %
+  \def\maincolor{\cmykBlack}
+  \pdfsetcolor{\maincolor}
+  \edef\thiscolor{\maincolor}
+  \def\lastcolordefs{}
+  %
+  \def\makefootline{%
+    \baselineskip24pt
+    \line{\pdfsetcolor{\maincolor}\the\footline}%
+  }
+  %
+  \def\makeheadline{%
+    \vbox to 0pt{%
+      \vskip-22.5pt
+      \line{%
+        \vbox to8.5pt{}%
+        % Extract \thiscolor definition from the marks.
+        \getcolormarks
+        % Typeset the headline with \maincolor, then restore the color.
+        \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}%
+      }%
+      \vss
+    }%
+    \nointerlineskip
+  }
+  %
+  %
+  \pdfcatalog{/PageMode /UseOutlines}
+  %
   % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto).
   \def\dopdfimage#1#2#3{%
     \def\imagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}%
     \def\imageheight{#3}\setbox2 = \hbox{\ignorespaces #3}%
+    %
+    % pdftex (and the PDF format) support .png, .jpg, .pdf (among
+    % others).  Let's try in that order.
+    \let\pdfimgext=\empty
+    \begingroup
+      \openin 1 #1.png \ifeof 1
+        \openin 1 #1.jpg \ifeof 1
+          \openin 1 #1.jpeg \ifeof 1
+            \openin 1 #1.JPG \ifeof 1
+              \openin 1 #1.pdf \ifeof 1
+                \errhelp = \nopdfimagehelp
+                \errmessage{Could not find image file #1 for pdf}%
+              \else \gdef\pdfimgext{pdf}%
+              \fi
+            \else \gdef\pdfimgext{JPG}%
+            \fi
+          \else \gdef\pdfimgext{jpeg}%
+          \fi
+        \else \gdef\pdfimgext{jpg}%
+        \fi
+      \else \gdef\pdfimgext{png}%
+      \fi
+      \closein 1
+    \endgroup
+    %
     % without \immediate, pdftex seg faults when the same image is
     % included twice.  (Version 3.14159-pre-1.0-unofficial-20010704.)
     \ifnum\pdftexversion < 14
@@ -1272,28 +1387,35 @@
       \ifdim \wd0 >0pt width \imagewidth \fi
       \ifdim \wd2 >0pt height \imageheight \fi
       \ifnum\pdftexversion<13
-         #1.pdf%
+         #1.\pdfimgext
        \else
-         {#1.pdf}%
+         {#1.\pdfimgext}%
        \fi
     \ifnum\pdftexversion < 14 \else
       \pdfrefximage \pdflastximage
     \fi}
+  %
   \def\pdfmkdest#1{{%
     % We have to set dummies so commands such as @code, and characters
     % such as \, aren't expanded when present in a section title.
-    \atdummies
+    \indexnofonts
+    \turnoffactive
     \activebackslashdouble
+    \makevalueexpandable
     \def\pdfdestname{#1}%
     \backslashparens\pdfdestname
-    \pdfdest name{\pdfdestname} xyz%
-  }}%
+    \safewhatsit{\pdfdest name{\pdfdestname} xyz}%
+  }}
   %
   % used to mark target names; must be expandable.
-  \def\pdfmkpgn#1{#1}%
+  \def\pdfmkpgn#1{#1}
   %
-  \let\linkcolor = \Blue  % was Cyan, but that seems light?
-  \def\endlink{\Black\pdfendlink}
+  % by default, use a color that is dark enough to print on paper as
+  % nearly black, but still distinguishable for online viewing.
+  \def\urlcolor{\cmykDarkRed}
+  \def\linkcolor{\cmykDarkRed}
+  \def\endlink{\setcolor{\maincolor}\pdfendlink}
+  %
   % Adding outlines to PDF; macros for calculating structure of outlines
   % come from Petr Olsak
   \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0%
@@ -1395,7 +1517,7 @@
       \indexnofonts
       \setupdatafile
       \catcode`\\=\active \otherbackslash
-      \input \jobname.toc
+      \input \tocreadfilename
     \endgroup
   }
   %
@@ -1425,7 +1547,7 @@
       address@hidden@}%
       \let\/=\empty
       \makevalueexpandable
-      \leavevmode\Red
+      \leavevmode\setcolor{\urlcolor}%
       \startlink attr{/Border [0 0 0]}%
         user{/Subtype /Link /A << /S /URI /URI (#1) >>}%
     \endgroup}
@@ -1452,13 +1574,14 @@
     {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0}
   \def\pdflink#1{%
     \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}}
-    \linkcolor #1\endlink}
+    \setcolor{\linkcolor}#1\endlink}
   \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
 \else
   \let\pdfmkdest = \gobble
   \let\pdfurl = \gobble
   \let\endlink = \relax
-  \let\linkcolor = \relax
+  \let\setcolor = \gobble
+  \let\pdfsetcolor = \gobble
   \let\pdfmakeoutlines = \relax
 \fi  % \ifx\pdfoutput
 
@@ -1505,8 +1628,12 @@
 \def\strutheightpercent{.70833}
 \def\strutdepthpercent {.29167}
 %
+% can get a sort of poor man's double spacing by redefining this.
+\def\baselinefactor{1}
+%
 \def\setleading#1{%
-  \normalbaselineskip = #1\relax
+  \dimen0 = #1\relax
+  \normalbaselineskip = \baselinefactor\dimen0
   \normallineskip = \lineskipfactor\normalbaselineskip
   \normalbaselines
   \setbox\strutbox =\hbox{%
@@ -1515,13 +1642,280 @@
   }%
 }
 
+% PDF CMaps.  See also LaTeX's t1.cmap.
+%
+% do nothing with this by default.
+\expandafter\let\csname cmapOT1\endcsname\gobble
+\expandafter\let\csname cmapOT1IT\endcsname\gobble
+\expandafter\let\csname cmapOT1TT\endcsname\gobble
 
+% if we are producing pdf, and we have \pdffontattr, then define cmaps.
+% (\pdffontattr was introduced many years ago, but people still run
+% older pdftex's; it's easy to conditionalize, so we do.)
+\ifpdf \ifx\pdffontattr\undefined \else
+  \begingroup
+    \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
+    \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
+%%DocumentNeededResources: ProcSet (CIDInit)
+%%IncludeResource: ProcSet (CIDInit)
+%%BeginResource: CMap (TeX-OT1-0)
+%%Title: (TeX-OT1-0 TeX OT1 0)
+%%Version: 1.000
+%%EndComments
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo
+<< /Registry (TeX)
+/Ordering (OT1)
+/Supplement 0
+>> def
+/CMapName /TeX-OT1-0 def
+/CMapType 2 def
+1 begincodespacerange
+<00> <7F>
+endcodespacerange
+8 beginbfrange
+<00> <01> <0393>
+<09> <0A> <03A8>
+<23> <26> <0023>
+<28> <3B> <0028>
+<3F> <5B> <003F>
+<5D> <5E> <005D>
+<61> <7A> <0061>
+<7B> <7C> <2013>
+endbfrange
+40 beginbfchar
+<02> <0398>
+<03> <039B>
+<04> <039E>
+<05> <03A0>
+<06> <03A3>
+<07> <03D2>
+<08> <03A6>
+<0B> <00660066>
+<0C> <00660069>
+<0D> <0066006C>
+<0E> <006600660069>
+<0F> <00660066006C>
+<10> <0131>
+<11> <0237>
+<12> <0060>
+<13> <00B4>
+<14> <02C7>
+<15> <02D8>
+<16> <00AF>
+<17> <02DA>
+<18> <00B8>
+<19> <00DF>
+<1A> <00E6>
+<1B> <0153>
+<1C> <00F8>
+<1D> <00C6>
+<1E> <0152>
+<1F> <00D8>
+<21> <0021>
+<22> <201D>
+<27> <2019>
+<3C> <00A1>
+<3D> <003D>
+<3E> <00BF>
+<5C> <201C>
+<5F> <02D9>
+<60> <2018>
+<7D> <02DD>
+<7E> <007E>
+<7F> <00A8>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+%%EndResource
+%%EOF
+    }\endgroup
+  \expandafter\edef\csname cmapOT1\endcsname#1{%
+    \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
+  }%
+%
+% \cmapOT1IT
+  \begingroup
+    \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
+    \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
+%%DocumentNeededResources: ProcSet (CIDInit)
+%%IncludeResource: ProcSet (CIDInit)
+%%BeginResource: CMap (TeX-OT1IT-0)
+%%Title: (TeX-OT1IT-0 TeX OT1IT 0)
+%%Version: 1.000
+%%EndComments
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo
+<< /Registry (TeX)
+/Ordering (OT1IT)
+/Supplement 0
+>> def
+/CMapName /TeX-OT1IT-0 def
+/CMapType 2 def
+1 begincodespacerange
+<00> <7F>
+endcodespacerange
+8 beginbfrange
+<00> <01> <0393>
+<09> <0A> <03A8>
+<25> <26> <0025>
+<28> <3B> <0028>
+<3F> <5B> <003F>
+<5D> <5E> <005D>
+<61> <7A> <0061>
+<7B> <7C> <2013>
+endbfrange
+42 beginbfchar
+<02> <0398>
+<03> <039B>
+<04> <039E>
+<05> <03A0>
+<06> <03A3>
+<07> <03D2>
+<08> <03A6>
+<0B> <00660066>
+<0C> <00660069>
+<0D> <0066006C>
+<0E> <006600660069>
+<0F> <00660066006C>
+<10> <0131>
+<11> <0237>
+<12> <0060>
+<13> <00B4>
+<14> <02C7>
+<15> <02D8>
+<16> <00AF>
+<17> <02DA>
+<18> <00B8>
+<19> <00DF>
+<1A> <00E6>
+<1B> <0153>
+<1C> <00F8>
+<1D> <00C6>
+<1E> <0152>
+<1F> <00D8>
+<21> <0021>
+<22> <201D>
+<23> <0023>
+<24> <00A3>
+<27> <2019>
+<3C> <00A1>
+<3D> <003D>
+<3E> <00BF>
+<5C> <201C>
+<5F> <02D9>
+<60> <2018>
+<7D> <02DD>
+<7E> <007E>
+<7F> <00A8>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+%%EndResource
+%%EOF
+    }\endgroup
+  \expandafter\edef\csname cmapOT1IT\endcsname#1{%
+    \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
+  }%
+%
+% \cmapOT1TT
+  \begingroup
+    \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
+    \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
+%%DocumentNeededResources: ProcSet (CIDInit)
+%%IncludeResource: ProcSet (CIDInit)
+%%BeginResource: CMap (TeX-OT1TT-0)
+%%Title: (TeX-OT1TT-0 TeX OT1TT 0)
+%%Version: 1.000
+%%EndComments
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo
+<< /Registry (TeX)
+/Ordering (OT1TT)
+/Supplement 0
+>> def
+/CMapName /TeX-OT1TT-0 def
+/CMapType 2 def
+1 begincodespacerange
+<00> <7F>
+endcodespacerange
+5 beginbfrange
+<00> <01> <0393>
+<09> <0A> <03A8>
+<21> <26> <0021>
+<28> <5F> <0028>
+<61> <7E> <0061>
+endbfrange
+32 beginbfchar
+<02> <0398>
+<03> <039B>
+<04> <039E>
+<05> <03A0>
+<06> <03A3>
+<07> <03D2>
+<08> <03A6>
+<0B> <2191>
+<0C> <2193>
+<0D> <0027>
+<0E> <00A1>
+<0F> <00BF>
+<10> <0131>
+<11> <0237>
+<12> <0060>
+<13> <00B4>
+<14> <02C7>
+<15> <02D8>
+<16> <00AF>
+<17> <02DA>
+<18> <00B8>
+<19> <00DF>
+<1A> <00E6>
+<1B> <0153>
+<1C> <00F8>
+<1D> <00C6>
+<1E> <0152>
+<1F> <00D8>
+<20> <2423>
+<27> <2019>
+<60> <2018>
+<7F> <00A8>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+%%EndResource
+%%EOF
+    }\endgroup
+  \expandafter\edef\csname cmapOT1TT\endcsname#1{%
+    \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
+  }%
+\fi\fi
+
+
 % Set the font macro #1 to the font named #2, adding on the
 % specified font prefix (normally `cm').
-% #3 is the font's design size, #4 is a scale factor
-\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4}
+% #3 is the font's design size, #4 is a scale factor, #5 is the CMap
+% encoding (currently only OT1, OT1IT and OT1TT are allowed, pass
+% empty to omit).
+\def\setfont#1#2#3#4#5{%
+  \font#1=\fontprefix#2#3 scaled #4
+  \csname cmap#5\endcsname#1%
+}
+% This is what gets called when #5 of \setfont is empty.
+\let\cmap\gobble
+% emacs-page end of cmaps
 
-
 % Use cm as the default font prefix.
 % To specify the font prefix, you must define \fontprefix
 % before you read in texinfo.tex.
@@ -1548,119 +1942,127 @@
 % Definitions for a main text size of 11pt.  This is the default in
 % Texinfo.
 % 
-\def\definetextfontsizexi{
+\def\definetextfontsizexi{%
 % Text fonts (11.2pt, magstep1).
 \def\textnominalsize{11pt}
 \edef\mainmagstep{\magstephalf}
-\setfont\textrm\rmshape{10}{\mainmagstep}
-\setfont\texttt\ttshape{10}{\mainmagstep}
-\setfont\textbf\bfshape{10}{\mainmagstep}
-\setfont\textit\itshape{10}{\mainmagstep}
-\setfont\textsl\slshape{10}{\mainmagstep}
-\setfont\textsf\sfshape{10}{\mainmagstep}
-\setfont\textsc\scshape{10}{\mainmagstep}
-\setfont\textttsl\ttslshape{10}{\mainmagstep}
+\setfont\textrm\rmshape{10}{\mainmagstep}{OT1}
+\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT}
+\setfont\textbf\bfshape{10}{\mainmagstep}{OT1}
+\setfont\textit\itshape{10}{\mainmagstep}{OT1IT}
+\setfont\textsl\slshape{10}{\mainmagstep}{OT1}
+\setfont\textsf\sfshape{10}{\mainmagstep}{OT1}
+\setfont\textsc\scshape{10}{\mainmagstep}{OT1}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT}
 \font\texti=cmmi10 scaled \mainmagstep
 \font\textsy=cmsy10 scaled \mainmagstep
+\def\textecsize{1095}
 
 % A few fonts for @defun names and args.
-\setfont\defbf\bfshape{10}{\magstep1}
-\setfont\deftt\ttshape{10}{\magstep1}
-\setfont\defttsl\ttslshape{10}{\magstep1}
+\setfont\defbf\bfshape{10}{\magstep1}{OT1}
+\setfont\deftt\ttshape{10}{\magstep1}{OT1TT}
+\setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT}
 \def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf}
 
 % Fonts for indices, footnotes, small examples (9pt).
 \def\smallnominalsize{9pt}
-\setfont\smallrm\rmshape{9}{1000}
-\setfont\smalltt\ttshape{9}{1000}
-\setfont\smallbf\bfshape{10}{900}
-\setfont\smallit\itshape{9}{1000}
-\setfont\smallsl\slshape{9}{1000}
-\setfont\smallsf\sfshape{9}{1000}
-\setfont\smallsc\scshape{10}{900}
-\setfont\smallttsl\ttslshape{10}{900}
+\setfont\smallrm\rmshape{9}{1000}{OT1}
+\setfont\smalltt\ttshape{9}{1000}{OT1TT}
+\setfont\smallbf\bfshape{10}{900}{OT1}
+\setfont\smallit\itshape{9}{1000}{OT1IT}
+\setfont\smallsl\slshape{9}{1000}{OT1}
+\setfont\smallsf\sfshape{9}{1000}{OT1}
+\setfont\smallsc\scshape{10}{900}{OT1}
+\setfont\smallttsl\ttslshape{10}{900}{OT1TT}
 \font\smalli=cmmi9
 \font\smallsy=cmsy9
+\def\smallecsize{0900}
 
 % Fonts for small examples (8pt).
 \def\smallernominalsize{8pt}
-\setfont\smallerrm\rmshape{8}{1000}
-\setfont\smallertt\ttshape{8}{1000}
-\setfont\smallerbf\bfshape{10}{800}
-\setfont\smallerit\itshape{8}{1000}
-\setfont\smallersl\slshape{8}{1000}
-\setfont\smallersf\sfshape{8}{1000}
-\setfont\smallersc\scshape{10}{800}
-\setfont\smallerttsl\ttslshape{10}{800}
+\setfont\smallerrm\rmshape{8}{1000}{OT1}
+\setfont\smallertt\ttshape{8}{1000}{OT1TT}
+\setfont\smallerbf\bfshape{10}{800}{OT1}
+\setfont\smallerit\itshape{8}{1000}{OT1IT}
+\setfont\smallersl\slshape{8}{1000}{OT1}
+\setfont\smallersf\sfshape{8}{1000}{OT1}
+\setfont\smallersc\scshape{10}{800}{OT1}
+\setfont\smallerttsl\ttslshape{10}{800}{OT1TT}
 \font\smalleri=cmmi8
 \font\smallersy=cmsy8
+\def\smallerecsize{0800}
 
 % Fonts for title page (20.4pt):
 \def\titlenominalsize{20pt}
-\setfont\titlerm\rmbshape{12}{\magstep3}
-\setfont\titleit\itbshape{10}{\magstep4}
-\setfont\titlesl\slbshape{10}{\magstep4}
-\setfont\titlett\ttbshape{12}{\magstep3}
-\setfont\titlettsl\ttslshape{10}{\magstep4}
-\setfont\titlesf\sfbshape{17}{\magstep1}
+\setfont\titlerm\rmbshape{12}{\magstep3}{OT1}
+\setfont\titleit\itbshape{10}{\magstep4}{OT1IT}
+\setfont\titlesl\slbshape{10}{\magstep4}{OT1}
+\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT}
+\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT}
+\setfont\titlesf\sfbshape{17}{\magstep1}{OT1}
 \let\titlebf=\titlerm
-\setfont\titlesc\scbshape{10}{\magstep4}
+\setfont\titlesc\scbshape{10}{\magstep4}{OT1}
 \font\titlei=cmmi12 scaled \magstep3
 \font\titlesy=cmsy10 scaled \magstep4
 \def\authorrm{\secrm}
 \def\authortt{\sectt}
+\def\titleecsize{2074}
 
 % Chapter (and unnumbered) fonts (17.28pt).
 \def\chapnominalsize{17pt}
-\setfont\chaprm\rmbshape{12}{\magstep2}
-\setfont\chapit\itbshape{10}{\magstep3}
-\setfont\chapsl\slbshape{10}{\magstep3}
-\setfont\chaptt\ttbshape{12}{\magstep2}
-\setfont\chapttsl\ttslshape{10}{\magstep3}
-\setfont\chapsf\sfbshape{17}{1000}
+\setfont\chaprm\rmbshape{12}{\magstep2}{OT1}
+\setfont\chapit\itbshape{10}{\magstep3}{OT1IT}
+\setfont\chapsl\slbshape{10}{\magstep3}{OT1}
+\setfont\chaptt\ttbshape{12}{\magstep2}{OT1TT}
+\setfont\chapttsl\ttslshape{10}{\magstep3}{OT1TT}
+\setfont\chapsf\sfbshape{17}{1000}{OT1}
 \let\chapbf=\chaprm
-\setfont\chapsc\scbshape{10}{\magstep3}
+\setfont\chapsc\scbshape{10}{\magstep3}{OT1}
 \font\chapi=cmmi12 scaled \magstep2
 \font\chapsy=cmsy10 scaled \magstep3
+\def\chapecsize{1728}
 
 % Section fonts (14.4pt).
 \def\secnominalsize{14pt}
-\setfont\secrm\rmbshape{12}{\magstep1}
-\setfont\secit\itbshape{10}{\magstep2}
-\setfont\secsl\slbshape{10}{\magstep2}
-\setfont\sectt\ttbshape{12}{\magstep1}
-\setfont\secttsl\ttslshape{10}{\magstep2}
-\setfont\secsf\sfbshape{12}{\magstep1}
+\setfont\secrm\rmbshape{12}{\magstep1}{OT1}
+\setfont\secit\itbshape{10}{\magstep2}{OT1IT}
+\setfont\secsl\slbshape{10}{\magstep2}{OT1}
+\setfont\sectt\ttbshape{12}{\magstep1}{OT1TT}
+\setfont\secttsl\ttslshape{10}{\magstep2}{OT1TT}
+\setfont\secsf\sfbshape{12}{\magstep1}{OT1}
 \let\secbf\secrm
-\setfont\secsc\scbshape{10}{\magstep2}
+\setfont\secsc\scbshape{10}{\magstep2}{OT1}
 \font\seci=cmmi12 scaled \magstep1
 \font\secsy=cmsy10 scaled \magstep2
+\def\sececsize{1440}
 
 % Subsection fonts (13.15pt).
 \def\ssecnominalsize{13pt}
-\setfont\ssecrm\rmbshape{12}{\magstephalf}
-\setfont\ssecit\itbshape{10}{1315}
-\setfont\ssecsl\slbshape{10}{1315}
-\setfont\ssectt\ttbshape{12}{\magstephalf}
-\setfont\ssecttsl\ttslshape{10}{1315}
-\setfont\ssecsf\sfbshape{12}{\magstephalf}
+\setfont\ssecrm\rmbshape{12}{\magstephalf}{OT1}
+\setfont\ssecit\itbshape{10}{1315}{OT1IT}
+\setfont\ssecsl\slbshape{10}{1315}{OT1}
+\setfont\ssectt\ttbshape{12}{\magstephalf}{OT1TT}
+\setfont\ssecttsl\ttslshape{10}{1315}{OT1TT}
+\setfont\ssecsf\sfbshape{12}{\magstephalf}{OT1}
 \let\ssecbf\ssecrm
-\setfont\ssecsc\scbshape{10}{1315}
+\setfont\ssecsc\scbshape{10}{1315}{OT1}
 \font\sseci=cmmi12 scaled \magstephalf
 \font\ssecsy=cmsy10 scaled 1315
+\def\ssececsize{1200}
 
 % Reduced fonts for @acro in text (10pt).
 \def\reducednominalsize{10pt}
-\setfont\reducedrm\rmshape{10}{1000}
-\setfont\reducedtt\ttshape{10}{1000}
-\setfont\reducedbf\bfshape{10}{1000}
-\setfont\reducedit\itshape{10}{1000}
-\setfont\reducedsl\slshape{10}{1000}
-\setfont\reducedsf\sfshape{10}{1000}
-\setfont\reducedsc\scshape{10}{1000}
-\setfont\reducedttsl\ttslshape{10}{1000}
+\setfont\reducedrm\rmshape{10}{1000}{OT1}
+\setfont\reducedtt\ttshape{10}{1000}{OT1TT}
+\setfont\reducedbf\bfshape{10}{1000}{OT1}
+\setfont\reducedit\itshape{10}{1000}{OT1IT}
+\setfont\reducedsl\slshape{10}{1000}{OT1}
+\setfont\reducedsf\sfshape{10}{1000}{OT1}
+\setfont\reducedsc\scshape{10}{1000}{OT1}
+\setfont\reducedttsl\ttslshape{10}{1000}{OT1TT}
 \font\reducedi=cmmi10
 \font\reducedsy=cmsy10
+\def\reducedecsize{1000}
 
 % reset the current fonts
 \textfonts
@@ -1677,115 +2079,123 @@
 % Text fonts (10pt).
 \def\textnominalsize{10pt}
 \edef\mainmagstep{1000}
-\setfont\textrm\rmshape{10}{\mainmagstep}
-\setfont\texttt\ttshape{10}{\mainmagstep}
-\setfont\textbf\bfshape{10}{\mainmagstep}
-\setfont\textit\itshape{10}{\mainmagstep}
-\setfont\textsl\slshape{10}{\mainmagstep}
-\setfont\textsf\sfshape{10}{\mainmagstep}
-\setfont\textsc\scshape{10}{\mainmagstep}
-\setfont\textttsl\ttslshape{10}{\mainmagstep}
+\setfont\textrm\rmshape{10}{\mainmagstep}{OT1}
+\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT}
+\setfont\textbf\bfshape{10}{\mainmagstep}{OT1}
+\setfont\textit\itshape{10}{\mainmagstep}{OT1IT}
+\setfont\textsl\slshape{10}{\mainmagstep}{OT1}
+\setfont\textsf\sfshape{10}{\mainmagstep}{OT1}
+\setfont\textsc\scshape{10}{\mainmagstep}{OT1}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT}
 \font\texti=cmmi10 scaled \mainmagstep
 \font\textsy=cmsy10 scaled \mainmagstep
+\def\textecsize{1000}
 
 % A few fonts for @defun names and args.
-\setfont\defbf\bfshape{10}{\magstephalf}
-\setfont\deftt\ttshape{10}{\magstephalf}
-\setfont\defttsl\ttslshape{10}{\magstephalf}
+\setfont\defbf\bfshape{10}{\magstephalf}{OT1}
+\setfont\deftt\ttshape{10}{\magstephalf}{OT1TT}
+\setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT}
 \def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf}
 
 % Fonts for indices, footnotes, small examples (9pt).
 \def\smallnominalsize{9pt}
-\setfont\smallrm\rmshape{9}{1000}
-\setfont\smalltt\ttshape{9}{1000}
-\setfont\smallbf\bfshape{10}{900}
-\setfont\smallit\itshape{9}{1000}
-\setfont\smallsl\slshape{9}{1000}
-\setfont\smallsf\sfshape{9}{1000}
-\setfont\smallsc\scshape{10}{900}
-\setfont\smallttsl\ttslshape{10}{900}
+\setfont\smallrm\rmshape{9}{1000}{OT1}
+\setfont\smalltt\ttshape{9}{1000}{OT1TT}
+\setfont\smallbf\bfshape{10}{900}{OT1}
+\setfont\smallit\itshape{9}{1000}{OT1IT}
+\setfont\smallsl\slshape{9}{1000}{OT1}
+\setfont\smallsf\sfshape{9}{1000}{OT1}
+\setfont\smallsc\scshape{10}{900}{OT1}
+\setfont\smallttsl\ttslshape{10}{900}{OT1TT}
 \font\smalli=cmmi9
 \font\smallsy=cmsy9
+\def\smallecsize{0900}
 
 % Fonts for small examples (8pt).
 \def\smallernominalsize{8pt}
-\setfont\smallerrm\rmshape{8}{1000}
-\setfont\smallertt\ttshape{8}{1000}
-\setfont\smallerbf\bfshape{10}{800}
-\setfont\smallerit\itshape{8}{1000}
-\setfont\smallersl\slshape{8}{1000}
-\setfont\smallersf\sfshape{8}{1000}
-\setfont\smallersc\scshape{10}{800}
-\setfont\smallerttsl\ttslshape{10}{800}
+\setfont\smallerrm\rmshape{8}{1000}{OT1}
+\setfont\smallertt\ttshape{8}{1000}{OT1TT}
+\setfont\smallerbf\bfshape{10}{800}{OT1}
+\setfont\smallerit\itshape{8}{1000}{OT1IT}
+\setfont\smallersl\slshape{8}{1000}{OT1}
+\setfont\smallersf\sfshape{8}{1000}{OT1}
+\setfont\smallersc\scshape{10}{800}{OT1}
+\setfont\smallerttsl\ttslshape{10}{800}{OT1TT}
 \font\smalleri=cmmi8
 \font\smallersy=cmsy8
+\def\smallerecsize{0800}
 
 % Fonts for title page (20.4pt):
 \def\titlenominalsize{20pt}
-\setfont\titlerm\rmbshape{12}{\magstep3}
-\setfont\titleit\itbshape{10}{\magstep4}
-\setfont\titlesl\slbshape{10}{\magstep4}
-\setfont\titlett\ttbshape{12}{\magstep3}
-\setfont\titlettsl\ttslshape{10}{\magstep4}
-\setfont\titlesf\sfbshape{17}{\magstep1}
+\setfont\titlerm\rmbshape{12}{\magstep3}{OT1}
+\setfont\titleit\itbshape{10}{\magstep4}{OT1IT}
+\setfont\titlesl\slbshape{10}{\magstep4}{OT1}
+\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT}
+\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT}
+\setfont\titlesf\sfbshape{17}{\magstep1}{OT1}
 \let\titlebf=\titlerm
-\setfont\titlesc\scbshape{10}{\magstep4}
+\setfont\titlesc\scbshape{10}{\magstep4}{OT1}
 \font\titlei=cmmi12 scaled \magstep3
 \font\titlesy=cmsy10 scaled \magstep4
 \def\authorrm{\secrm}
 \def\authortt{\sectt}
+\def\titleecsize{2074}
 
 % Chapter fonts (14.4pt).
 \def\chapnominalsize{14pt}
-\setfont\chaprm\rmbshape{12}{\magstep1}
-\setfont\chapit\itbshape{10}{\magstep2}
-\setfont\chapsl\slbshape{10}{\magstep2}
-\setfont\chaptt\ttbshape{12}{\magstep1}
-\setfont\chapttsl\ttslshape{10}{\magstep2}
-\setfont\chapsf\sfbshape{12}{\magstep1}
+\setfont\chaprm\rmbshape{12}{\magstep1}{OT1}
+\setfont\chapit\itbshape{10}{\magstep2}{OT1IT}
+\setfont\chapsl\slbshape{10}{\magstep2}{OT1}
+\setfont\chaptt\ttbshape{12}{\magstep1}{OT1TT}
+\setfont\chapttsl\ttslshape{10}{\magstep2}{OT1TT}
+\setfont\chapsf\sfbshape{12}{\magstep1}{OT1}
 \let\chapbf\chaprm
-\setfont\chapsc\scbshape{10}{\magstep2}
+\setfont\chapsc\scbshape{10}{\magstep2}{OT1}
 \font\chapi=cmmi12 scaled \magstep1
 \font\chapsy=cmsy10 scaled \magstep2
+\def\chapecsize{1440}
 
 % Section fonts (12pt).
 \def\secnominalsize{12pt}
-\setfont\secrm\rmbshape{12}{1000}
-\setfont\secit\itbshape{10}{\magstep1}
-\setfont\secsl\slbshape{10}{\magstep1}
-\setfont\sectt\ttbshape{12}{1000}
-\setfont\secttsl\ttslshape{10}{\magstep1}
-\setfont\secsf\sfbshape{12}{1000}
+\setfont\secrm\rmbshape{12}{1000}{OT1}
+\setfont\secit\itbshape{10}{\magstep1}{OT1IT}
+\setfont\secsl\slbshape{10}{\magstep1}{OT1}
+\setfont\sectt\ttbshape{12}{1000}{OT1TT}
+\setfont\secttsl\ttslshape{10}{\magstep1}{OT1TT}
+\setfont\secsf\sfbshape{12}{1000}{OT1}
 \let\secbf\secrm
-\setfont\secsc\scbshape{10}{\magstep1}
+\setfont\secsc\scbshape{10}{\magstep1}{OT1}
 \font\seci=cmmi12 
 \font\secsy=cmsy10 scaled \magstep1
+\def\sececsize{1200}
 
 % Subsection fonts (10pt).
 \def\ssecnominalsize{10pt}
-\setfont\ssecrm\rmbshape{10}{1000}
-\setfont\ssecit\itbshape{10}{1000}
-\setfont\ssecsl\slbshape{10}{1000}
-\setfont\ssectt\ttbshape{10}{1000}
-\setfont\ssecttsl\ttslshape{10}{1000}
-\setfont\ssecsf\sfbshape{10}{1000}
+\setfont\ssecrm\rmbshape{10}{1000}{OT1}
+\setfont\ssecit\itbshape{10}{1000}{OT1IT}
+\setfont\ssecsl\slbshape{10}{1000}{OT1}
+\setfont\ssectt\ttbshape{10}{1000}{OT1TT}
+\setfont\ssecttsl\ttslshape{10}{1000}{OT1TT}
+\setfont\ssecsf\sfbshape{10}{1000}{OT1}
 \let\ssecbf\ssecrm
-\setfont\ssecsc\scbshape{10}{1000}
+\setfont\ssecsc\scbshape{10}{1000}{OT1}
 \font\sseci=cmmi10
 \font\ssecsy=cmsy10
+\def\ssececsize{1000}
 
 % Reduced fonts for @acro in text (9pt).
 \def\reducednominalsize{9pt}
-\setfont\reducedrm\rmshape{9}{1000}
-\setfont\reducedtt\ttshape{9}{1000}
-\setfont\reducedbf\bfshape{10}{900}
-\setfont\reducedit\itshape{9}{1000}
-\setfont\reducedsl\slshape{9}{1000}
-\setfont\reducedsf\sfshape{9}{1000}
-\setfont\reducedsc\scshape{10}{900}
-\setfont\reducedttsl\ttslshape{10}{900}
+\setfont\reducedrm\rmshape{9}{1000}{OT1}
+\setfont\reducedtt\ttshape{9}{1000}{OT1TT}
+\setfont\reducedbf\bfshape{10}{900}{OT1}
+\setfont\reducedit\itshape{9}{1000}{OT1IT}
+\setfont\reducedsl\slshape{9}{1000}{OT1}
+\setfont\reducedsf\sfshape{9}{1000}{OT1}
+\setfont\reducedsc\scshape{10}{900}{OT1}
+\setfont\reducedttsl\ttslshape{10}{900}{OT1TT}
 \font\reducedi=cmmi9
 \font\reducedsy=cmsy9
+\def\reducedecsize{0900}
 
 % reduce space between paragraphs
 \divide\parskip by 2
@@ -1941,10 +2351,10 @@
 \newcount\fontdepth \fontdepth=0
 
 % Fonts for short table of contents.
-\setfont\shortcontrm\rmshape{12}{1000}
-\setfont\shortcontbf\bfshape{10}{\magstep1}  % no cmb12
-\setfont\shortcontsl\slshape{12}{1000}
-\setfont\shortconttt\ttshape{12}{1000}
+\setfont\shortcontrm\rmshape{12}{1000}{OT1}
+\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1}  % no cmb12
+\setfont\shortcontsl\slshape{12}{1000}{OT1}
+\setfont\shortconttt\ttshape{12}{1000}{OT1TT}
 
 %% Add scribe-like font environments, plus @l for inline lisp (usually sans
 %% serif) and @ii for TeX italic
@@ -2007,7 +2417,7 @@
   \null
 }
 \def\samp#1{`\tclose{#1}'\null}
-\setfont\keyrm\rmshape{8}{1000}
+\setfont\keyrm\rmshape{8}{1000}{OT1}
 \font\keysy=cmsy9
 \def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{%
   \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
@@ -2015,6 +2425,7 @@
      \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
     \kern-0.4pt\hrule}%
   \kern-.06em\raise0.4pt\hbox{\angleright}}}}
+\def\key #1{{\nohyphenation \uppercase{#1}}\null}
 % The old definition, with no lozenge:
 %\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
 \def\ctrl #1{{\tt \rawbackslash \hat}#1}
@@ -2299,6 +2710,35 @@
   \thiseurofont
 }
 
+% Hacks for glyphs from the EC fonts similar to \euro.  We don't
+% use \let for the aliases, because sometimes we redefine the original
+% macro, and the alias should reflect the redefinition.
+\def\guillemetleft{{\ecfont \char"13}}
+\def\guillemotleft{\guillemetleft}
+\def\guillemetright{{\ecfont \char"14}}
+\def\guillemotright{\guillemetright}
+\def\guilsinglleft{{\ecfont \char"0E}}
+\def\guilsinglright{{\ecfont \char"0F}}
+\def\quotedblbase{{\ecfont \char"12}}
+\def\quotesinglbase{{\ecfont \char"0D}}
+%
+\def\ecfont{%
+  % We can't distinguish serif/sanserif and italic/slanted, but this
+  % is used for crude hacks anyway (like adding French and German
+  % quotes to documents typeset with CM, where we lose kerning), so
+  % hopefully nobody will notice/care.
+  \edef\ecsize{\csname\curfontsize ecsize\endcsname}%
+  \edef\nominalsize{\csname\curfontsize nominalsize\endcsname}%
+  \ifx\curfontstyle\bfstylename
+    % bold:
+    \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize
+  \else
+    % regular:
+    \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize
+  \fi
+  \thisecfont
+}
+
 % @registeredsymbol - R in a circle.  The font for the R should really
 % be smaller yet, but lllsize is the best we can do for now.
 % Adapted from the plain.tex definition of \copyright.
@@ -2321,7 +2761,13 @@
 \def\Orb{\mathhexbox20D}
 \fi
 
+% Quotes.
+\chardef\quotedblleft="5C
+\chardef\quotedblright=`\"
+\chardef\quoteleft=`\`
+\chardef\quoteright=`\'
 
+
 \message{page headings,}
 
 \newskip\titlepagetopglue \titlepagetopglue = 1.5in
@@ -2490,7 +2936,34 @@
 
 \parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}}
 
+% @evenheadingmarks top     \thischapter <- chapter at the top of a page
+% @evenheadingmarks bottom  \thischapter <- chapter at the bottom of a page
+%
+% The same set of arguments for:
+%
+% @oddheadingmarks
+% @evenfootingmarks
+% @oddfootingmarks
+% @everyheadingmarks
+% @everyfootingmarks
 
+\def\evenheadingmarks{\headingmarks{even}{heading}}
+\def\oddheadingmarks{\headingmarks{odd}{heading}}
+\def\evenfootingmarks{\headingmarks{even}{footing}}
+\def\oddfootingmarks{\headingmarks{odd}{footing}}
+\def\everyheadingmarks#1 {\headingmarks{even}{heading}{#1}
+                          \headingmarks{odd}{heading}{#1} }
+\def\everyfootingmarks#1 {\headingmarks{even}{footing}{#1}
+                          \headingmarks{odd}{footing}{#1} }
+% #1 = even/odd, #2 = heading/footing, #3 = top/bottom.
+\def\headingmarks#1#2#3 {%
+  \expandafter\let\expandafter\temp \csname get#3headingmarks\endcsname
+  \global\expandafter\let\csname get#1#2marks\endcsname \temp
+}
+
+\everyheadingmarks bottom
+\everyfootingmarks bottom
+
 % @headings double      turns headings on for double-sided printing.
 % @headings single      turns headings on for single-sided printing.
 % @headings off         turns them off.
@@ -3530,11 +4003,21 @@
   \definedummyword\equiv
   \definedummyword\error
   \definedummyword\euro
+  \definedummyword\guillemetleft
+  \definedummyword\guillemetright
+  \definedummyword\guilsinglleft
+  \definedummyword\guilsinglright
   \definedummyword\expansion
   \definedummyword\minus
   \definedummyword\pounds
   \definedummyword\point
   \definedummyword\print
+  \definedummyword\quotedblbase
+  \definedummyword\quotedblleft
+  \definedummyword\quotedblright
+  \definedummyword\quoteleft
+  \definedummyword\quoteright
+  \definedummyword\quotesinglbase
   \definedummyword\result
   \definedummyword\textdegree
   %
@@ -3664,11 +4147,21 @@
   \def\equiv{==}%
   \def\error{error}%
   \def\euro{euro}%
+  \def\guillemetleft{<<}%
+  \def\guillemetright{>>}%
+  \def\guilsinglleft{<}%
+  \def\guilsinglright{>}%
   \def\expansion{==>}%
   \def\minus{-}%
   \def\pounds{pounds}%
   \def\point{.}%
   \def\print{-|}%
+  \def\quotedblbase{"}%
+  \def\quotedblleft{"}%
+  \def\quotedblright{"}%
+  \def\quoteleft{`}%
+  \def\quoteright{'}%
+  \def\quotesinglbase{,}%
   \def\result{=>}%
   \def\textdegree{degrees}%
   %
@@ -3710,11 +4203,7 @@
     %
     \edef\writeto{\csname#1indfile\endcsname}%
     %
-    \ifvmode
-      \dosubindsanitize
-    \else
-      \dosubindwrite
-    \fi
+    \safewhatsit\dosubindwrite
   }%
   \fi
 }
@@ -3751,13 +4240,13 @@
   \temp
 }
 
-% Take care of unwanted page breaks:
+% Take care of unwanted page breaks/skips around a whatsit:
 %
 % If a skip is the last thing on the list now, preserve it
 % by backing up by \lastskip, doing the \write, then inserting
 % the skip again.  Otherwise, the whatsit generated by the
-% \write will make \lastskip zero.  The result is that sequences
-% like this:
+% \write or \pdfdest will make \lastskip zero.  The result is that
+% sequences like this:
 % @end defun
 % @tindex whatever
 % @defun ...
@@ -3781,25 +4270,31 @@
 %
 \edef\zeroskipmacro{\expandafter\the\csname address@hidden
 %
+\newskip\whatsitskip
+\newcount\whatsitpenalty
+%
 % ..., ready, GO:
 %
-\def\dosubindsanitize{%
+\def\safewhatsit#1{%
+\ifhmode
+  #1%
+\else
   % \lastskip and \lastpenalty cannot both be nonzero simultaneously.
-  \skip0 = \lastskip
+  \whatsitskip = \lastskip
   \edef\lastskipmacro{\the\lastskip}%
-  \count255 = \lastpenalty
+  \whatsitpenalty = \lastpenalty
   %
   % If \lastskip is nonzero, that means the last item was a
   % skip.  And since a skip is discardable, that means this
-  % -\skip0 glue we're inserting is preceded by a
+  % -\whatsitskip glue we're inserting is preceded by a
   % non-discardable item, therefore it is not a potential
   % breakpoint, therefore no \nobreak needed.
   \ifx\lastskipmacro\zeroskipmacro
   \else
-    \vskip-\skip0
+    \vskip-\whatsitskip
   \fi
   %
-  \dosubindwrite
+  #1%
   %
   \ifx\lastskipmacro\zeroskipmacro
     % If \lastskip was zero, perhaps the last item was a penalty, and
@@ -3813,13 +4308,14 @@
     %   Description.
     % would allow a break between the index-whatever whatsit
     % and the "Description." paragraph.
-    \ifnum\count255>9999 \penalty\count255 \fi
+    \ifnum\whatsitpenalty>9999 \penalty\whatsitpenalty \fi
   \else
     % On the other hand, if we had a nonzero \lastskip,
     % this make-up glue would be preceded by a non-discardable item
     % (the whatsit from the \write), so we must insert a \nobreak.
-    \nobreak\vskip\skip0
+    \nobreak\vskip\whatsitskip
   \fi
+\fi
 }
 
 % The index entry written in the file actually looks like
@@ -3862,6 +4358,7 @@
   %
   \smallfonts \rm
   \tolerance = 9500
+  \plainfrenchspacing
   \everypar = {}% don't want the \kern\-parindent from indentation suppression.
   %
   % See if the index file exists and is nonempty.
@@ -3991,11 +4488,8 @@
     % The following is kludged to not output a line of dots in the index if
     % there are no page numbers.  The next person who breaks this will be
     % cursed by a Unix daemon.
-    \def\tempa{{\rm }}%
-    \def\tempb{#1}%
-    \edef\tempc{\tempa}%
-    \edef\tempd{\tempb}%
-    \ifx\tempc\tempd
+    \setbox\boxA = \hbox{#1}%
+    \ifdim\wd\boxA = 0pt
       \ %
     \else
       %
@@ -4131,6 +4625,34 @@
 %
 % All done with double columns.
 \def\enddoublecolumns{%
+  % The following penalty ensures that the page builder is exercised
+  % _before_ we change the output routine.  This is necessary in the
+  % following situation:
+  %
+  % The last section of the index consists only of a single entry.
+  % Before this section, \pagetotal is less than \pagegoal, so no
+  % break occurs before the last section starts.  However, the last
+  % section, consisting of \initial and the single \entry, does not
+  % fit on the page and has to be broken off.  Without the following
+  % penalty the page builder will not be exercised until \eject
+  % below, and by that time we'll already have changed the output
+  % routine to the \balancecolumns version, so the next-to-last
+  % double-column page will be processed with \balancecolumns, which
+  % is wrong:  The two columns will go to the main vertical list, with
+  % the broken-off section in the recent contributions.  As soon as
+  % the output routine finishes, TeX starts reconsidering the page
+  % break.  The two columns and the broken-off section both fit on the
+  % page, because the two columns now take up only half of the page
+  % goal.  When TeX sees \eject from below which follows the final
+  % section, it invokes the new output routine that we've set after
+  % \balancecolumns below; \onepageout will try to fit the two columns
+  % and the final section into the vbox of \pageheight (see
+  % \pagebody), causing an overfull box.
+  %
+  % Note that glue won't work here, because glue does not exercise the
+  % page builder, unlike penalties (see The TeXbook, pp. 280-281).
+  \penalty0
+  %
   \output = {%
     % Split the last of the double-column material.  Leave it on the
     % current page, no automatic page break.
@@ -4240,11 +4762,15 @@
   \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
   \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
 
-% Each @chapter defines this as the name of the chapter.
-% page headings and footings can use it.  @section does likewise.
-% However, they are not reliable, because we don't use marks.
+% Each @chapter defines these (using marks) as the number+name, number
+% and name of the chapter.  Page headings and footings can use
+% these.  @section does likewise.
 \def\thischapter{}
+\def\thischapternum{}
+\def\thischaptername{}
 \def\thissection{}
+\def\thissectionnum{}
+\def\thissectionname{}
 
 \newcount\absseclevel % used to calculate proper heading level
 \newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count
@@ -4545,7 +5071,20 @@
 
 \def\chapbreak{\dobreak \chapheadingskip {-4000}}
 \def\chappager{\par\vfill\supereject}
-\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+% Because \domark is called before \chapoddpage, the filler page will
+% get the headings for the next chapter, which is wrong.  But we don't
+% care -- we just disable all headings on the filler page.
+\def\chapoddpage{%
+  \chappager
+  \ifodd\pageno \else
+    \begingroup
+      \evenheadline={\hfil}\evenfootline={\hfil}%
+      \oddheadline={\hfil}\oddfootline={\hfil}%
+      \hbox to 0pt{}%
+      \chappager
+    \endgroup
+  \fi
+}
 
 \def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
 
@@ -4579,45 +5118,72 @@
 \def\Yappendixkeyword{Yappendix}
 %
 \def\chapmacro#1#2#3{%
+  % Insert the first mark before the heading break (see notes for \domark).
+  \let\prevchapterdefs=\lastchapterdefs
+  \let\prevsectiondefs=\lastsectiondefs
+  \gdef\lastsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}%
+                        \gdef\thissection{}}%
+  %
+  \def\temptype{#2}%
+  \ifx\temptype\Ynothingkeyword
+    \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}%
+                          \gdef\thischapter{\thischaptername}}%
+  \else\ifx\temptype\Yomitfromtockeyword
+    \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}%
+                          \gdef\thischapter{}}%
+  \else\ifx\temptype\Yappendixkeyword
+    \toks0={#1}%
+    \xdef\lastchapterdefs{%
+      \gdef\noexpand\thischaptername{\the\toks0}%
+      \gdef\noexpand\thischapternum{\appendixletter}%
+      \gdef\noexpand\thischapter{\putwordAppendix{} \noexpand\thischapternum:
+                                 \noexpand\thischaptername}%
+    }%
+  \else
+    \toks0={#1}%
+    \xdef\lastchapterdefs{%
+      \gdef\noexpand\thischaptername{\the\toks0}%
+      \gdef\noexpand\thischapternum{\the\chapno}%
+      \gdef\noexpand\thischapter{\putwordChapter{} \noexpand\thischapternum:
+                                 \noexpand\thischaptername}%
+    }%
+  \fi\fi\fi
+  %
+  % Output the mark.  Pass it through \safewhatsit, to take care of
+  % the preceding space.
+  \safewhatsit\domark
+  %
+  % Insert the chapter heading break.
   \pchapsepmacro
+  %
+  % Now the second mark, after the heading break.  No break points
+  % between here and the heading.
+  \let\prevchapterdefs=\lastchapterdefs
+  \let\prevsectiondefs=\lastsectiondefs
+  \domark
+  %
   {%
     \chapfonts \rm
     %
-    % Have to define \thissection before calling \donoderef, because the
+    % Have to define \lastsection before calling \donoderef, because the
     % xref code eventually uses it.  On the other hand, it has to be called
     % after \pchapsepmacro, or the headline will change too soon.
-    \gdef\thissection{#1}%
-    \gdef\thischaptername{#1}%
+    \gdef\lastsection{#1}%
     %
     % Only insert the separating space if we have a chapter/appendix
     % number, and don't print the unnumbered ``number''.
-    \def\temptype{#2}%
     \ifx\temptype\Ynothingkeyword
       \setbox0 = \hbox{}%
       \def\toctype{unnchap}%
-      \gdef\thischapternum{}%
-      \gdef\thischapter{#1}%
     \else\ifx\temptype\Yomitfromtockeyword
       \setbox0 = \hbox{}% contents like unnumbered, but no toc entry
       \def\toctype{omit}%
-      \gdef\thischapternum{}%
-      \gdef\thischapter{}%
     \else\ifx\temptype\Yappendixkeyword
       \setbox0 = \hbox{\putwordAppendix{} #3\enspace}%
       \def\toctype{app}%
-      \xdef\thischapternum{\appendixletter}%
-      % We don't substitute the actual chapter name into \thischapter
-      % because we don't want its macros evaluated now.  And we don't
-      % use \thissection because that changes with each section.
-      %
-      \xdef\thischapter{\putwordAppendix{} \appendixletter:
-                        \noexpand\thischaptername}%
     \else
       \setbox0 = \hbox{#3\enspace}%
       \def\toctype{numchap}%
-      \xdef\thischapternum{\the\chapno}%
-      \xdef\thischapter{\putwordChapter{} \the\chapno:
-                        \noexpand\thischaptername}%
     \fi\fi\fi
     %
     % Write the toc entry for this chapter.  Must come before the
@@ -4633,6 +5199,7 @@
     \donoderef{#2}%
     %
     % Typeset the actual heading.
+    \nobreak % Avoid page breaks at the interline glue.
     \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
           \hangindent=\wd0 \centerparametersmaybe
           \unhbox0 #1\par}%
@@ -4695,36 +5262,78 @@
 % the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the
 % section number.
 %
+\def\seckeyword{sec}
+%
 \def\sectionheading#1#2#3#4{%
   {%
     % Switch to the right set of fonts.
     \csname #2fonts\endcsname \rm
     %
+    \def\sectionlevel{#2}%
+    \def\temptype{#3}%
+    %
+    % Insert first mark before the heading break (see notes for \domark).
+    \let\prevsectiondefs=\lastsectiondefs
+    \ifx\temptype\Ynothingkeyword
+      \ifx\sectionlevel\seckeyword
+        \gdef\lastsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}%
+                              \gdef\thissection{\thissectionname}}%
+      \fi
+    \else\ifx\temptype\Yomitfromtockeyword
+      % Don't redefine \thissection.
+    \else\ifx\temptype\Yappendixkeyword
+      \ifx\sectionlevel\seckeyword
+        \toks0={#1}%
+        \xdef\lastsectiondefs{%
+          \gdef\noexpand\thissectionname{\the\toks0}%
+          \gdef\noexpand\thissectionnum{#4}%
+          \gdef\noexpand\thissection{\putwordSection{} 
\noexpand\thissectionnum:
+                                     \noexpand\thissectionname}%
+        }%
+      \fi
+    \else
+      \ifx\sectionlevel\seckeyword
+        \toks0={#1}%
+        \xdef\lastsectiondefs{%
+          \gdef\noexpand\thissectionname{\the\toks0}%
+          \gdef\noexpand\thissectionnum{#4}%
+          \gdef\noexpand\thissection{\putwordSection{} 
\noexpand\thissectionnum:
+                                     \noexpand\thissectionname}%
+        }%
+      \fi
+    \fi\fi\fi
+    %
+    % Output the mark.  Pass it through \safewhatsit, to take care of
+    % the preceding space.
+    \safewhatsit\domark
+    %
     % Insert space above the heading.
     \csname #2headingbreak\endcsname
     %
+    % Now the second mark, after the heading break.  No break points
+    % between here and the heading.
+    \let\prevsectiondefs=\lastsectiondefs
+    \domark
+    %
     % Only insert the space after the number if we have a section number.
-    \def\sectionlevel{#2}%
-    \def\temptype{#3}%
-    %
     \ifx\temptype\Ynothingkeyword
       \setbox0 = \hbox{}%
       \def\toctype{unn}%
-      \gdef\thissection{#1}%
+      \gdef\lastsection{#1}%
     \else\ifx\temptype\Yomitfromtockeyword
       % for @headings -- no section number, don't include in toc,
-      % and don't redefine \thissection.
+      % and don't redefine \lastsection.
       \setbox0 = \hbox{}%
       \def\toctype{omit}%
       \let\sectionlevel=\empty
     \else\ifx\temptype\Yappendixkeyword
       \setbox0 = \hbox{#4\enspace}%
       \def\toctype{app}%
-      \gdef\thissection{#1}%
+      \gdef\lastsection{#1}%
     \else
       \setbox0 = \hbox{#4\enspace}%
       \def\toctype{num}%
-      \gdef\thissection{#1}%
+      \gdef\lastsection{#1}%
     \fi\fi\fi
     %
     % Write the toc entry (before \donoderef).  See comments in \chapmacro.
@@ -4839,7 +5448,7 @@
 \def\readtocfile{%
   \setupdatafile
   \activecatcodes
-  \input \jobname.toc
+  \input \tocreadfilename
 }
 
 \newskip\contentsrightmargin \contentsrightmargin=1in
@@ -4858,7 +5467,6 @@
   %
   % Don't need to put `Contents' or `Short Contents' in the headline.
   % It is abundantly clear what they are.
-  \def\thischapter{}%
   \chapmacro{#1}{Yomitfromtoc}{}%
   %
   \savepageno = \pageno
@@ -4870,11 +5478,16 @@
     \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi
 }
 
+% redefined for the two-volume lispref.  We always output on
+% \jobname.toc even if this is redefined.
+% 
+\def\tocreadfilename{\jobname.toc}
 
 % Normal (long) toc.
+%
 \def\contents{%
   \startcontents{\putwordTOC}%
-    \openin 1 \jobname.toc
+    \openin 1 \tocreadfilename\space
     \ifeof 1 \else
       \readtocfile
     \fi
@@ -4912,7 +5525,7 @@
     \let\numsubsubsecentry = \numsecentry
     \let\appsubsubsecentry = \numsecentry
     \let\unnsubsubsecentry = \numsecentry
-    \openin 1 \jobname.toc
+    \openin 1 \tocreadfilename\space
     \ifeof 1 \else
       \readtocfile
     \fi
@@ -5247,12 +5860,18 @@
 \let\SETdispenvsize\relax
 \def\setnormaldispenv{%
   \ifx\SETdispenvsize\smallword
+    % end paragraph for sake of leading, in case document has no blank
+    % line.  This is redundant with what happens in \aboveenvbreak, but
+    % we need to do it before changing the fonts, and it's inconvenient
+    % to change the fonts afterward.
+    \ifnum \lastpenalty=10000 \else \endgraf \fi
     \smallexamplefonts \rm
   \fi
 }
 \def\setsmalldispenv{%
   \ifx\SETdispenvsize\nosmallword
   \else
+    \ifnum \lastpenalty=10000 \else \endgraf \fi
     \smallexamplefonts \rm
   \fi
 }
@@ -5419,11 +6038,11 @@
 % regular 0x27.  
 % 
 \def\codequoteright{%
-  \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax
-    '%
-  \else
-    \char'15
-  \fi
+  \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax
+    \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax
+      '%
+    \else \char'15 \fi
+  \else \char'15 \fi
 }
 %
 % and a similar option for the left quote char vs. a grave accent.
@@ -5431,11 +6050,11 @@
 % the code environments to do likewise.
 % 
 \def\codequoteleft{%
-  \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax
-    `%
-  \else
-    \char'22
-  \fi
+  \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax
+    \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax
+      `%
+    \else \char'22 \fi
+  \else \char'22 \fi
 }
 %
 \begingroup
@@ -5553,28 +6172,36 @@
   \endgroup
 }
 
+
 \message{defuns,}
 % @defun etc.
 
 \newskip\defbodyindent \defbodyindent=.4in
 \newskip\defargsindent \defargsindent=50pt
 \newskip\deflastargmargin \deflastargmargin=18pt
+\newcount\defunpenalty
 
 % Start the processing of @deffn:
 \def\startdefun{%
   \ifnum\lastpenalty<10000
     \medbreak
+    \defunpenalty=10003 % Will keep this @deffn together with the
+                        % following @def command, see below.
   \else
     % If there are two @def commands in a row, we'll have a \nobreak,
     % which is there to keep the function description together with its
     % header.  But if there's nothing but headers, we need to allow a
     % break somewhere.  Check specifically for penalty 10002, inserted
-    % by \defargscommonending, instead of 10000, since the sectioning
+    % by \printdefunline, instead of 10000, since the sectioning
     % commands also insert a nobreak penalty, and we don't want to allow
     % a break between a section heading and a defun.
-    % 
-    \ifnum\lastpenalty=10002 \penalty2000 \fi
     %
+    % As a minor refinement, we avoid "club" headers by signalling
+    % with penalty of 10003 after the very first @deffn in the
+    % sequence (see above), and penalty of 10002 after any following
+    % @def command.
+    \ifnum\lastpenalty=10002 \penalty2000 \else \defunpenalty=10002 \fi
+    %
     % Similarly, after a section heading, do not allow a break.
     % But do insert the glue.
     \medskip  % preceded by discardable penalty, so not a breakpoint
@@ -5591,7 +6218,7 @@
   %
   % As above, allow line break if we have multiple x headers in a row.
   % It's not a great place, though.
-  \ifnum\lastpenalty=10002 \penalty3000 \fi
+  \ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi
   %
   % And now, it's time to reuse the body of the original defun:
   \expandafter\gobbledefun#1%
@@ -5609,7 +6236,7 @@
     \advance\rightskip by 0pt plus 1fil
     \endgraf
     \nobreak\vskip -\parskip
-    \penalty 10002  % signal to \startdefun and \dodefunx
+    \penalty\defunpenalty  % signal to \startdefun and \dodefunx
     % Some of the @defun-type tags do not enable magic parentheses,
     % rendering the following check redundant.  But we don't optimize.
     \checkparencounts
@@ -5878,12 +6505,14 @@
   \ifnum\parencount=0 \else \badparencount \fi
   \ifnum\brackcount=0 \else \badbrackcount \fi
 }
+% these should not use \errmessage; the glibc manual, at least, actually
+% has such constructs (when documenting function pointers).
 \def\badparencount{%
-  \errmessage{Unbalanced parentheses in @def}%
+  \message{Warning: unbalanced parentheses in @def...}%
   \global\parencount=0
 }
 \def\badbrackcount{%
-  \errmessage{Unbalanced square braces in @def}%
+  \message{Warning: unbalanced square brackets in @def...}%
   \global\brackcount=0
 }
 
@@ -5978,6 +6607,10 @@
 % all characters are catcode 10, 11 or 12, except \ which is active
 % (as in normal texinfo). It is necessary to change the definition of \.
 
+% Non-ASCII encodings make 8-bit characters active, so un-activate
+% them to avoid their expansion.  Must do this non-globally, to
+% confine the change to the current group.
+
 % It's necessary to have hard CRs when the macro is executed. This is
 % done by  making ^^M (\endlinechar) catcode 12 when reading the macro
 % body, and then making it the \newlinechar in \scanmacro.
@@ -5992,6 +6625,7 @@
   \catcode`\_=\other
   \catcode`\|=\other
   \catcode`\~=\other
+  \ifx\declaredencoding\ascii \else \setnonasciicharscatcodenonglobal\other \fi
 }
 
 \def\scanargctxt{%
@@ -6209,7 +6843,6 @@
 \message{cross references,}
 
 \newwrite\auxfile
-
 \newif\ifhavexrefs    % True if xref values are known.
 \newif\ifwarnedxrefs  % True if we warned once that they aren't known.
 
@@ -6254,7 +6887,7 @@
 
 % \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an
 % anchor), which consists of three parts:
-% 1) NAME-title - the current sectioning name taken from \thissection,
+% 1) NAME-title - the current sectioning name taken from \lastsection,
 %                 or the anchor name.
 % 2) NAME-snt   - section number and type, passed as the SNT arg, or
 %                 empty for anchors.
@@ -6273,10 +6906,10 @@
        address@hidden #1 of \setref, expanded by the \edef
          ##1}{##2}}% these are parameters of \writexrdef
       }%
-      \toks0 = \expandafter{\thissection}%
+      \toks0 = \expandafter{\lastsection}%
       \immediate \writexrdef{title}{\the\toks0 }%
       \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc.
-      \writexrdef{pg}{\folio}% will be written later, during \shipout
+      \safewhatsit{\writexrdef{pg}{\folio}}% will be written later, during 
\shipout
     }%
   \fi
 }
@@ -6322,7 +6955,8 @@
   \ifpdf
     \leavevmode
     \getfilename{#4}%
-    {\turnoffactive
+    {\indexnofonts
+     \turnoffactive
      % See comments at \activebackslashdouble.
      {\activebackslashdouble \xdef\pdfxrefdest{#1}%
       \backslashparens\pdfxrefdest}%
@@ -6335,7 +6969,7 @@
          goto name{\pdfmkpgn{\pdfxrefdest}}%
      \fi
     }%
-    \linkcolor
+    \setcolor{\linkcolor}%
   \fi
   %
   % Float references are printed completely differently: "Figure 1.2"
@@ -6373,7 +7007,7 @@
     % is a loss.  Therefore, we give the text of the node name again, so it
     % is as if TeX is seeing it for the first time.
     \ifdim \wd1 > 0pt
-      \putwordsection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}%
+      \putwordSection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}%
     \else
       % _ (for example) has to be the character _ for the purposes of the
       % control sequence corresponding to the node, but it has to expand
@@ -6469,10 +7103,18 @@
 % collisions).  But if this is a float type, we have more work to do.
 %
 \def\xrdef#1#2{%
-  \expandafter\gdef\csname XR#1\endcsname{#2}% remember this xref value.
+  {% The node name might contain 8-bit characters, which in our current
+   % implementation are changed to commands like @'e.  Don't let these
+   % mess up the control sequence name.
+    \indexnofonts
+    \turnoffactive
+    \xdef\safexrefname{#1}%
+  }%
   %
+  \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% remember this xref
+  %
   % Was that xref control sequence that we just defined for a float?
-  \expandafter\iffloat\csname XR#1\endcsname
+  \expandafter\iffloat\csname XR\safexrefname\endcsname
     % it was a float, and we have the (safe) float type in \iffloattype.
     \expandafter\let\expandafter\floatlist
       \csname floatlist\iffloattype\endcsname
@@ -6487,7 +7129,8 @@
     %
     % Remember this xref in the control sequence \floatlistFLOATTYPE,
     % for later use in \listoffloats.
-    \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0{#1}}%
+    \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0
+      {\safexrefname}}%
   \fi
 }
 
@@ -6591,6 +7234,7 @@
   \input\jobname.#1
 \endgroup}
 
+
 \message{insertions,}
 % including footnotes.
 
@@ -6863,13 +7507,13 @@
       \global\advance\floatno by 1
       %
       {%
-        % This magic value for \thissection is output by \setref as the
+        % This magic value for \lastsection is output by \setref as the
         % XREFLABEL-title value.  \xrefX uses it to distinguish float
         % labels (which have a completely different output format) from
         % node and anchor labels.  And \xrdef uses it to construct the
         % lists of floats.
         %
-        \edef\thissection{\floatmagic=\safefloattype}%
+        \edef\lastsection{\floatmagic=\safefloattype}%
         \setref{\floatlabel}{Yfloat}%
       }%
     \fi
@@ -7004,7 +7648,7 @@
 
 % #1 is the control sequence we are passed; we expand into a conditional
 % which is true if #1 represents a float ref.  That is, the magic
-% \thissection value which we \setref above.
+% \lastsection value which we \setref above.
 %
 \def\iffloat#1{\expandafter\doiffloat#1==\finish}
 %
@@ -7065,39 +7709,871 @@
   \writeentry
 }}
 
+
 \message{localization,}
-% and i18n.
 
 % @documentlanguage is usually given very early, just after
 % @setfilename.  If done too late, it may not override everything
-% properly.  Single argument is the language abbreviation.
-% It would be nice if we could set up a hyphenation file here.
+% properly.  Single argument is the language (de) or locale (de_DE)
+% abbreviation.  It would be nice if we could set up a hyphenation file.
 %
-\parseargdef\documentlanguage{%
+{
+  \catcode`\_ = \active
+  \globaldefs=1
+\parseargdef\documentlanguage{\begingroup
+  \let_=\normalunderscore  % normal _ character for filenames
   \tex % read txi-??.tex file in plain TeX.
-    % Read the file if it exists.
+    % Read the file by the name they passed if it exists.
     \openin 1 txi-#1.tex
     \ifeof 1
-      \errhelp = \nolanghelp
-      \errmessage{Cannot read language file txi-#1.tex}%
+      \documentlanguagetrywithoutunderscore{#1_\finish}%
     \else
       \input txi-#1.tex
     \fi
     \closein 1
   \endgroup
+\endgroup}
 }
+%
+% If they passed de_DE, and txi-de_DE.tex doesn't exist,
+% try txi-de.tex.
+% 
+\def\documentlanguagetrywithoutunderscore#1_#2\finish{%
+  \openin 1 txi-#1.tex
+  \ifeof 1
+    \errhelp = \nolanghelp
+    \errmessage{Cannot read language file txi-#1.tex}%
+  \else
+    \input txi-#1.tex
+  \fi
+  \closein 1
+}
+%
 \newhelp\nolanghelp{The given language definition file cannot be found or
 is empty.  Maybe you need to install it?  In the current directory
 should work if nowhere else does.}
 
+% Set the catcode of characters 128 through 255 to the specified number.
+%
+\def\setnonasciicharscatcode#1{%
+   \count255=128
+   \loop\ifnum\count255<256
+      \global\catcode\count255=#1\relax
+      \advance\count255 by 1
+   \repeat
+}
 
-% @documentencoding should change something in TeX eventually, most
-% likely, but for now just recognize it.
-\let\documentencoding = \comment
+\def\setnonasciicharscatcodenonglobal#1{%
+   \count255=128
+   \loop\ifnum\count255<256
+      \catcode\count255=#1\relax
+      \advance\count255 by 1
+   \repeat
+}
 
+% @documentencoding sets the definition of non-ASCII characters
+% according to the specified encoding.
+%
+\parseargdef\documentencoding{%
+  % Encoding being declared for the document.
+  \def\declaredencoding{\csname #1.enc\endcsname}%
+  %
+  % Supported encodings: names converted to tokens in order to be able
+  % to compare them with \ifx.
+  \def\ascii{\csname US-ASCII.enc\endcsname}%
+  \def\latnine{\csname ISO-8859-15.enc\endcsname}%
+  \def\latone{\csname ISO-8859-1.enc\endcsname}%
+  \def\lattwo{\csname ISO-8859-2.enc\endcsname}%
+  \def\utfeight{\csname UTF-8.enc\endcsname}%
+  %
+  \ifx \declaredencoding \ascii
+     \asciichardefs
+  %
+  \else \ifx \declaredencoding \lattwo
+     \setnonasciicharscatcode\active
+     \lattwochardefs
+  %
+  \else \ifx \declaredencoding \latone 
+     \setnonasciicharscatcode\active
+     \latonechardefs
+  %
+  \else \ifx \declaredencoding \latnine
+     \setnonasciicharscatcode\active
+     \latninechardefs
+  %
+  \else \ifx \declaredencoding \utfeight
+     \setnonasciicharscatcode\active
+     \utfeightchardefs
+  %
+  \else 
+    \message{Unknown document encoding #1, ignoring.}%
+  %
+  \fi % utfeight
+  \fi % latnine
+  \fi % latone
+  \fi % lattwo
+  \fi % ascii
+}
 
-% Page size parameters.
+% A message to be logged when using a character that isn't available
+% the default font encoding (OT1).
+% 
+\def\missingcharmsg#1{\message{Character missing in OT1 encoding: #1.}}
+
+% Take account of \c (plain) vs. \, (Texinfo) difference.
+\def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi}
+
+% First, make active non-ASCII characters in order for them to be
+% correctly categorized when TeX reads the replacement text of
+% macros containing the character definitions.
+\setnonasciicharscatcode\active
 %
+% Latin1 (ISO-8859-1) character definitions.
+\def\latonechardefs{%
+  \gdef^^a0{~} 
+  \gdef^^a1{\exclamdown}
+  \gdef^^a2{\missingcharmsg{CENT SIGN}} 
+  \gdef^^a3{{\pounds}}
+  \gdef^^a4{\missingcharmsg{CURRENCY SIGN}}
+  \gdef^^a5{\missingcharmsg{YEN SIGN}}
+  \gdef^^a6{\missingcharmsg{BROKEN BAR}} 
+  \gdef^^a7{\S}
+  \gdef^^a8{\"{}} 
+  \gdef^^a9{\copyright} 
+  \gdef^^aa{\ordf}
+  \gdef^^ab{\missingcharmsg{LEFT-POINTING DOUBLE ANGLE QUOTATION MARK}} 
+  \gdef^^ac{$\lnot$}
+  \gdef^^ad{\-} 
+  \gdef^^ae{\registeredsymbol} 
+  \gdef^^af{\={}}
+  %
+  \gdef^^b0{\textdegree}
+  \gdef^^b1{$\pm$}
+  \gdef^^b2{$^2$}
+  \gdef^^b3{$^3$}
+  \gdef^^b4{\'{}}
+  \gdef^^b5{$\mu$}
+  \gdef^^b6{\P}
+  %
+  \gdef^^b7{$^.$}
+  \gdef^^b8{\cedilla\ }
+  \gdef^^b9{$^1$}
+  \gdef^^ba{\ordm}
+  %
+  \gdef^^bb{\missingcharmsg{RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK}}
+  \gdef^^bc{$1\over4$}
+  \gdef^^bd{$1\over2$}
+  \gdef^^be{$3\over4$}
+  \gdef^^bf{\questiondown}
+  %
+  \gdef^^c0{\`A}
+  \gdef^^c1{\'A}
+  \gdef^^c2{\^A}
+  \gdef^^c3{\~A}
+  \gdef^^c4{\"A}
+  \gdef^^c5{\ringaccent A} 
+  \gdef^^c6{\AE}
+  \gdef^^c7{\cedilla C}
+  \gdef^^c8{\`E}
+  \gdef^^c9{\'E}
+  \gdef^^ca{\^E}
+  \gdef^^cb{\"E}
+  \gdef^^cc{\`I}
+  \gdef^^cd{\'I}
+  \gdef^^ce{\^I}
+  \gdef^^cf{\"I}
+  %
+  \gdef^^d0{\missingcharmsg{LATIN CAPITAL LETTER ETH}}
+  \gdef^^d1{\~N}
+  \gdef^^d2{\`O}
+  \gdef^^d3{\'O}
+  \gdef^^d4{\^O}
+  \gdef^^d5{\~O}
+  \gdef^^d6{\"O}
+  \gdef^^d7{$\times$}
+  \gdef^^d8{\O}
+  \gdef^^d9{\`U}
+  \gdef^^da{\'U}
+  \gdef^^db{\^U}
+  \gdef^^dc{\"U}
+  \gdef^^dd{\'Y}
+  \gdef^^de{\missingcharmsg{LATIN CAPITAL LETTER THORN}}
+  \gdef^^df{\ss}
+  %
+  \gdef^^e0{\`a}
+  \gdef^^e1{\'a}
+  \gdef^^e2{\^a}
+  \gdef^^e3{\~a}
+  \gdef^^e4{\"a}
+  \gdef^^e5{\ringaccent a}
+  \gdef^^e6{\ae}
+  \gdef^^e7{\cedilla c}
+  \gdef^^e8{\`e}
+  \gdef^^e9{\'e}
+  \gdef^^ea{\^e}
+  \gdef^^eb{\"e}
+  \gdef^^ec{\`{\dotless i}}
+  \gdef^^ed{\'{\dotless i}}
+  \gdef^^ee{\^{\dotless i}}
+  \gdef^^ef{\"{\dotless i}}
+  %
+  \gdef^^f0{\missingcharmsg{LATIN SMALL LETTER ETH}}
+  \gdef^^f1{\~n}
+  \gdef^^f2{\`o}
+  \gdef^^f3{\'o}
+  \gdef^^f4{\^o}
+  \gdef^^f5{\~o}
+  \gdef^^f6{\"o}
+  \gdef^^f7{$\div$}
+  \gdef^^f8{\o}
+  \gdef^^f9{\`u}
+  \gdef^^fa{\'u}
+  \gdef^^fb{\^u}
+  \gdef^^fc{\"u}
+  \gdef^^fd{\'y}
+  \gdef^^fe{\missingcharmsg{LATIN SMALL LETTER THORN}}
+  \gdef^^ff{\"y}
+}
+
+% Latin9 (ISO-8859-15) encoding character definitions.
+\def\latninechardefs{%
+  % Encoding is almost identical to Latin1.
+  \latonechardefs
+  %
+  \gdef^^a4{\euro}
+  \gdef^^a6{\v S}
+  \gdef^^a8{\v s}
+  \gdef^^b4{\v Z}
+  \gdef^^b8{\v z}
+  \gdef^^bc{\OE}
+  \gdef^^bd{\oe}
+  \gdef^^be{\"Y}
+}
+
+% Latin2 (ISO-8859-2) character definitions.
+\def\lattwochardefs{%
+  \gdef^^a0{~}
+  \gdef^^a1{\missingcharmsg{LATIN CAPITAL LETTER A WITH OGONEK}}
+  \gdef^^a2{\u{}}
+  \gdef^^a3{\L}
+  \gdef^^a4{\missingcharmsg{CURRENCY SIGN}}
+  \gdef^^a5{\v L}
+  \gdef^^a6{\'S}
+  \gdef^^a7{\S}
+  \gdef^^a8{\"{}}
+  \gdef^^a9{\v S}
+  \gdef^^aa{\cedilla S}
+  \gdef^^ab{\v T}
+  \gdef^^ac{\'Z}
+  \gdef^^ad{\-}
+  \gdef^^ae{\v Z}
+  \gdef^^af{\dotaccent Z}
+  %
+  \gdef^^b0{\textdegree}
+  \gdef^^b1{\missingcharmsg{LATIN SMALL LETTER A WITH OGONEK}}
+  \gdef^^b2{\missingcharmsg{OGONEK}}
+  \gdef^^b3{\l}
+  \gdef^^b4{\'{}}
+  \gdef^^b5{\v l}
+  \gdef^^b6{\'s}
+  \gdef^^b7{\v{}}
+  \gdef^^b8{\cedilla\ }
+  \gdef^^b9{\v s}
+  \gdef^^ba{\cedilla s}
+  \gdef^^bb{\v t}
+  \gdef^^bc{\'z}
+  \gdef^^bd{\H{}}
+  \gdef^^be{\v z}
+  \gdef^^bf{\dotaccent z}
+  %
+  \gdef^^c0{\'R}
+  \gdef^^c1{\'A}
+  \gdef^^c2{\^A}
+  \gdef^^c3{\u A}
+  \gdef^^c4{\"A}
+  \gdef^^c5{\'L}
+  \gdef^^c6{\'C}
+  \gdef^^c7{\cedilla C}
+  \gdef^^c8{\v C}
+  \gdef^^c9{\'E}
+  \gdef^^ca{\missingcharmsg{LATIN CAPITAL LETTER E WITH OGONEK}}
+  \gdef^^cb{\"E}
+  \gdef^^cc{\v E}
+  \gdef^^cd{\'I}
+  \gdef^^ce{\^I}
+  \gdef^^cf{\v D}
+  %
+  \gdef^^d0{\missingcharmsg{LATIN CAPITAL LETTER D WITH STROKE}}
+  \gdef^^d1{\'N}
+  \gdef^^d2{\v N}
+  \gdef^^d3{\'O}
+  \gdef^^d4{\^O}
+  \gdef^^d5{\H O}
+  \gdef^^d6{\"O}
+  \gdef^^d7{$\times$}
+  \gdef^^d8{\v R}
+  \gdef^^d9{\ringaccent U} 
+  \gdef^^da{\'U}
+  \gdef^^db{\H U}
+  \gdef^^dc{\"U}
+  \gdef^^dd{\'Y}
+  \gdef^^de{\cedilla T}
+  \gdef^^df{\ss}
+  %
+  \gdef^^e0{\'r}
+  \gdef^^e1{\'a}
+  \gdef^^e2{\^a}
+  \gdef^^e3{\u a}
+  \gdef^^e4{\"a}
+  \gdef^^e5{\'l}
+  \gdef^^e6{\'c}
+  \gdef^^e7{\cedilla c}
+  \gdef^^e8{\v c}
+  \gdef^^e9{\'e}
+  \gdef^^ea{\missingcharmsg{LATIN SMALL LETTER E WITH OGONEK}}
+  \gdef^^eb{\"e}
+  \gdef^^ec{\v e}
+  \gdef^^ed{\'\i}
+  \gdef^^ee{\^\i}
+  \gdef^^ef{\v d}
+  %
+  \gdef^^f0{\missingcharmsg{LATIN SMALL LETTER D WITH STROKE}}
+  \gdef^^f1{\'n}
+  \gdef^^f2{\v n}
+  \gdef^^f3{\'o}
+  \gdef^^f4{\^o}
+  \gdef^^f5{\H o}
+  \gdef^^f6{\"o}
+  \gdef^^f7{$\div$}
+  \gdef^^f8{\v r}
+  \gdef^^f9{\ringaccent u}
+  \gdef^^fa{\'u}
+  \gdef^^fb{\H u}
+  \gdef^^fc{\"u}
+  \gdef^^fd{\'y}
+  \gdef^^fe{\cedilla t}
+  \gdef^^ff{\dotaccent{}}
+}
+
+% UTF-8 character definitions.
+% 
+% This code to support UTF-8 is based on LaTeX's utf8.def, with some
+% changes for Texinfo conventions.  It is included here under the GPL by
+% permission from Frank Mittelbach and the LaTeX team.
+% 
+\newcount\countUTFx
+\newcount\countUTFy
+\newcount\countUTFz
+
+\gdef\UTFviiiTwoOctets#1#2{\expandafter
+   \UTFviiiDefined\csname u8:#1\string #2\endcsname}
+%
+\gdef\UTFviiiThreeOctets#1#2#3{\expandafter
+   \UTFviiiDefined\csname u8:#1\string #2\string #3\endcsname}
+%
+\gdef\UTFviiiFourOctets#1#2#3#4{\expandafter
+   \UTFviiiDefined\csname u8:#1\string #2\string #3\string #4\endcsname}
+
+\gdef\UTFviiiDefined#1{%
+  \ifx #1\relax
+    \message{\linenumber Unicode char \string #1 not defined for Texinfo}%
+  \else
+    \expandafter #1%
+  \fi
+}
+
+\begingroup
+  \catcode`\~13
+  \catcode`\"12
+
+  \def\UTFviiiLoop{%
+    \global\catcode\countUTFx\active
+    \uccode`\~\countUTFx
+    \uppercase\expandafter{\UTFviiiTmp}%
+    \advance\countUTFx by 1
+    \ifnum\countUTFx < \countUTFy
+      \expandafter\UTFviiiLoop
+    \fi}
+
+  \countUTFx = "C2
+  \countUTFy = "E0
+  \def\UTFviiiTmp{%
+    \xdef~{\noexpand\UTFviiiTwoOctets\string~}}
+  \UTFviiiLoop
+
+  \countUTFx = "E0
+  \countUTFy = "F0
+  \def\UTFviiiTmp{%
+    \xdef~{\noexpand\UTFviiiThreeOctets\string~}}
+  \UTFviiiLoop
+
+  \countUTFx = "F0
+  \countUTFy = "F4
+  \def\UTFviiiTmp{%
+    \xdef~{\noexpand\UTFviiiFourOctets\string~}}
+  \UTFviiiLoop
+\endgroup
+
+\begingroup
+  \catcode`\"=12
+  \catcode`\<=12
+  \catcode`\.=12
+  \catcode`\,=12
+  \catcode`\;=12
+  \catcode`\!=12
+  \catcode`\~=13
+
+  \gdef\DeclareUnicodeCharacter#1#2{%
+    \countUTFz = "#1\relax
+    \wlog{\space\space defining Unicode char U+#1 (decimal \the\countUTFz)}%
+    \begingroup
+      \parseXMLCharref
+      \def\UTFviiiTwoOctets##1##2{%
+        \csname u8:##1\string ##2\endcsname}%
+      \def\UTFviiiThreeOctets##1##2##3{%
+        \csname u8:##1\string ##2\string ##3\endcsname}%
+      \def\UTFviiiFourOctets##1##2##3##4{%
+        \csname u8:##1\string ##2\string ##3\string ##4\endcsname}%
+      \expandafter\expandafter\expandafter\expandafter
+       \expandafter\expandafter\expandafter
+       \gdef\UTFviiiTmp{#2}%
+    \endgroup}
+
+  \gdef\parseXMLCharref{%
+    \ifnum\countUTFz < "A0\relax
+      \errhelp = \EMsimple
+      \errmessage{Cannot define Unicode char value < 00A0}%
+    \else\ifnum\countUTFz < "800\relax
+      \parseUTFviiiA,%
+      \parseUTFviiiB C\UTFviiiTwoOctets.,%
+    \else\ifnum\countUTFz < "10000\relax
+      \parseUTFviiiA;%
+      \parseUTFviiiA,%
+      \parseUTFviiiB E\UTFviiiThreeOctets.{,;}%
+    \else
+      \parseUTFviiiA;%
+      \parseUTFviiiA,%
+      \parseUTFviiiA!%
+      \parseUTFviiiB F\UTFviiiFourOctets.{!,;}%
+    \fi\fi\fi
+  }
+
+  \gdef\parseUTFviiiA#1{%
+    \countUTFx = \countUTFz
+    \divide\countUTFz by 64
+    \countUTFy = \countUTFz
+    \multiply\countUTFz by 64
+    \advance\countUTFx by -\countUTFz
+    \advance\countUTFx by 128
+    \uccode `#1\countUTFx
+    \countUTFz = \countUTFy}
+
+  \gdef\parseUTFviiiB#1#2#3#4{%
+    \advance\countUTFz by "#10\relax
+    \uccode `#3\countUTFz
+    \uppercase{\gdef\UTFviiiTmp{#2#3#4}}}
+\endgroup
+
+\def\utfeightchardefs{%
+  \DeclareUnicodeCharacter{00A0}{\tie}
+  \DeclareUnicodeCharacter{00A1}{\exclamdown}
+  \DeclareUnicodeCharacter{00A3}{\pounds}
+  \DeclareUnicodeCharacter{00A8}{\"{ }}
+  \DeclareUnicodeCharacter{00A9}{\copyright}
+  \DeclareUnicodeCharacter{00AA}{\ordf}
+  \DeclareUnicodeCharacter{00AB}{\guillemetleft}
+  \DeclareUnicodeCharacter{00AD}{\-}
+  \DeclareUnicodeCharacter{00AE}{\registeredsymbol}
+  \DeclareUnicodeCharacter{00AF}{\={ }}
+
+  \DeclareUnicodeCharacter{00B0}{\ringaccent{ }}
+  \DeclareUnicodeCharacter{00B4}{\'{ }}
+  \DeclareUnicodeCharacter{00B8}{\cedilla{ }}
+  \DeclareUnicodeCharacter{00BA}{\ordm}
+  \DeclareUnicodeCharacter{00BB}{\guillemetright}
+  \DeclareUnicodeCharacter{00BF}{\questiondown}
+
+  \DeclareUnicodeCharacter{00C0}{\`A}
+  \DeclareUnicodeCharacter{00C1}{\'A}
+  \DeclareUnicodeCharacter{00C2}{\^A}
+  \DeclareUnicodeCharacter{00C3}{\~A}
+  \DeclareUnicodeCharacter{00C4}{\"A}
+  \DeclareUnicodeCharacter{00C5}{\AA}
+  \DeclareUnicodeCharacter{00C6}{\AE}
+  \DeclareUnicodeCharacter{00C7}{\cedilla{C}}
+  \DeclareUnicodeCharacter{00C8}{\`E}
+  \DeclareUnicodeCharacter{00C9}{\'E}
+  \DeclareUnicodeCharacter{00CA}{\^E}
+  \DeclareUnicodeCharacter{00CB}{\"E}
+  \DeclareUnicodeCharacter{00CC}{\`I}
+  \DeclareUnicodeCharacter{00CD}{\'I}
+  \DeclareUnicodeCharacter{00CE}{\^I}
+  \DeclareUnicodeCharacter{00CF}{\"I}
+
+  \DeclareUnicodeCharacter{00D1}{\~N}
+  \DeclareUnicodeCharacter{00D2}{\`O}
+  \DeclareUnicodeCharacter{00D3}{\'O}
+  \DeclareUnicodeCharacter{00D4}{\^O}
+  \DeclareUnicodeCharacter{00D5}{\~O}
+  \DeclareUnicodeCharacter{00D6}{\"O}
+  \DeclareUnicodeCharacter{00D8}{\O}
+  \DeclareUnicodeCharacter{00D9}{\`U}
+  \DeclareUnicodeCharacter{00DA}{\'U}
+  \DeclareUnicodeCharacter{00DB}{\^U}
+  \DeclareUnicodeCharacter{00DC}{\"U}
+  \DeclareUnicodeCharacter{00DD}{\'Y}
+  \DeclareUnicodeCharacter{00DF}{\ss}
+
+  \DeclareUnicodeCharacter{00E0}{\`a}
+  \DeclareUnicodeCharacter{00E1}{\'a}
+  \DeclareUnicodeCharacter{00E2}{\^a}
+  \DeclareUnicodeCharacter{00E3}{\~a}
+  \DeclareUnicodeCharacter{00E4}{\"a}
+  \DeclareUnicodeCharacter{00E5}{\aa}
+  \DeclareUnicodeCharacter{00E6}{\ae}
+  \DeclareUnicodeCharacter{00E7}{\cedilla{c}}
+  \DeclareUnicodeCharacter{00E8}{\`e}
+  \DeclareUnicodeCharacter{00E9}{\'e}
+  \DeclareUnicodeCharacter{00EA}{\^e}
+  \DeclareUnicodeCharacter{00EB}{\"e}
+  \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}}
+  \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}}
+  \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}}
+  \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}}
+
+  \DeclareUnicodeCharacter{00F1}{\~n}
+  \DeclareUnicodeCharacter{00F2}{\`o}
+  \DeclareUnicodeCharacter{00F3}{\'o}
+  \DeclareUnicodeCharacter{00F4}{\^o}
+  \DeclareUnicodeCharacter{00F5}{\~o}
+  \DeclareUnicodeCharacter{00F6}{\"o}
+  \DeclareUnicodeCharacter{00F8}{\o}
+  \DeclareUnicodeCharacter{00F9}{\`u}
+  \DeclareUnicodeCharacter{00FA}{\'u}
+  \DeclareUnicodeCharacter{00FB}{\^u}
+  \DeclareUnicodeCharacter{00FC}{\"u}
+  \DeclareUnicodeCharacter{00FD}{\'y}
+  \DeclareUnicodeCharacter{00FF}{\"y}
+
+  \DeclareUnicodeCharacter{0100}{\=A}
+  \DeclareUnicodeCharacter{0101}{\=a}
+  \DeclareUnicodeCharacter{0102}{\u{A}}
+  \DeclareUnicodeCharacter{0103}{\u{a}}
+  \DeclareUnicodeCharacter{0106}{\'C}
+  \DeclareUnicodeCharacter{0107}{\'c}
+  \DeclareUnicodeCharacter{0108}{\^C}
+  \DeclareUnicodeCharacter{0109}{\^c}
+  \DeclareUnicodeCharacter{010A}{\dotaccent{C}}
+  \DeclareUnicodeCharacter{010B}{\dotaccent{c}}
+  \DeclareUnicodeCharacter{010C}{\v{C}}
+  \DeclareUnicodeCharacter{010D}{\v{c}}
+  \DeclareUnicodeCharacter{010E}{\v{D}}
+
+  \DeclareUnicodeCharacter{0112}{\=E}
+  \DeclareUnicodeCharacter{0113}{\=e}
+  \DeclareUnicodeCharacter{0114}{\u{E}}
+  \DeclareUnicodeCharacter{0115}{\u{e}}
+  \DeclareUnicodeCharacter{0116}{\dotaccent{E}}
+  \DeclareUnicodeCharacter{0117}{\dotaccent{e}}
+  \DeclareUnicodeCharacter{011A}{\v{E}}
+  \DeclareUnicodeCharacter{011B}{\v{e}}
+  \DeclareUnicodeCharacter{011C}{\^G}
+  \DeclareUnicodeCharacter{011D}{\^g}
+  \DeclareUnicodeCharacter{011E}{\u{G}}
+  \DeclareUnicodeCharacter{011F}{\u{g}}
+
+  \DeclareUnicodeCharacter{0120}{\dotaccent{G}}
+  \DeclareUnicodeCharacter{0121}{\dotaccent{g}}
+  \DeclareUnicodeCharacter{0124}{\^H}
+  \DeclareUnicodeCharacter{0125}{\^h}
+  \DeclareUnicodeCharacter{0128}{\~I}
+  \DeclareUnicodeCharacter{0129}{\~{\dotless{i}}}
+  \DeclareUnicodeCharacter{012A}{\=I}
+  \DeclareUnicodeCharacter{012B}{\={\dotless{i}}}
+  \DeclareUnicodeCharacter{012C}{\u{I}}
+  \DeclareUnicodeCharacter{012D}{\u{\dotless{i}}}
+
+  \DeclareUnicodeCharacter{0130}{\dotaccent{I}}
+  \DeclareUnicodeCharacter{0131}{\dotless{i}}
+  \DeclareUnicodeCharacter{0132}{IJ}
+  \DeclareUnicodeCharacter{0133}{ij}
+  \DeclareUnicodeCharacter{0134}{\^J}
+  \DeclareUnicodeCharacter{0135}{\^{\dotless{j}}}
+  \DeclareUnicodeCharacter{0139}{\'L}
+  \DeclareUnicodeCharacter{013A}{\'l}
+
+  \DeclareUnicodeCharacter{0141}{\L}
+  \DeclareUnicodeCharacter{0142}{\l}
+  \DeclareUnicodeCharacter{0143}{\'N}
+  \DeclareUnicodeCharacter{0144}{\'n}
+  \DeclareUnicodeCharacter{0147}{\v{N}}
+  \DeclareUnicodeCharacter{0148}{\v{n}}
+  \DeclareUnicodeCharacter{014C}{\=O}
+  \DeclareUnicodeCharacter{014D}{\=o}
+  \DeclareUnicodeCharacter{014E}{\u{O}}
+  \DeclareUnicodeCharacter{014F}{\u{o}}
+
+  \DeclareUnicodeCharacter{0150}{\H{O}}
+  \DeclareUnicodeCharacter{0151}{\H{o}}
+  \DeclareUnicodeCharacter{0152}{\OE}
+  \DeclareUnicodeCharacter{0153}{\oe}
+  \DeclareUnicodeCharacter{0154}{\'R}
+  \DeclareUnicodeCharacter{0155}{\'r}
+  \DeclareUnicodeCharacter{0158}{\v{R}}
+  \DeclareUnicodeCharacter{0159}{\v{r}}
+  \DeclareUnicodeCharacter{015A}{\'S}
+  \DeclareUnicodeCharacter{015B}{\'s}
+  \DeclareUnicodeCharacter{015C}{\^S}
+  \DeclareUnicodeCharacter{015D}{\^s}
+  \DeclareUnicodeCharacter{015E}{\cedilla{S}}
+  \DeclareUnicodeCharacter{015F}{\cedilla{s}}
+
+  \DeclareUnicodeCharacter{0160}{\v{S}}
+  \DeclareUnicodeCharacter{0161}{\v{s}}
+  \DeclareUnicodeCharacter{0162}{\cedilla{t}}
+  \DeclareUnicodeCharacter{0163}{\cedilla{T}}
+  \DeclareUnicodeCharacter{0164}{\v{T}}
+
+  \DeclareUnicodeCharacter{0168}{\~U}
+  \DeclareUnicodeCharacter{0169}{\~u}
+  \DeclareUnicodeCharacter{016A}{\=U}
+  \DeclareUnicodeCharacter{016B}{\=u}
+  \DeclareUnicodeCharacter{016C}{\u{U}}
+  \DeclareUnicodeCharacter{016D}{\u{u}}
+  \DeclareUnicodeCharacter{016E}{\ringaccent{U}}
+  \DeclareUnicodeCharacter{016F}{\ringaccent{u}}
+
+  \DeclareUnicodeCharacter{0170}{\H{U}}
+  \DeclareUnicodeCharacter{0171}{\H{u}}
+  \DeclareUnicodeCharacter{0174}{\^W}
+  \DeclareUnicodeCharacter{0175}{\^w}
+  \DeclareUnicodeCharacter{0176}{\^Y}
+  \DeclareUnicodeCharacter{0177}{\^y}
+  \DeclareUnicodeCharacter{0178}{\"Y}
+  \DeclareUnicodeCharacter{0179}{\'Z}
+  \DeclareUnicodeCharacter{017A}{\'z}
+  \DeclareUnicodeCharacter{017B}{\dotaccent{Z}}
+  \DeclareUnicodeCharacter{017C}{\dotaccent{z}}
+  \DeclareUnicodeCharacter{017D}{\v{Z}}
+  \DeclareUnicodeCharacter{017E}{\v{z}}
+
+  \DeclareUnicodeCharacter{01C4}{D\v{Z}}
+  \DeclareUnicodeCharacter{01C5}{D\v{z}}
+  \DeclareUnicodeCharacter{01C6}{d\v{z}}
+  \DeclareUnicodeCharacter{01C7}{LJ}
+  \DeclareUnicodeCharacter{01C8}{Lj}
+  \DeclareUnicodeCharacter{01C9}{lj}
+  \DeclareUnicodeCharacter{01CA}{NJ}
+  \DeclareUnicodeCharacter{01CB}{Nj}
+  \DeclareUnicodeCharacter{01CC}{nj}
+  \DeclareUnicodeCharacter{01CD}{\v{A}}
+  \DeclareUnicodeCharacter{01CE}{\v{a}}
+  \DeclareUnicodeCharacter{01CF}{\v{I}}
+
+  \DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}}
+  \DeclareUnicodeCharacter{01D1}{\v{O}}
+  \DeclareUnicodeCharacter{01D2}{\v{o}}
+  \DeclareUnicodeCharacter{01D3}{\v{U}}
+  \DeclareUnicodeCharacter{01D4}{\v{u}}
+
+  \DeclareUnicodeCharacter{01E2}{\={\AE}}
+  \DeclareUnicodeCharacter{01E3}{\={\ae}}
+  \DeclareUnicodeCharacter{01E6}{\v{G}}
+  \DeclareUnicodeCharacter{01E7}{\v{g}}
+  \DeclareUnicodeCharacter{01E8}{\v{K}}
+  \DeclareUnicodeCharacter{01E9}{\v{k}}
+
+  \DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}}
+  \DeclareUnicodeCharacter{01F1}{DZ}
+  \DeclareUnicodeCharacter{01F2}{Dz}
+  \DeclareUnicodeCharacter{01F3}{dz}
+  \DeclareUnicodeCharacter{01F4}{\'G}
+  \DeclareUnicodeCharacter{01F5}{\'g}
+  \DeclareUnicodeCharacter{01F8}{\`N}
+  \DeclareUnicodeCharacter{01F9}{\`n}
+  \DeclareUnicodeCharacter{01FC}{\'{\AE}}
+  \DeclareUnicodeCharacter{01FD}{\'{\ae}}
+  \DeclareUnicodeCharacter{01FE}{\'{\O}}
+  \DeclareUnicodeCharacter{01FF}{\'{\o}}
+
+  \DeclareUnicodeCharacter{021E}{\v{H}}
+  \DeclareUnicodeCharacter{021F}{\v{h}}
+
+  \DeclareUnicodeCharacter{0226}{\dotaccent{A}}
+  \DeclareUnicodeCharacter{0227}{\dotaccent{a}}
+  \DeclareUnicodeCharacter{0228}{\cedilla{E}}
+  \DeclareUnicodeCharacter{0229}{\cedilla{e}}
+  \DeclareUnicodeCharacter{022E}{\dotaccent{O}}
+  \DeclareUnicodeCharacter{022F}{\dotaccent{o}}
+
+  \DeclareUnicodeCharacter{0232}{\=Y}
+  \DeclareUnicodeCharacter{0233}{\=y}
+  \DeclareUnicodeCharacter{0237}{\dotless{j}}
+
+  \DeclareUnicodeCharacter{1E02}{\dotaccent{B}}
+  \DeclareUnicodeCharacter{1E03}{\dotaccent{b}}
+  \DeclareUnicodeCharacter{1E04}{\udotaccent{B}}
+  \DeclareUnicodeCharacter{1E05}{\udotaccent{b}}
+  \DeclareUnicodeCharacter{1E06}{\ubaraccent{B}}
+  \DeclareUnicodeCharacter{1E07}{\ubaraccent{b}}
+  \DeclareUnicodeCharacter{1E0A}{\dotaccent{D}}
+  \DeclareUnicodeCharacter{1E0B}{\dotaccent{d}}
+  \DeclareUnicodeCharacter{1E0C}{\udotaccent{D}}
+  \DeclareUnicodeCharacter{1E0D}{\udotaccent{d}}
+  \DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}}
+  \DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}}
+
+  \DeclareUnicodeCharacter{1E1E}{\dotaccent{F}}
+  \DeclareUnicodeCharacter{1E1F}{\dotaccent{f}}
+
+  \DeclareUnicodeCharacter{1E20}{\=G}
+  \DeclareUnicodeCharacter{1E21}{\=g}
+  \DeclareUnicodeCharacter{1E22}{\dotaccent{H}}
+  \DeclareUnicodeCharacter{1E23}{\dotaccent{h}}
+  \DeclareUnicodeCharacter{1E24}{\udotaccent{H}}
+  \DeclareUnicodeCharacter{1E25}{\udotaccent{h}}
+  \DeclareUnicodeCharacter{1E26}{\"H}
+  \DeclareUnicodeCharacter{1E27}{\"h}
+
+  \DeclareUnicodeCharacter{1E30}{\'K}
+  \DeclareUnicodeCharacter{1E31}{\'k}
+  \DeclareUnicodeCharacter{1E32}{\udotaccent{K}}
+  \DeclareUnicodeCharacter{1E33}{\udotaccent{k}}
+  \DeclareUnicodeCharacter{1E34}{\ubaraccent{K}}
+  \DeclareUnicodeCharacter{1E35}{\ubaraccent{k}}
+  \DeclareUnicodeCharacter{1E36}{\udotaccent{L}}
+  \DeclareUnicodeCharacter{1E37}{\udotaccent{l}}
+  \DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}}
+  \DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}}
+  \DeclareUnicodeCharacter{1E3E}{\'M}
+  \DeclareUnicodeCharacter{1E3F}{\'m}
+
+  \DeclareUnicodeCharacter{1E40}{\dotaccent{M}}
+  \DeclareUnicodeCharacter{1E41}{\dotaccent{m}}
+  \DeclareUnicodeCharacter{1E42}{\udotaccent{M}}
+  \DeclareUnicodeCharacter{1E43}{\udotaccent{m}}
+  \DeclareUnicodeCharacter{1E44}{\dotaccent{N}}
+  \DeclareUnicodeCharacter{1E45}{\dotaccent{n}}
+  \DeclareUnicodeCharacter{1E46}{\udotaccent{N}}
+  \DeclareUnicodeCharacter{1E47}{\udotaccent{n}}
+  \DeclareUnicodeCharacter{1E48}{\ubaraccent{N}}
+  \DeclareUnicodeCharacter{1E49}{\ubaraccent{n}}
+
+  \DeclareUnicodeCharacter{1E54}{\'P}
+  \DeclareUnicodeCharacter{1E55}{\'p}
+  \DeclareUnicodeCharacter{1E56}{\dotaccent{P}}
+  \DeclareUnicodeCharacter{1E57}{\dotaccent{p}}
+  \DeclareUnicodeCharacter{1E58}{\dotaccent{R}}
+  \DeclareUnicodeCharacter{1E59}{\dotaccent{r}}
+  \DeclareUnicodeCharacter{1E5A}{\udotaccent{R}}
+  \DeclareUnicodeCharacter{1E5B}{\udotaccent{r}}
+  \DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}}
+  \DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}}
+
+  \DeclareUnicodeCharacter{1E60}{\dotaccent{S}}
+  \DeclareUnicodeCharacter{1E61}{\dotaccent{s}}
+  \DeclareUnicodeCharacter{1E62}{\udotaccent{S}}
+  \DeclareUnicodeCharacter{1E63}{\udotaccent{s}}
+  \DeclareUnicodeCharacter{1E6A}{\dotaccent{T}}
+  \DeclareUnicodeCharacter{1E6B}{\dotaccent{t}}
+  \DeclareUnicodeCharacter{1E6C}{\udotaccent{T}}
+  \DeclareUnicodeCharacter{1E6D}{\udotaccent{t}}
+  \DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}}
+  \DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}}
+
+  \DeclareUnicodeCharacter{1E7C}{\~V}
+  \DeclareUnicodeCharacter{1E7D}{\~v}
+  \DeclareUnicodeCharacter{1E7E}{\udotaccent{V}}
+  \DeclareUnicodeCharacter{1E7F}{\udotaccent{v}}
+
+  \DeclareUnicodeCharacter{1E80}{\`W}
+  \DeclareUnicodeCharacter{1E81}{\`w}
+  \DeclareUnicodeCharacter{1E82}{\'W}
+  \DeclareUnicodeCharacter{1E83}{\'w}
+  \DeclareUnicodeCharacter{1E84}{\"W}
+  \DeclareUnicodeCharacter{1E85}{\"w}
+  \DeclareUnicodeCharacter{1E86}{\dotaccent{W}}
+  \DeclareUnicodeCharacter{1E87}{\dotaccent{w}}
+  \DeclareUnicodeCharacter{1E88}{\udotaccent{W}}
+  \DeclareUnicodeCharacter{1E89}{\udotaccent{w}}
+  \DeclareUnicodeCharacter{1E8A}{\dotaccent{X}}
+  \DeclareUnicodeCharacter{1E8B}{\dotaccent{x}}
+  \DeclareUnicodeCharacter{1E8C}{\"X}
+  \DeclareUnicodeCharacter{1E8D}{\"x}
+  \DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}}
+  \DeclareUnicodeCharacter{1E8F}{\dotaccent{y}}
+
+  \DeclareUnicodeCharacter{1E90}{\^Z}
+  \DeclareUnicodeCharacter{1E91}{\^z}
+  \DeclareUnicodeCharacter{1E92}{\udotaccent{Z}}
+  \DeclareUnicodeCharacter{1E93}{\udotaccent{z}}
+  \DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}}
+  \DeclareUnicodeCharacter{1E95}{\ubaraccent{z}}
+  \DeclareUnicodeCharacter{1E96}{\ubaraccent{h}}
+  \DeclareUnicodeCharacter{1E97}{\"t}
+  \DeclareUnicodeCharacter{1E98}{\ringaccent{w}}
+  \DeclareUnicodeCharacter{1E99}{\ringaccent{y}}
+
+  \DeclareUnicodeCharacter{1EA0}{\udotaccent{A}}
+  \DeclareUnicodeCharacter{1EA1}{\udotaccent{a}}
+
+  \DeclareUnicodeCharacter{1EB8}{\udotaccent{E}}
+  \DeclareUnicodeCharacter{1EB9}{\udotaccent{e}}
+  \DeclareUnicodeCharacter{1EBC}{\~E}
+  \DeclareUnicodeCharacter{1EBD}{\~e}
+
+  \DeclareUnicodeCharacter{1ECA}{\udotaccent{I}}
+  \DeclareUnicodeCharacter{1ECB}{\udotaccent{i}}
+  \DeclareUnicodeCharacter{1ECC}{\udotaccent{O}}
+  \DeclareUnicodeCharacter{1ECD}{\udotaccent{o}}
+
+  \DeclareUnicodeCharacter{1EE4}{\udotaccent{U}}
+  \DeclareUnicodeCharacter{1EE5}{\udotaccent{u}}
+
+  \DeclareUnicodeCharacter{1EF2}{\`Y}
+  \DeclareUnicodeCharacter{1EF3}{\`y}
+  \DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}}
+
+  \DeclareUnicodeCharacter{1EF8}{\~Y}
+  \DeclareUnicodeCharacter{1EF9}{\~y}
+
+  \DeclareUnicodeCharacter{2013}{--}
+  \DeclareUnicodeCharacter{2014}{---}
+  \DeclareUnicodeCharacter{2018}{\quoteleft}
+  \DeclareUnicodeCharacter{2019}{\quoteright}
+  \DeclareUnicodeCharacter{201A}{\quotesinglbase}
+  \DeclareUnicodeCharacter{201C}{\quotedblleft}
+  \DeclareUnicodeCharacter{201D}{\quotedblright}
+  \DeclareUnicodeCharacter{201E}{\quotedblbase}
+  \DeclareUnicodeCharacter{2022}{\bullet}
+  \DeclareUnicodeCharacter{2026}{\dots}
+  \DeclareUnicodeCharacter{2039}{\guilsinglleft}
+  \DeclareUnicodeCharacter{203A}{\guilsinglright}
+  \DeclareUnicodeCharacter{20AC}{\euro}
+
+  \DeclareUnicodeCharacter{2192}{\expansion}
+  \DeclareUnicodeCharacter{21D2}{\result}
+
+  \DeclareUnicodeCharacter{2212}{\minus}
+  \DeclareUnicodeCharacter{2217}{\point}
+  \DeclareUnicodeCharacter{2261}{\equiv}
+}% end of \utfeightchardefs
+
+
+% US-ASCII character definitions.
+\def\asciichardefs{% nothing need be done
+   \relax
+}
+
+% Make non-ASCII characters printable again for compatibility with
+% existing Texinfo documents that may use them, even without declaring a
+% document encoding.
+%
+\setnonasciicharscatcode \other
+
+
+\message{formatting,}
+
 \newdimen\defaultparindent \defaultparindent = 15pt
 
 \chapheadingskip = 15pt plus 4pt minus 2pt
@@ -7110,7 +8586,7 @@
 % Don't be so finicky about underfull hboxes, either.
 \hbadness = 2000
 
-% Following George Bush, just get rid of widows and orphans.
+% Following George Bush, get rid of widows and orphans.
 \widowpenalty=10000
 \clubpenalty=10000
 
@@ -7157,6 +8633,10 @@
   \ifpdf
     \pdfpageheight #7\relax
     \pdfpagewidth #8\relax
+    % if we don't reset these, they will remain at "1 true in" of
+    % whatever layout pdftex was dumped with.
+    \pdfhorigin = 1 true in
+    \pdfvorigin = 1 true in
   \fi
   %
   \setleading{\textleading}
@@ -7171,7 +8651,7 @@
   \textleading = 13.2pt
   %
   % If page is nothing but text, make it come out even.
-  \internalpagesizes{46\baselineskip}{6in}%
+  \internalpagesizes{607.2pt}{6in}% that's 46 lines
                     {\voffset}{.25in}%
                     {\bindingoffset}{36pt}%
                     {11in}{8.5in}%
@@ -7183,7 +8663,7 @@
   \textleading = 12pt
   %
   \internalpagesizes{7.5in}{5in}%
-                    {\voffset}{.25in}%
+                    {-.2in}{0in}%
                     {\bindingoffset}{16pt}%
                     {9.25in}{7in}%
   %
@@ -7227,7 +8707,7 @@
   % \global\normaloffset = -6mm
   % \global\bindingoffset = 10mm
   % @end tex
-  \internalpagesizes{51\baselineskip}{160mm}
+  \internalpagesizes{673.2pt}{160mm}% that's 51 lines
                     {\voffset}{\hoffset}%
                     {\bindingoffset}{44pt}%
                     {297mm}{210mm}%
@@ -7292,7 +8772,7 @@
   \parskip = 3pt plus 2pt minus 1pt
   \setleading{\textleading}%
   %
-  \dimen0 = #1
+  \dimen0 = #1\relax
   \advance\dimen0 by \voffset
   %
   \dimen2 = \hsize

Modified: libmicrohttpd/src/Makefile.am
===================================================================
--- libmicrohttpd/src/Makefile.am       2008-04-12 10:43:20 UTC (rev 6675)
+++ libmicrohttpd/src/Makefile.am       2008-04-12 20:45:58 UTC (rev 6676)
@@ -1 +1,9 @@
-SUBDIRS = include daemon . 
+if HAVE_CURL
+curltests = testcurl
+if HAVE_ZZUF
+if HAVE_SOCAT
+zzuftests = testzzuf
+endif
+endif
+endif
+SUBDIRS = include daemon examples $(curltests) $(zzuftests) . 

Modified: libmicrohttpd/src/daemon/Makefile.am
===================================================================
--- libmicrohttpd/src/daemon/Makefile.am        2008-04-12 10:43:20 UTC (rev 
6675)
+++ libmicrohttpd/src/daemon/Makefile.am        2008-04-12 20:45:58 UTC (rev 
6676)
@@ -23,42 +23,9 @@
   postprocessor.c \
   response.c response.h 
 
-# example programs
-
-noinst_PROGRAMS = minimal_example fileserver_example
-
-minimal_example_SOURCES = \
- minimal_example.c 
-minimal_example_LDADD = \
- $(top_builddir)/src/daemon/libmicrohttpd.la 
-
-fileserver_example_SOURCES = \
- fileserver_example.c 
-fileserver_example_LDADD = \
- $(top_builddir)/src/daemon/libmicrohttpd.la 
-
-
-# No curl, no testcases
-if HAVE_CURL
-
 check_PROGRAMS = \
-  postprocessor_test \
-  daemontest \
-  daemontest_get \
-  daemontest_post \
-  daemontest_postform \
-  daemontest_post_loop \
-  daemontest_put \
-  daemontest_large_put \
-  daemontest_get11 \
-  daemontest_post11 \
-  daemontest_postform11 \
-  daemontest_post_loop11 \
-  daemontest_put11 \
-  daemontest_large_put11 \
-  daemontest_long_header \
-  daemontest_get_chunked \
-  daemontest_put_chunked 
+  postprocessor_test 
+  daemontest 
 
 TESTS = $(check_PROGRAMS)
 
@@ -71,96 +38,3 @@
   postprocessor_test.c
 postprocessor_test_LDADD = \
   $(top_builddir)/src/daemon/libmicrohttpd.la 
-
-daemontest_get_SOURCES = \
-  daemontest_get.c
-daemontest_get_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-daemontest_get_chunked_SOURCES = \
-  daemontest_get_chunked.c
-daemontest_get_chunked_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-daemontest_post_SOURCES = \
-  daemontest_post.c
-daemontest_post_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-daemontest_postform_SOURCES = \
-  daemontest_postform.c
-daemontest_postform_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-daemontest_post_loop_SOURCES = \
-  daemontest_post_loop.c
-daemontest_post_loop_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-daemontest_put_SOURCES = \
-  daemontest_put.c
-daemontest_put_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-daemontest_put_chunked_SOURCES = \
-  daemontest_put_chunked.c
-daemontest_put_chunked_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-daemontest_get11_SOURCES = \
-  daemontest_get.c
-daemontest_get11_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-daemontest_post11_SOURCES = \
-  daemontest_post.c
-daemontest_post11_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-daemontest_postform11_SOURCES = \
-  daemontest_postform.c
-daemontest_postform11_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-daemontest_post_loop11_SOURCES = \
-  daemontest_post_loop.c
-daemontest_post_loop11_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-daemontest_put11_SOURCES = \
-  daemontest_put.c
-daemontest_put11_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-
-daemontest_large_put_SOURCES = \
-  daemontest_large_put.c
-daemontest_large_put_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-daemontest_large_put11_SOURCES = \
-  daemontest_large_put.c
-daemontest_large_put11_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-daemontest_long_header_SOURCES = \
-  daemontest_long_header.c
-daemontest_long_header_LDADD = \
-  $(top_builddir)/src/daemon/libmicrohttpd.la \
-  @LIBCURL@ 
-
-endif

Deleted: libmicrohttpd/src/daemon/daemontest.c
===================================================================
--- libmicrohttpd/src/daemon/daemontest.c       2008-04-12 10:43:20 UTC (rev 
6675)
+++ libmicrohttpd/src/daemon/daemontest.c       2008-04-12 20:45:58 UTC (rev 
6676)
@@ -1,163 +0,0 @@
-/*
-     This file is part of libmicrohttpd
-     (C) 2007 Christian Grothoff
-
-     libmicrohttpd is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
-     option) any later version.
-
-     libmicrohttpd is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with libmicrohttpd; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file daemontest.c
- * @brief  Testcase for libmicrohttpd starts and stops
- * @author Christian Grothoff
- */
-
-#include "config.h"
-#include "microhttpd.h"
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#endif
-
-
-static int
-testStartError ()
-{
-  struct MHD_Daemon *d;
-
-  d = MHD_start_daemon (MHD_USE_DEBUG, 0, NULL, NULL, NULL, NULL);
-  if (d != NULL)
-    return 1;
-  return 0;
-}
-
-static int
-apc_nothing (void *cls, const struct sockaddr *addr, socklen_t addrlen)
-{
-  return MHD_NO;
-}
-
-static int
-apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen)
-{
-  return MHD_YES;
-}
-
-static int
-ahc_nothing (void *cls,
-             struct MHD_Connection *connection,
-             const char *url,
-             const char *method,
-             const char *version,
-             const char *upload_data, unsigned int *upload_data_size,
-             void **unused)
-{
-  return MHD_NO;
-}
-
-static int
-testStartStop ()
-{
-  struct MHD_Daemon *d;
-
-  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
-                        1080,
-                        &apc_nothing,
-                        NULL, &ahc_nothing, NULL, MHD_OPTION_END);
-  if (d == NULL)
-    return 2;
-  MHD_stop_daemon (d);
-  return 0;
-}
-
-static int
-testExternalRun ()
-{
-  struct MHD_Daemon *d;
-  fd_set rs;
-  int maxfd;
-  int i;
-
-  d = MHD_start_daemon (MHD_USE_DEBUG,
-                        1081,
-                        &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
-
-  if (d == NULL)
-    return 4;
-  i = 0;
-  while (i < 15)
-    {
-      maxfd = 0;
-      FD_ZERO (&rs);
-      MHD_get_fdset (d, &rs, &rs, &rs, &maxfd);
-      if (MHD_run (d) == MHD_NO)
-        {
-          MHD_stop_daemon (d);
-          return 8;
-        }
-      i++;
-    }
-  MHD_stop_daemon (d);
-  return 0;
-}
-
-static int
-testThread ()
-{
-  struct MHD_Daemon *d;
-  d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY,
-                        1082,
-                        &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
-
-  if (d == NULL)
-    return 16;
-  if (MHD_run (d) != MHD_NO)
-    return 32;
-  MHD_stop_daemon (d);
-  return 0;
-}
-
-static int
-testMultithread ()
-{
-  struct MHD_Daemon *d;
-  d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION,
-                        1083,
-                        &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
-
-  if (d == NULL)
-    return 64;
-  if (MHD_run (d) != MHD_NO)
-    return 128;
-  MHD_stop_daemon (d);
-  return 0;
-}
-
-int
-main (int argc, char *const *argv)
-{
-  unsigned int errorCount = 0;
-  errorCount += testStartError ();
-  errorCount += testStartStop ();
-  errorCount += testExternalRun ();
-  errorCount += testThread ();
-  errorCount += testMultithread ();
-  if (errorCount != 0)
-    fprintf (stderr, "Error (code: %u)\n", errorCount);
-  return errorCount != 0;       /* 0 == pass */
-}

Deleted: libmicrohttpd/src/daemon/daemontest_get.c
===================================================================
--- libmicrohttpd/src/daemon/daemontest_get.c   2008-04-12 10:43:20 UTC (rev 
6675)
+++ libmicrohttpd/src/daemon/daemontest_get.c   2008-04-12 20:45:58 UTC (rev 
6676)
@@ -1,330 +0,0 @@
-/*
-     This file is part of libmicrohttpd
-     (C) 2007 Christian Grothoff
-
-     libmicrohttpd is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
-     option) any later version.
-
-     libmicrohttpd is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with libmicrohttpd; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file daemontest_get.c
- * @brief  Testcase for libmicrohttpd GET operations
- *         TODO: test parsing of query
- * @author Christian Grothoff
- */
-
-#include "config.h"
-#include <curl/curl.h>
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#endif
-
-static int oneone;
-
-struct CBC
-{
-  char *buf;
-  size_t pos;
-  size_t size;
-};
-
-static size_t
-copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
-{
-  struct CBC *cbc = ctx;
-
-  if (cbc->pos + size * nmemb > cbc->size)
-    return 0;                   /* overflow */
-  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
-  cbc->pos += size * nmemb;
-  return size * nmemb;
-}
-
-static int
-ahc_echo (void *cls,
-          struct MHD_Connection *connection,
-          const char *url,
-          const char *method,
-          const char *version,
-          const char *upload_data, unsigned int *upload_data_size,
-          void **unused)
-{
-  static int ptr;
-  const char *me = cls;
-  struct MHD_Response *response;
-  int ret;
-
-  if (0 != strcmp (me, method))
-    return MHD_NO;              /* unexpected method */
-  if (&ptr != *unused)
-    {
-      *unused = &ptr;
-      return MHD_YES;
-    }
-  *unused = NULL;
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
-  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
-  MHD_destroy_response (response);
-  if (ret == MHD_NO)
-    abort ();
-  return ret;
-}
-
-
-static int
-testInternalGet ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  CURLcode errornum;
-
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
-                        11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
-  if (d == NULL)
-    return 1;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11080/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  if (oneone)
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  else
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-  if (CURLE_OK != (errornum = curl_easy_perform (c)))
-    {
-      fprintf (stderr,
-               "curl_easy_perform failed: `%s'\n",
-               curl_easy_strerror (errornum));
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 2;
-    }
-  curl_easy_cleanup (c);
-  MHD_stop_daemon (d);
-  if (cbc.pos != strlen ("/hello_world"))
-    return 4;
-  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
-    return 8;
-  return 0;
-}
-
-static int
-testMultithreadedGet ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  CURLcode errornum;
-
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
-                        1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
-  if (d == NULL)
-    return 16;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  if (oneone)
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  else
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-  if (CURLE_OK != (errornum = curl_easy_perform (c)))
-    {
-      fprintf (stderr,
-               "curl_easy_perform failed: `%s'\n",
-               curl_easy_strerror (errornum));
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 32;
-    }
-  curl_easy_cleanup (c);
-  MHD_stop_daemon (d);
-  if (cbc.pos != strlen ("/hello_world"))
-    return 64;
-  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
-    return 128;
-  return 0;
-}
-
-
-static int
-testExternalGet ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  CURLM *multi;
-  CURLMcode mret;
-  fd_set rs;
-  fd_set ws;
-  fd_set es;
-  int max;
-  int running;
-  struct CURLMsg *msg;
-  time_t start;
-  struct timeval tv;
-
-  multi = NULL;
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_DEBUG,
-                        1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
-  if (d == NULL)
-    return 256;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  if (oneone)
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  else
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-
-
-  multi = curl_multi_init ();
-  if (multi == NULL)
-    {
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 512;
-    }
-  mret = curl_multi_add_handle (multi, c);
-  if (mret != CURLM_OK)
-    {
-      curl_multi_cleanup (multi);
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 1024;
-    }
-  start = time (NULL);
-  while ((time (NULL) - start < 5) && (multi != NULL))
-    {
-      max = 0;
-      FD_ZERO (&rs);
-      FD_ZERO (&ws);
-      FD_ZERO (&es);
-      curl_multi_perform (multi, &running);
-      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
-      if (mret != CURLM_OK)
-        {
-          curl_multi_remove_handle (multi, c);
-          curl_multi_cleanup (multi);
-          curl_easy_cleanup (c);
-          MHD_stop_daemon (d);
-          return 2048;
-        }
-      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
-        {
-          curl_multi_remove_handle (multi, c);
-          curl_multi_cleanup (multi);
-          curl_easy_cleanup (c);
-          MHD_stop_daemon (d);
-          return 4096;
-        }
-      tv.tv_sec = 0;
-      tv.tv_usec = 1000;
-      select (max + 1, &rs, &ws, &es, &tv);
-      curl_multi_perform (multi, &running);
-      if (running == 0)
-        {
-          msg = curl_multi_info_read (multi, &running);
-          if (msg == NULL)
-            break;
-          if (msg->msg == CURLMSG_DONE)
-            {
-              if (msg->data.result != CURLE_OK)
-                printf ("%s failed at %s:%d: `%s'\n",
-                        "curl_multi_perform",
-                        __FILE__,
-                        __LINE__, curl_easy_strerror (msg->data.result));
-              curl_multi_remove_handle (multi, c);
-              curl_multi_cleanup (multi);
-              curl_easy_cleanup (c);
-              c = NULL;
-              multi = NULL;
-            }
-        }
-      MHD_run (d);
-    }
-  if (multi != NULL)
-    {
-      curl_multi_remove_handle (multi, c);
-      curl_easy_cleanup (c);
-      curl_multi_cleanup (multi);
-    }
-  MHD_stop_daemon (d);
-  if (cbc.pos != strlen ("/hello_world"))
-    return 8192;
-  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
-    return 16384;
-  return 0;
-}
-
-
-
-int
-main (int argc, char *const *argv)
-{
-  unsigned int errorCount = 0;
-
-  oneone = NULL != strstr (argv[0], "11");
-  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
-    return 2;
-  errorCount += testInternalGet ();
-  errorCount += testMultithreadedGet ();
-  errorCount += testExternalGet ();
-  if (errorCount != 0)
-    fprintf (stderr, "Error (code: %u)\n", errorCount);
-  curl_global_cleanup ();
-  return errorCount != 0;       /* 0 == pass */
-}

Deleted: libmicrohttpd/src/daemon/daemontest_get_chunked.c
===================================================================
--- libmicrohttpd/src/daemon/daemontest_get_chunked.c   2008-04-12 10:43:20 UTC 
(rev 6675)
+++ libmicrohttpd/src/daemon/daemontest_get_chunked.c   2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -1,364 +0,0 @@
-/*
-     This file is part of libmicrohttpd
-     (C) 2007 Christian Grothoff
-
-     libmicrohttpd is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
-     option) any later version.
-
-     libmicrohttpd is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with libmicrohttpd; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file daemontest_get_chunked.c
- * @brief  Testcase for libmicrohttpd GET operations with chunked content 
encoding
- *         TODO:
- *         - how to test that chunking was actually used?
- *         - use CURLOPT_HEADERFUNCTION to validate
- *           footer was sent
- * @author Christian Grothoff
- */
-
-#include "config.h"
-#include <curl/curl.h>
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#endif
-
-struct CBC
-{
-  char *buf;
-  size_t pos;
-  size_t size;
-};
-
-static size_t
-copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
-{
-  struct CBC *cbc = ctx;
-
-  if (cbc->pos + size * nmemb > cbc->size)
-    return 0;                   /* overflow */
-  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
-  cbc->pos += size * nmemb;
-  return size * nmemb;
-}
-
-/**
- * MHD content reader callback that returns
- * data in chunks.
- */
-static int
-crc (void *cls, size_t pos, char *buf, int max)
-{
-  struct MHD_Response **responseptr = cls;
-
-  if (pos == 128 * 10)
-    {
-      MHD_add_response_header (*responseptr, "Footer", "working");
-      return -1;                /* end of stream */
-    }
-  if (max < 128)
-    abort ();                   /* should not happen in this testcase... */
-  memset (buf, 'A' + (pos / 128), 128);
-  return 128;
-}
-
-/**
- * Dummy function that does nothing.
- */
-static void
-crcf (void *ptr)
-{
-  free (ptr);
-}
-
-static int
-ahc_echo (void *cls,
-          struct MHD_Connection *connection,
-          const char *url,
-          const char *method,
-          const char *version,
-          const char *upload_data, unsigned int *upload_data_size, void **ptr)
-{
-  static int aptr;
-  const char *me = cls;
-  struct MHD_Response *response;
-  struct MHD_Response **responseptr;
-  int ret;
-
-  if (0 != strcmp (me, method))
-    return MHD_NO;              /* unexpected method */
-  if (&aptr != *ptr)
-    {
-      /* do never respond on first call */
-      *ptr = &aptr;
-      return MHD_YES;
-    }
-  responseptr = malloc (sizeof (struct MHD_Response *));
-  response = MHD_create_response_from_callback (-1,
-                                                1024,
-                                                &crc, responseptr, &crcf);
-  *responseptr = response;
-  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
-  MHD_destroy_response (response);
-  return ret;
-}
-
-static int
-validate (struct CBC cbc, int ebase)
-{
-  int i;
-  char buf[128];
-
-  if (cbc.pos != 128 * 10)
-    return ebase;
-
-  for (i = 0; i < 10; i++)
-    {
-      memset (buf, 'A' + i, 128);
-      if (0 != memcmp (buf, &cbc.buf[i * 128], 128))
-        {
-          fprintf (stderr,
-                   "Got  `%.*s'\nWant `%.*s'\n",
-                   128, buf, 128, &cbc.buf[i * 128]);
-          return ebase * 2;
-        }
-    }
-  return 0;
-}
-
-static int
-testInternalGet ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  CURLcode errornum;
-
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
-                        1080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
-  if (d == NULL)
-    return 1;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-  if (CURLE_OK != (errornum = curl_easy_perform (c)))
-    {
-      fprintf (stderr,
-               "curl_easy_perform failed: `%s'\n",
-               curl_easy_strerror (errornum));
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 2;
-    }
-  curl_easy_cleanup (c);
-  MHD_stop_daemon (d);
-  return validate (cbc, 4);
-}
-
-static int
-testMultithreadedGet ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  CURLcode errornum;
-
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
-                        1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
-  if (d == NULL)
-    return 16;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-  if (CURLE_OK != (errornum = curl_easy_perform (c)))
-    {
-      fprintf (stderr,
-               "curl_easy_perform failed: `%s'\n",
-               curl_easy_strerror (errornum));
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 32;
-    }
-  curl_easy_cleanup (c);
-  MHD_stop_daemon (d);
-  return validate (cbc, 64);
-}
-
-
-static int
-testExternalGet ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  CURLM *multi;
-  CURLMcode mret;
-  fd_set rs;
-  fd_set ws;
-  fd_set es;
-  int max;
-  int running;
-  struct CURLMsg *msg;
-  time_t start;
-  struct timeval tv;
-
-  multi = NULL;
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_DEBUG,
-                        1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
-  if (d == NULL)
-    return 256;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 5L);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-
-
-  multi = curl_multi_init ();
-  if (multi == NULL)
-    {
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 512;
-    }
-  mret = curl_multi_add_handle (multi, c);
-  if (mret != CURLM_OK)
-    {
-      curl_multi_cleanup (multi);
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 1024;
-    }
-  start = time (NULL);
-  while ((time (NULL) - start < 5) && (multi != NULL))
-    {
-      max = 0;
-      FD_ZERO (&rs);
-      FD_ZERO (&ws);
-      FD_ZERO (&es);
-      curl_multi_perform (multi, &running);
-      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
-      if (mret != CURLM_OK)
-        {
-          curl_multi_remove_handle (multi, c);
-          curl_multi_cleanup (multi);
-          curl_easy_cleanup (c);
-          MHD_stop_daemon (d);
-          return 2048;
-        }
-      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
-        {
-          curl_multi_remove_handle (multi, c);
-          curl_multi_cleanup (multi);
-          curl_easy_cleanup (c);
-          MHD_stop_daemon (d);
-          return 4096;
-        }
-      tv.tv_sec = 0;
-      tv.tv_usec = 1000;
-      select (max + 1, &rs, &ws, &es, &tv);
-      curl_multi_perform (multi, &running);
-      if (running == 0)
-        {
-          msg = curl_multi_info_read (multi, &running);
-          if (msg == NULL)
-            break;
-          if (msg->msg == CURLMSG_DONE)
-            {
-              if (msg->data.result != CURLE_OK)
-                printf ("%s failed at %s:%d: `%s'\n",
-                        "curl_multi_perform",
-                        __FILE__,
-                        __LINE__, curl_easy_strerror (msg->data.result));
-              curl_multi_remove_handle (multi, c);
-              curl_multi_cleanup (multi);
-              curl_easy_cleanup (c);
-              c = NULL;
-              multi = NULL;
-            }
-        }
-      MHD_run (d);
-    }
-  if (multi != NULL)
-    {
-      curl_multi_remove_handle (multi, c);
-      curl_easy_cleanup (c);
-      curl_multi_cleanup (multi);
-    }
-  MHD_stop_daemon (d);
-  return validate (cbc, 8192);
-}
-
-
-
-int
-main (int argc, char *const *argv)
-{
-  unsigned int errorCount = 0;
-
-  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
-    return 2;
-  errorCount += testInternalGet ();
-  if (0)
-    {
-      errorCount += testMultithreadedGet ();
-      errorCount += testExternalGet ();
-    }
-  if (errorCount != 0)
-    fprintf (stderr, "Error (code: %u)\n", errorCount);
-  curl_global_cleanup ();
-  return errorCount != 0;       /* 0 == pass */
-}

Deleted: libmicrohttpd/src/daemon/daemontest_large_put.c
===================================================================
--- libmicrohttpd/src/daemon/daemontest_large_put.c     2008-04-12 10:43:20 UTC 
(rev 6675)
+++ libmicrohttpd/src/daemon/daemontest_large_put.c     2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -1,404 +0,0 @@
-/*
-     This file is part of libmicrohttpd
-     (C) 2007 Christian Grothoff
-
-     libmicrohttpd is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
-     option) any later version.
-
-     libmicrohttpd is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with libmicrohttpd; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file daemontest_put.c
- * @brief  Testcase for libmicrohttpd PUT operations
- * @author Christian Grothoff
- */
-
-#include "config.h"
-#include <curl/curl.h>
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#endif
-
-static int oneone;
-
-/**
- * Do not make this much larger since we will hit the
- * MHD default buffer limit and the test code is not
- * written for incremental upload processing...
- */
-#define PUT_SIZE (512 * 1024)
-
-static char *put_buffer;
-
-struct CBC
-{
-  char *buf;
-  size_t pos;
-  size_t size;
-};
-
-static size_t
-putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
-{
-  unsigned int *pos = ptr;
-  unsigned int wrt;
-
-  wrt = size * nmemb;
-  if (wrt > PUT_SIZE - (*pos))
-    wrt = PUT_SIZE - (*pos);
-  memcpy (stream, &put_buffer[*pos], wrt);
-  (*pos) += wrt;
-  return wrt;
-}
-
-static size_t
-copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
-{
-  struct CBC *cbc = ctx;
-
-  if (cbc->pos + size * nmemb > cbc->size)
-    return 0;                   /* overflow */
-  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
-  cbc->pos += size * nmemb;
-  return size * nmemb;
-}
-
-static int
-ahc_echo (void *cls,
-          struct MHD_Connection *connection,
-          const char *url,
-          const char *method,
-          const char *version,
-          const char *upload_data, unsigned int *upload_data_size,
-          void **unused)
-{
-  int *done = cls;
-  struct MHD_Response *response;
-  int ret;
-
-  if (0 != strcmp ("PUT", method))
-    return MHD_NO;              /* unexpected method */
-  if ((*done) == 0)
-    {
-      if (*upload_data_size != PUT_SIZE)
-        {
-#if 0
-          fprintf (stderr,
-                   "Waiting for more data (%u/%u)...\n",
-                   *upload_data_size, PUT_SIZE);
-#endif
-          return MHD_YES;       /* not yet ready */
-        }
-      if (0 == memcmp (upload_data, put_buffer, PUT_SIZE))
-        {
-          *upload_data_size = 0;
-        }
-      else
-        {
-          printf ("Invalid upload data!\n");
-          return MHD_NO;
-        }
-      *done = 1;
-      return MHD_YES;
-    }
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
-  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
-  MHD_destroy_response (response);
-  return ret;
-}
-
-
-static int
-testInternalPut ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  struct CBC cbc;
-  unsigned int pos = 0;
-  int done_flag = 0;
-  CURLcode errornum;
-  char buf[2048];
-
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
-                        1080,
-                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
-  if (d == NULL)
-    return 1;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
-  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
-  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
-  curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  if (oneone)
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  else
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-  if (CURLE_OK != (errornum = curl_easy_perform (c)))
-    {
-      fprintf (stderr,
-               "curl_easy_perform failed: `%s'\n",
-               curl_easy_strerror (errornum));
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 2;
-    }
-  curl_easy_cleanup (c);
-  MHD_stop_daemon (d);
-  if (cbc.pos != strlen ("/hello_world"))
-    return 4;
-  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
-    return 8;
-  return 0;
-}
-
-static int
-testMultithreadedPut ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  struct CBC cbc;
-  unsigned int pos = 0;
-  int done_flag = 0;
-  CURLcode errornum;
-  char buf[2048];
-
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
-                        1081,
-                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
-  if (d == NULL)
-    {
-      free (cbc.buf);
-      return 16;
-    }
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
-  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
-  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
-  curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  if (oneone)
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  else
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-  if (CURLE_OK != (errornum = curl_easy_perform (c)))
-    {
-      fprintf (stderr,
-               "curl_easy_perform failed: `%s'\n",
-               curl_easy_strerror (errornum));
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 32;
-    }
-  curl_easy_cleanup (c);
-  MHD_stop_daemon (d);
-  if (cbc.pos != strlen ("/hello_world"))
-    {
-      fprintf (stderr, "Got invalid response `%.*s'\n", cbc.pos, cbc.buf);
-      return 64;
-    }
-  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
-    return 128;
-  return 0;
-}
-
-
-static int
-testExternalPut ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  struct CBC cbc;
-  CURLM *multi;
-  CURLMcode mret;
-  fd_set rs;
-  fd_set ws;
-  fd_set es;
-  int max;
-  int running;
-  struct CURLMsg *msg;
-  time_t start;
-  struct timeval tv;
-  unsigned int pos = 0;
-  int done_flag = 0;
-  char buf[2048];
-
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  multi = NULL;
-  d = MHD_start_daemon (MHD_USE_DEBUG,
-                        1082,
-                        NULL, NULL, &ahc_echo, &done_flag,
-                        MHD_OPTION_CONNECTION_MEMORY_LIMIT,
-                        PUT_SIZE * 4, MHD_OPTION_END);
-  if (d == NULL)
-    return 256;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
-  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
-  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
-  curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  if (oneone)
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  else
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-
-
-  multi = curl_multi_init ();
-  if (multi == NULL)
-    {
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 512;
-    }
-  mret = curl_multi_add_handle (multi, c);
-  if (mret != CURLM_OK)
-    {
-      curl_multi_cleanup (multi);
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 1024;
-    }
-  start = time (NULL);
-  while ((time (NULL) - start < 5) && (multi != NULL))
-    {
-      max = 0;
-      FD_ZERO (&rs);
-      FD_ZERO (&ws);
-      FD_ZERO (&es);
-      curl_multi_perform (multi, &running);
-      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
-      if (mret != CURLM_OK)
-        {
-          curl_multi_remove_handle (multi, c);
-          curl_multi_cleanup (multi);
-          curl_easy_cleanup (c);
-          MHD_stop_daemon (d);
-          return 2048;
-        }
-      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
-        {
-          curl_multi_remove_handle (multi, c);
-          curl_multi_cleanup (multi);
-          curl_easy_cleanup (c);
-          MHD_stop_daemon (d);
-          return 4096;
-        }
-      tv.tv_sec = 0;
-      tv.tv_usec = 1000;
-      select (max + 1, &rs, &ws, &es, &tv);
-      curl_multi_perform (multi, &running);
-      if (running == 0)
-        {
-          msg = curl_multi_info_read (multi, &running);
-          if (msg == NULL)
-            break;
-          if (msg->msg == CURLMSG_DONE)
-            {
-              if (msg->data.result != CURLE_OK)
-                printf ("%s failed at %s:%d: `%s'\n",
-                        "curl_multi_perform",
-                        __FILE__,
-                        __LINE__, curl_easy_strerror (msg->data.result));
-              curl_multi_remove_handle (multi, c);
-              curl_multi_cleanup (multi);
-              curl_easy_cleanup (c);
-              c = NULL;
-              multi = NULL;
-            }
-        }
-      MHD_run (d);
-    }
-  if (multi != NULL)
-    {
-      curl_multi_remove_handle (multi, c);
-      curl_easy_cleanup (c);
-      curl_multi_cleanup (multi);
-    }
-  MHD_stop_daemon (d);
-  if (cbc.pos != strlen ("/hello_world"))
-    {
-      fprintf (stderr, "Got invalid response `%.*s'\n", cbc.pos, cbc.buf);
-      return 8192;
-    }
-  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
-    return 16384;
-  return 0;
-}
-
-
-
-int
-main (int argc, char *const *argv)
-{
-  unsigned int errorCount = 0;
-
-  oneone = NULL != strstr (argv[0], "11");
-  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
-    return 2;
-  put_buffer = malloc (PUT_SIZE);
-  memset (put_buffer, 1, PUT_SIZE);
-  if (0)
-    {
-      errorCount += testInternalPut ();
-      errorCount += testMultithreadedPut ();
-    }
-  errorCount += testExternalPut ();
-  free (put_buffer);
-  if (errorCount != 0)
-    fprintf (stderr, "Error (code: %u)\n", errorCount);
-  curl_global_cleanup ();
-  return errorCount != 0;       /* 0 == pass */
-}

Deleted: libmicrohttpd/src/daemon/daemontest_long_header.c
===================================================================
--- libmicrohttpd/src/daemon/daemontest_long_header.c   2008-04-12 10:43:20 UTC 
(rev 6675)
+++ libmicrohttpd/src/daemon/daemontest_long_header.c   2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -1,240 +0,0 @@
-/*
-     This file is part of libmicrohttpd
-     (C) 2007 Christian Grothoff
-
-     libmicrohttpd is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
-     option) any later version.
-
-     libmicrohttpd is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with libmicrohttpd; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file daemontest_long_header.c
- * @brief  Testcase for libmicrohttpd handling of very long headers
- * @author Christian Grothoff
- */
-
-#include "config.h"
-#include <curl/curl.h>
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#endif
-
-/**
- * We will set the memory available per connection to
- * half of this value, so the actual value does not have
- * to be big at all...
- */
-#define VERY_LONG (1024*10)
-
-static int oneone;
-
-static int
-apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen)
-{
-  return MHD_YES;
-}
-
-struct CBC
-{
-  char *buf;
-  size_t pos;
-  size_t size;
-};
-
-static size_t
-copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
-{
-  return size * nmemb;
-}
-
-static int
-ahc_echo (void *cls,
-          struct MHD_Connection *connection,
-          const char *url,
-          const char *method,
-          const char *version,
-          const char *upload_data, unsigned int *upload_data_size,
-          void **unused)
-{
-  const char *me = cls;
-  struct MHD_Response *response;
-  int ret;
-
-  if (0 != strcmp (me, method))
-    return MHD_NO;              /* unexpected method */
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
-  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
-  MHD_destroy_response (response);
-  return ret;
-}
-
-
-static int
-testLongUrlGet ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  char *url;
-  long code;
-
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
-                        1080,
-                        &apc_all,
-                        NULL,
-                        &ahc_echo,
-                        "GET",
-                        MHD_OPTION_CONNECTION_MEMORY_LIMIT,
-                        VERY_LONG / 2, MHD_OPTION_END);
-  if (d == NULL)
-    return 1;
-  c = curl_easy_init ();
-  url = malloc (VERY_LONG);
-  memset (url, 'a', VERY_LONG);
-  url[VERY_LONG - 1] = '\0';
-  memcpy (url, "http://localhost:1080/";, strlen ("http://localhost:1080/";));
-  curl_easy_setopt (c, CURLOPT_URL, url);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  if (oneone)
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  else
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-  if (CURLE_OK == curl_easy_perform (c))
-    {
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      free (url);
-      return 2;
-    }
-  if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code))
-    {
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      free (url);
-      return 4;
-    }
-  curl_easy_cleanup (c);
-  MHD_stop_daemon (d);
-  free (url);
-  if (code != MHD_HTTP_REQUEST_URI_TOO_LONG)
-    return 8;
-  return 0;
-}
-
-
-static int
-testLongHeaderGet ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  char *url;
-  long code;
-  struct curl_slist *header = NULL;
-
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
-                        1080,
-                        &apc_all,
-                        NULL,
-                        &ahc_echo,
-                        "GET",
-                        MHD_OPTION_CONNECTION_MEMORY_LIMIT,
-                        VERY_LONG / 2, MHD_OPTION_END);
-  if (d == NULL)
-    return 16;
-  c = curl_easy_init ();
-  url = malloc (VERY_LONG);
-  memset (url, 'a', VERY_LONG);
-  url[VERY_LONG - 1] = '\0';
-  url[VERY_LONG / 2] = ':';
-  url[VERY_LONG / 2 + 1] = ':';
-  header = curl_slist_append (header, url);
-
-  curl_easy_setopt (c, CURLOPT_HTTPHEADER, header);
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  if (oneone)
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  else
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-  if (CURLE_OK == curl_easy_perform (c))
-    {
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      curl_slist_free_all (header);
-      free (url);
-      return 32;
-    }
-  if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code))
-    {
-      curl_slist_free_all (header);
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      free (url);
-      return 64;
-    }
-  curl_slist_free_all (header);
-  curl_easy_cleanup (c);
-  MHD_stop_daemon (d);
-  free (url);
-  if (code != MHD_HTTP_REQUEST_ENTITY_TOO_LARGE)
-    return 128;
-  return 0;
-}
-
-int
-main (int argc, char *const *argv)
-{
-  unsigned int errorCount = 0;
-
-  oneone = NULL != strstr (argv[0], "11");
-  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
-    return 2;
-  errorCount += testLongUrlGet ();
-  errorCount += testLongHeaderGet ();
-  if (errorCount != 0)
-    fprintf (stderr, "Error (code: %u)\n", errorCount);
-  curl_global_cleanup ();
-  return errorCount != 0;       /* 0 == pass */
-}

Deleted: libmicrohttpd/src/daemon/daemontest_put.c
===================================================================
--- libmicrohttpd/src/daemon/daemontest_put.c   2008-04-12 10:43:20 UTC (rev 
6675)
+++ libmicrohttpd/src/daemon/daemontest_put.c   2008-04-12 20:45:58 UTC (rev 
6676)
@@ -1,375 +0,0 @@
-/*
-     This file is part of libmicrohttpd
-     (C) 2007 Christian Grothoff
-
-     libmicrohttpd is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
-     option) any later version.
-
-     libmicrohttpd is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with libmicrohttpd; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file daemontest_put.c
- * @brief  Testcase for libmicrohttpd PUT operations
- * @author Christian Grothoff
- */
-
-#include "config.h"
-#include <curl/curl.h>
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#endif
-
-static int oneone;
-
-struct CBC
-{
-  char *buf;
-  size_t pos;
-  size_t size;
-};
-
-static size_t
-putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
-{
-  unsigned int *pos = ptr;
-  unsigned int wrt;
-
-  wrt = size * nmemb;
-  if (wrt > 8 - (*pos))
-    wrt = 8 - (*pos);
-  memcpy (stream, &("Hello123"[*pos]), wrt);
-  (*pos) += wrt;
-  return wrt;
-}
-
-static size_t
-copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
-{
-  struct CBC *cbc = ctx;
-
-  if (cbc->pos + size * nmemb > cbc->size)
-    return 0;                   /* overflow */
-  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
-  cbc->pos += size * nmemb;
-  return size * nmemb;
-}
-
-static int
-ahc_echo (void *cls,
-          struct MHD_Connection *connection,
-          const char *url,
-          const char *method,
-          const char *version,
-          const char *upload_data, unsigned int *upload_data_size,
-          void **unused)
-{
-  int *done = cls;
-  struct MHD_Response *response;
-  int ret;
-
-  if (0 != strcmp ("PUT", method))
-    return MHD_NO;              /* unexpected method */
-  if ((*done) == 0)
-    {
-      if (*upload_data_size != 8)
-        return MHD_YES;         /* not yet ready */
-      if (0 == memcmp (upload_data, "Hello123", 8))
-        {
-          *upload_data_size = 0;
-        }
-      else
-        {
-          printf ("Invalid upload data `%8s'!\n", upload_data);
-          return MHD_NO;
-        }
-      *done = 1;
-      return MHD_YES;
-    }
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
-  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
-  MHD_destroy_response (response);
-  return ret;
-}
-
-
-static int
-testInternalPut ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  unsigned int pos = 0;
-  int done_flag = 0;
-  CURLcode errornum;
-
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
-                        1080,
-                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
-  if (d == NULL)
-    return 1;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
-  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
-  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
-  curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  if (oneone)
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  else
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-  if (CURLE_OK != (errornum = curl_easy_perform (c)))
-    {
-      fprintf (stderr,
-               "curl_easy_perform failed: `%s'\n",
-               curl_easy_strerror (errornum));
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 2;
-    }
-  curl_easy_cleanup (c);
-  MHD_stop_daemon (d);
-  if (cbc.pos != strlen ("/hello_world"))
-    return 4;
-  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
-    return 8;
-  return 0;
-}
-
-static int
-testMultithreadedPut ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  unsigned int pos = 0;
-  int done_flag = 0;
-  CURLcode errornum;
-
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
-                        1081,
-                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
-  if (d == NULL)
-    return 16;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
-  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
-  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
-  curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  if (oneone)
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  else
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-  if (CURLE_OK != (errornum = curl_easy_perform (c)))
-    {
-      fprintf (stderr,
-               "curl_easy_perform failed: `%s'\n",
-               curl_easy_strerror (errornum));
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 32;
-    }
-  curl_easy_cleanup (c);
-  MHD_stop_daemon (d);
-  if (cbc.pos != strlen ("/hello_world"))
-    return 64;
-  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
-    return 128;
-
-  return 0;
-}
-
-
-static int
-testExternalPut ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  CURLM *multi;
-  CURLMcode mret;
-  fd_set rs;
-  fd_set ws;
-  fd_set es;
-  int max;
-  int running;
-  struct CURLMsg *msg;
-  time_t start;
-  struct timeval tv;
-  unsigned int pos = 0;
-  int done_flag = 0;
-
-  multi = NULL;
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_DEBUG,
-                        1082,
-                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
-  if (d == NULL)
-    return 256;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
-  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
-  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
-  curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  if (oneone)
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  else
-    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-
-
-  multi = curl_multi_init ();
-  if (multi == NULL)
-    {
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 512;
-    }
-  mret = curl_multi_add_handle (multi, c);
-  if (mret != CURLM_OK)
-    {
-      curl_multi_cleanup (multi);
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 1024;
-    }
-  start = time (NULL);
-  while ((time (NULL) - start < 5) && (multi != NULL))
-    {
-      max = 0;
-      FD_ZERO (&rs);
-      FD_ZERO (&ws);
-      FD_ZERO (&es);
-      curl_multi_perform (multi, &running);
-      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
-      if (mret != CURLM_OK)
-        {
-          curl_multi_remove_handle (multi, c);
-          curl_multi_cleanup (multi);
-          curl_easy_cleanup (c);
-          MHD_stop_daemon (d);
-          return 2048;
-        }
-      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
-        {
-          curl_multi_remove_handle (multi, c);
-          curl_multi_cleanup (multi);
-          curl_easy_cleanup (c);
-          MHD_stop_daemon (d);
-          return 4096;
-        }
-      tv.tv_sec = 0;
-      tv.tv_usec = 1000;
-      select (max + 1, &rs, &ws, &es, &tv);
-      curl_multi_perform (multi, &running);
-      if (running == 0)
-        {
-          msg = curl_multi_info_read (multi, &running);
-          if (msg == NULL)
-            break;
-          if (msg->msg == CURLMSG_DONE)
-            {
-              if (msg->data.result != CURLE_OK)
-                printf ("%s failed at %s:%d: `%s'\n",
-                        "curl_multi_perform",
-                        __FILE__,
-                        __LINE__, curl_easy_strerror (msg->data.result));
-              curl_multi_remove_handle (multi, c);
-              curl_multi_cleanup (multi);
-              curl_easy_cleanup (c);
-              c = NULL;
-              multi = NULL;
-            }
-        }
-      MHD_run (d);
-    }
-  if (multi != NULL)
-    {
-      curl_multi_remove_handle (multi, c);
-      curl_easy_cleanup (c);
-      curl_multi_cleanup (multi);
-    }
-  MHD_stop_daemon (d);
-  if (cbc.pos != strlen ("/hello_world"))
-    return 8192;
-  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
-    return 16384;
-  return 0;
-}
-
-
-
-int
-main (int argc, char *const *argv)
-{
-  unsigned int errorCount = 0;
-
-  oneone = NULL != strstr (argv[0], "11");
-  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
-    return 2;
-  errorCount += testInternalPut ();
-  if (0)
-    {
-      errorCount += testMultithreadedPut ();
-      errorCount += testExternalPut ();
-    }
-  if (errorCount != 0)
-    fprintf (stderr, "Error (code: %u)\n", errorCount);
-  curl_global_cleanup ();
-  return errorCount != 0;       /* 0 == pass */
-}

Deleted: libmicrohttpd/src/daemon/daemontest_put_chunked.c
===================================================================
--- libmicrohttpd/src/daemon/daemontest_put_chunked.c   2008-04-12 10:43:20 UTC 
(rev 6675)
+++ libmicrohttpd/src/daemon/daemontest_put_chunked.c   2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -1,383 +0,0 @@
-/*
-     This file is part of libmicrohttpd
-     (C) 2007 Christian Grothoff
-
-     libmicrohttpd is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
-     option) any later version.
-
-     libmicrohttpd is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with libmicrohttpd; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file daemontest_put_chunked.c
- * @brief Testcase for libmicrohttpd PUT operations with chunked encoding
- *        for the upload data
- * @author Christian Grothoff
- */
-
-#include "config.h"
-#include <curl/curl.h>
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#ifndef WINDOWS
-#include <unistd.h>
-#endif
-
-struct CBC
-{
-  char *buf;
-  size_t pos;
-  size_t size;
-};
-
-static size_t
-putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
-{
-  unsigned int *pos = ptr;
-  unsigned int wrt;
-
-  wrt = size * nmemb;
-  if (wrt > 8 - (*pos))
-    wrt = 8 - (*pos);
-  if (wrt > 4)
-    wrt = 4;                    /* only send half at first => force multiple 
chunks! */
-  memcpy (stream, &("Hello123"[*pos]), wrt);
-  (*pos) += wrt;
-  return wrt;
-}
-
-static size_t
-copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
-{
-  struct CBC *cbc = ctx;
-
-  if (cbc->pos + size * nmemb > cbc->size)
-    return 0;                   /* overflow */
-  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
-  cbc->pos += size * nmemb;
-  return size * nmemb;
-}
-
-static int
-ahc_echo (void *cls,
-          struct MHD_Connection *connection,
-          const char *url,
-          const char *method,
-          const char *version,
-          const char *upload_data, unsigned int *upload_data_size,
-          void **unused)
-{
-  int *done = cls;
-  struct MHD_Response *response;
-  int ret;
-  int have;
-
-  if (0 != strcmp ("PUT", method))
-    return MHD_NO;              /* unexpected method */
-  if ((*done) < 8)
-    {
-      have = *upload_data_size;
-      if (have + *done > 8)
-        {
-          printf ("Invalid upload data `%8s'!\n", upload_data);
-          return MHD_NO;
-        }
-      if (0 == memcmp (upload_data, &"Hello123"[*done], have))
-        {
-          *done += have;
-          *upload_data_size = 0;
-        }
-      else
-        {
-          printf ("Invalid upload data `%8s'!\n", upload_data);
-          return MHD_NO;
-        }
-#if 0
-      fprintf (stderr, "Not ready for response: %u/%u\n", *done, 8);
-#endif
-      return MHD_YES;
-    }
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
-  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
-  MHD_destroy_response (response);
-  return ret;
-}
-
-
-static int
-testInternalPut ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  unsigned int pos = 0;
-  int done_flag = 0;
-  CURLcode errornum;
-
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
-                        11080,
-                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
-  if (d == NULL)
-    return 1;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11080/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
-  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
-  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
-  /*
-     // by not giving the file size, we force chunking!
-     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
-   */
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-  if (CURLE_OK != (errornum = curl_easy_perform (c)))
-    {
-      fprintf (stderr,
-               "curl_easy_perform failed: `%s'\n",
-               curl_easy_strerror (errornum));
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 2;
-    }
-  curl_easy_cleanup (c);
-  MHD_stop_daemon (d);
-  if (cbc.pos != strlen ("/hello_world"))
-    return 4;
-  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
-    return 8;
-  return 0;
-}
-
-static int
-testMultithreadedPut ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  unsigned int pos = 0;
-  int done_flag = 0;
-  CURLcode errornum;
-
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
-                        11081,
-                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
-  if (d == NULL)
-    return 16;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
-  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
-  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
-  /*
-     // by not giving the file size, we force chunking!
-     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
-   */
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-  if (CURLE_OK != (errornum = curl_easy_perform (c)))
-    {
-      fprintf (stderr,
-               "curl_easy_perform failed: `%s'\n",
-               curl_easy_strerror (errornum));
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 32;
-    }
-  curl_easy_cleanup (c);
-  MHD_stop_daemon (d);
-  if (cbc.pos != strlen ("/hello_world"))
-    return 64;
-  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
-    return 128;
-
-  return 0;
-}
-
-
-static int
-testExternalPut ()
-{
-  struct MHD_Daemon *d;
-  CURL *c;
-  char buf[2048];
-  struct CBC cbc;
-  CURLM *multi;
-  CURLMcode mret;
-  fd_set rs;
-  fd_set ws;
-  fd_set es;
-  int max;
-  int running;
-  struct CURLMsg *msg;
-  time_t start;
-  struct timeval tv;
-  unsigned int pos = 0;
-  int done_flag = 0;
-
-  multi = NULL;
-  cbc.buf = buf;
-  cbc.size = 2048;
-  cbc.pos = 0;
-  d = MHD_start_daemon (MHD_USE_DEBUG,
-                        11082,
-                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
-  if (d == NULL)
-    return 256;
-  c = curl_easy_init ();
-  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11082/hello_world";);
-  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
-  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
-  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
-  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
-  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
-  /*
-     // by not giving the file size, we force chunking!
-     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
-   */
-  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
-  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
-  // NOTE: use of CONNECTTIMEOUT without also
-  //   setting NOSIGNAL results in really weird
-  //   crashes on my system!
-  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
-
-
-  multi = curl_multi_init ();
-  if (multi == NULL)
-    {
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 512;
-    }
-  mret = curl_multi_add_handle (multi, c);
-  if (mret != CURLM_OK)
-    {
-      curl_multi_cleanup (multi);
-      curl_easy_cleanup (c);
-      MHD_stop_daemon (d);
-      return 1024;
-    }
-  start = time (NULL);
-  while ((time (NULL) - start < 5) && (multi != NULL))
-    {
-      max = 0;
-      FD_ZERO (&rs);
-      FD_ZERO (&ws);
-      FD_ZERO (&es);
-      curl_multi_perform (multi, &running);
-      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
-      if (mret != CURLM_OK)
-        {
-          curl_multi_remove_handle (multi, c);
-          curl_multi_cleanup (multi);
-          curl_easy_cleanup (c);
-          MHD_stop_daemon (d);
-          return 2048;
-        }
-      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
-        {
-          curl_multi_remove_handle (multi, c);
-          curl_multi_cleanup (multi);
-          curl_easy_cleanup (c);
-          MHD_stop_daemon (d);
-          return 4096;
-        }
-      tv.tv_sec = 0;
-      tv.tv_usec = 1000;
-      select (max + 1, &rs, &ws, &es, &tv);
-      curl_multi_perform (multi, &running);
-      if (running == 0)
-        {
-          msg = curl_multi_info_read (multi, &running);
-          if (msg == NULL)
-            break;
-          if (msg->msg == CURLMSG_DONE)
-            {
-              if (msg->data.result != CURLE_OK)
-                printf ("%s failed at %s:%d: `%s'\n",
-                        "curl_multi_perform",
-                        __FILE__,
-                        __LINE__, curl_easy_strerror (msg->data.result));
-              curl_multi_remove_handle (multi, c);
-              curl_multi_cleanup (multi);
-              curl_easy_cleanup (c);
-              c = NULL;
-              multi = NULL;
-            }
-        }
-      MHD_run (d);
-    }
-  if (multi != NULL)
-    {
-      curl_multi_remove_handle (multi, c);
-      curl_easy_cleanup (c);
-      curl_multi_cleanup (multi);
-    }
-  MHD_stop_daemon (d);
-  if (cbc.pos != strlen ("/hello_world"))
-    return 8192;
-  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
-    return 16384;
-  return 0;
-}
-
-
-
-int
-main (int argc, char *const *argv)
-{
-  unsigned int errorCount = 0;
-
-  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
-    return 2;
-  errorCount += testInternalPut ();
-  if (0)
-    {
-      errorCount += testMultithreadedPut ();
-      errorCount += testExternalPut ();
-    }
-  if (errorCount != 0)
-    fprintf (stderr, "Error (code: %u)\n", errorCount);
-  curl_global_cleanup ();
-  return errorCount != 0;       /* 0 == pass */
-}

Deleted: libmicrohttpd/src/daemon/fileserver_example.c
===================================================================
--- libmicrohttpd/src/daemon/fileserver_example.c       2008-04-12 10:43:20 UTC 
(rev 6675)
+++ libmicrohttpd/src/daemon/fileserver_example.c       2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -1,113 +0,0 @@
-/*
-     This file is part of libmicrohttpd
-     (C) 2007 Christian Grothoff
-
-     libmicrohttpd is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
-     option) any later version.
-
-     libmicrohttpd is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with libmicrohttpd; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file fileserver_example.c
- * @brief minimal example for how to use libmicrohttpd to server files
- * @author Christian Grothoff
- */
-
-#include "config.h"
-#include <microhttpd.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifndef MINGW
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <stdio.h>
-
-#define PAGE "<html><head><title>File not found</title></head><body>File not 
found</body></html>"
-
-static int
-file_reader (void *cls, size_t pos, char *buf, int max)
-{
-  FILE *file = cls;
-
-  fseek (file, pos, SEEK_SET);
-  return fread (buf, 1, max, file);
-}
-
-static int
-ahc_echo (void *cls,
-          struct MHD_Connection *connection,
-          const char *url,
-          const char *method,
-          const char *upload_data,
-          const char *version, unsigned int *upload_data_size, void **ptr)
-{
-  static int aptr;
-  struct MHD_Response *response;
-  int ret;
-  FILE *file;
-  struct stat buf;
-
-  if (0 != strcmp (method, "GET"))
-    return MHD_NO;              /* unexpected method */
-  if (&aptr != *ptr)
-    {
-      /* do never respond on first call */
-      *ptr = &aptr;
-      return MHD_YES;
-    }
-  *ptr = NULL;                  /* reset when done */
-  file = fopen (&url[1], "r");
-  if (file == NULL)
-    {
-      response = MHD_create_response_from_data (strlen (PAGE),
-                                                (void *) PAGE,
-                                                MHD_NO, MHD_NO);
-      ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
-      MHD_destroy_response (response);
-    }
-  else
-    {
-      stat (&url[1], &buf);
-      response = MHD_create_response_from_callback (buf.st_size, 32 * 1024,    
 /* 32k page size */
-                                                    &file_reader,
-                                                    file,
-                                                    
(MHD_ContentReaderFreeCallback)
-                                                    & fclose);
-      ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
-      MHD_destroy_response (response);
-    }
-  return ret;
-}
-
-int
-main (int argc, char *const *argv)
-{
-  struct MHD_Daemon *d;
-
-  if (argc != 3)
-    {
-      printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
-      return 1;
-    }
-  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
-                        atoi (argv[1]),
-                        NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
-  if (d == NULL)
-    return 1;
-  sleep (atoi (argv[2]));
-  MHD_stop_daemon (d);
-  return 0;
-}

Deleted: libmicrohttpd/src/daemon/minimal_example.c
===================================================================
--- libmicrohttpd/src/daemon/minimal_example.c  2008-04-12 10:43:20 UTC (rev 
6675)
+++ libmicrohttpd/src/daemon/minimal_example.c  2008-04-12 20:45:58 UTC (rev 
6676)
@@ -1,85 +0,0 @@
-/*
-     This file is part of libmicrohttpd
-     (C) 2007 Christian Grothoff
-
-     libmicrohttpd is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
-     option) any later version.
-
-     libmicrohttpd is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with libmicrohttpd; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file minimal_example.c
- * @brief minimal example for how to use libmicrohttpd
- * @author Christian Grothoff
- */
-
-#include "config.h"
-#include <microhttpd.h>
-#include <stdlib.h>
-#ifndef MINGW
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <stdio.h>
-
-#define PAGE "<html><head><title>libmicrohttpd 
demo</title></head><body>libmicrohttpd demo</body></html>"
-
-static int
-ahc_echo (void *cls,
-          struct MHD_Connection *connection,
-          const char *url,
-          const char *method,
-          const char *version,
-          const char *upload_data, unsigned int *upload_data_size, void **ptr)
-{
-  static int aptr;
-  const char *me = cls;
-  struct MHD_Response *response;
-  int ret;
-
-  if (0 != strcmp (method, "GET"))
-    return MHD_NO;              /* unexpected method */
-  if (&aptr != *ptr)
-    {
-      /* do never respond on first call */
-      *ptr = &aptr;
-      return MHD_YES;
-    }
-  *ptr = NULL;                  /* reset when done */
-  response = MHD_create_response_from_data (strlen (me),
-                                            (void *) me, MHD_NO, MHD_NO);
-  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
-  MHD_destroy_response (response);
-  return ret;
-}
-
-int
-main (int argc, char *const *argv)
-{
-  struct MHD_Daemon *d;
-
-  if (argc != 3)
-    {
-      printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
-      return 1;
-    }
-  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
-                        atoi (argv[1]),
-                        NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
-  if (d == NULL)
-    return 1;
-  sleep (atoi (argv[2]));
-  MHD_stop_daemon (d);
-  return 0;
-}

Added: libmicrohttpd/src/examples/Makefile.am
===================================================================
--- libmicrohttpd/src/examples/Makefile.am                              (rev 0)
+++ libmicrohttpd/src/examples/Makefile.am      2008-04-12 20:45:58 UTC (rev 
6676)
@@ -0,0 +1,18 @@
+SUBDIRS  = .
+
+INCLUDES = -I$(top_srcdir)/src/include
+
+# example programs
+
+noinst_PROGRAMS = minimal_example fileserver_example
+
+minimal_example_SOURCES = \
+ minimal_example.c 
+minimal_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la 
+
+fileserver_example_SOURCES = \
+ fileserver_example.c 
+fileserver_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la 
+

Copied: libmicrohttpd/src/examples/fileserver_example.c (from rev 6670, 
libmicrohttpd/src/daemon/fileserver_example.c)
===================================================================
--- libmicrohttpd/src/examples/fileserver_example.c                             
(rev 0)
+++ libmicrohttpd/src/examples/fileserver_example.c     2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -0,0 +1,113 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file fileserver_example.c
+ * @brief minimal example for how to use libmicrohttpd to server files
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef MINGW
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+
+#define PAGE "<html><head><title>File not found</title></head><body>File not 
found</body></html>"
+
+static int
+file_reader (void *cls, size_t pos, char *buf, int max)
+{
+  FILE *file = cls;
+
+  fseek (file, pos, SEEK_SET);
+  return fread (buf, 1, max, file);
+}
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *upload_data,
+          const char *version, unsigned int *upload_data_size, void **ptr)
+{
+  static int aptr;
+  struct MHD_Response *response;
+  int ret;
+  FILE *file;
+  struct stat buf;
+
+  if (0 != strcmp (method, "GET"))
+    return MHD_NO;              /* unexpected method */
+  if (&aptr != *ptr)
+    {
+      /* do never respond on first call */
+      *ptr = &aptr;
+      return MHD_YES;
+    }
+  *ptr = NULL;                  /* reset when done */
+  file = fopen (&url[1], "r");
+  if (file == NULL)
+    {
+      response = MHD_create_response_from_data (strlen (PAGE),
+                                                (void *) PAGE,
+                                                MHD_NO, MHD_NO);
+      ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
+      MHD_destroy_response (response);
+    }
+  else
+    {
+      stat (&url[1], &buf);
+      response = MHD_create_response_from_callback (buf.st_size, 32 * 1024,    
 /* 32k page size */
+                                                    &file_reader,
+                                                    file,
+                                                    
(MHD_ContentReaderFreeCallback)
+                                                    & fclose);
+      ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+      MHD_destroy_response (response);
+    }
+  return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+  struct MHD_Daemon *d;
+
+  if (argc != 3)
+    {
+      printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
+      return 1;
+    }
+  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+                        atoi (argv[1]),
+                        NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  sleep (atoi (argv[2]));
+  MHD_stop_daemon (d);
+  return 0;
+}

Copied: libmicrohttpd/src/examples/minimal_example.c (from rev 6670, 
libmicrohttpd/src/daemon/minimal_example.c)
===================================================================
--- libmicrohttpd/src/examples/minimal_example.c                                
(rev 0)
+++ libmicrohttpd/src/examples/minimal_example.c        2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -0,0 +1,85 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file minimal_example.c
+ * @brief minimal example for how to use libmicrohttpd
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <microhttpd.h>
+#include <stdlib.h>
+#ifndef MINGW
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+
+#define PAGE "<html><head><title>libmicrohttpd 
demo</title></head><body>libmicrohttpd demo</body></html>"
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, unsigned int *upload_data_size, void **ptr)
+{
+  static int aptr;
+  const char *me = cls;
+  struct MHD_Response *response;
+  int ret;
+
+  if (0 != strcmp (method, "GET"))
+    return MHD_NO;              /* unexpected method */
+  if (&aptr != *ptr)
+    {
+      /* do never respond on first call */
+      *ptr = &aptr;
+      return MHD_YES;
+    }
+  *ptr = NULL;                  /* reset when done */
+  response = MHD_create_response_from_data (strlen (me),
+                                            (void *) me, MHD_NO, MHD_NO);
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+int
+main (int argc, char *const *argv)
+{
+  struct MHD_Daemon *d;
+
+  if (argc != 3)
+    {
+      printf ("%s PORT SECONDS-TO-RUN\n", argv[0]);
+      return 1;
+    }
+  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+                        atoi (argv[1]),
+                        NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  sleep (atoi (argv[2]));
+  MHD_stop_daemon (d);
+  return 0;
+}

Added: libmicrohttpd/src/testcurl/Makefile.am
===================================================================
--- libmicrohttpd/src/testcurl/Makefile.am                              (rev 0)
+++ libmicrohttpd/src/testcurl/Makefile.am      2008-04-12 20:45:58 UTC (rev 
6676)
@@ -0,0 +1,126 @@
+SUBDIRS  = .
+
+INCLUDES = -I$(top_srcdir)/src/include
+
+check_PROGRAMS = \
+  postprocessor_test \
+  daemontest \
+  daemontest_get \
+  daemontest_post \
+  daemontest_postform \
+  daemontest_post_loop \
+  daemontest_put \
+  daemontest_large_put \
+  daemontest_get11 \
+  daemontest_post11 \
+  daemontest_postform11 \
+  daemontest_post_loop11 \
+  daemontest_put11 \
+  daemontest_large_put11 \
+  daemontest_long_header \
+  daemontest_get_chunked \
+  daemontest_put_chunked 
+
+TESTS = $(check_PROGRAMS)
+
+daemontest_SOURCES = \
+  daemontest.c
+daemontest_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la 
+
+postprocessor_test_SOURCES = \
+  postprocessor_test.c
+postprocessor_test_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la 
+
+daemontest_get_SOURCES = \
+  daemontest_get.c
+daemontest_get_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_get_chunked_SOURCES = \
+  daemontest_get_chunked.c
+daemontest_get_chunked_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_post_SOURCES = \
+  daemontest_post.c
+daemontest_post_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_postform_SOURCES = \
+  daemontest_postform.c
+daemontest_postform_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_post_loop_SOURCES = \
+  daemontest_post_loop.c
+daemontest_post_loop_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_put_SOURCES = \
+  daemontest_put.c
+daemontest_put_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_put_chunked_SOURCES = \
+  daemontest_put_chunked.c
+daemontest_put_chunked_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_get11_SOURCES = \
+  daemontest_get.c
+daemontest_get11_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_post11_SOURCES = \
+  daemontest_post.c
+daemontest_post11_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_postform11_SOURCES = \
+  daemontest_postform.c
+daemontest_postform11_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_post_loop11_SOURCES = \
+  daemontest_post_loop.c
+daemontest_post_loop11_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_put11_SOURCES = \
+  daemontest_put.c
+daemontest_put11_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+
+daemontest_large_put_SOURCES = \
+  daemontest_large_put.c
+daemontest_large_put_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_large_put11_SOURCES = \
+  daemontest_large_put.c
+daemontest_large_put11_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_long_header_SOURCES = \
+  daemontest_long_header.c
+daemontest_long_header_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+

Copied: libmicrohttpd/src/testcurl/daemontest.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest.c)
===================================================================
--- libmicrohttpd/src/testcurl/daemontest.c                             (rev 0)
+++ libmicrohttpd/src/testcurl/daemontest.c     2008-04-12 20:45:58 UTC (rev 
6676)
@@ -0,0 +1,163 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest.c
+ * @brief  Testcase for libmicrohttpd starts and stops
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include "microhttpd.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+
+static int
+testStartError ()
+{
+  struct MHD_Daemon *d;
+
+  d = MHD_start_daemon (MHD_USE_DEBUG, 0, NULL, NULL, NULL, NULL);
+  if (d != NULL)
+    return 1;
+  return 0;
+}
+
+static int
+apc_nothing (void *cls, const struct sockaddr *addr, socklen_t addrlen)
+{
+  return MHD_NO;
+}
+
+static int
+apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen)
+{
+  return MHD_YES;
+}
+
+static int
+ahc_nothing (void *cls,
+             struct MHD_Connection *connection,
+             const char *url,
+             const char *method,
+             const char *version,
+             const char *upload_data, unsigned int *upload_data_size,
+             void **unused)
+{
+  return MHD_NO;
+}
+
+static int
+testStartStop ()
+{
+  struct MHD_Daemon *d;
+
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1080,
+                        &apc_nothing,
+                        NULL, &ahc_nothing, NULL, MHD_OPTION_END);
+  if (d == NULL)
+    return 2;
+  MHD_stop_daemon (d);
+  return 0;
+}
+
+static int
+testExternalRun ()
+{
+  struct MHD_Daemon *d;
+  fd_set rs;
+  int maxfd;
+  int i;
+
+  d = MHD_start_daemon (MHD_USE_DEBUG,
+                        1081,
+                        &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
+
+  if (d == NULL)
+    return 4;
+  i = 0;
+  while (i < 15)
+    {
+      maxfd = 0;
+      FD_ZERO (&rs);
+      MHD_get_fdset (d, &rs, &rs, &rs, &maxfd);
+      if (MHD_run (d) == MHD_NO)
+        {
+          MHD_stop_daemon (d);
+          return 8;
+        }
+      i++;
+    }
+  MHD_stop_daemon (d);
+  return 0;
+}
+
+static int
+testThread ()
+{
+  struct MHD_Daemon *d;
+  d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY,
+                        1082,
+                        &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
+
+  if (d == NULL)
+    return 16;
+  if (MHD_run (d) != MHD_NO)
+    return 32;
+  MHD_stop_daemon (d);
+  return 0;
+}
+
+static int
+testMultithread ()
+{
+  struct MHD_Daemon *d;
+  d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION,
+                        1083,
+                        &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
+
+  if (d == NULL)
+    return 64;
+  if (MHD_run (d) != MHD_NO)
+    return 128;
+  MHD_stop_daemon (d);
+  return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+  errorCount += testStartError ();
+  errorCount += testStartStop ();
+  errorCount += testExternalRun ();
+  errorCount += testThread ();
+  errorCount += testMultithread ();
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  return errorCount != 0;       /* 0 == pass */
+}

Copied: libmicrohttpd/src/testcurl/daemontest_get.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest_get.c)
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_get.c                         (rev 0)
+++ libmicrohttpd/src/testcurl/daemontest_get.c 2008-04-12 20:45:58 UTC (rev 
6676)
@@ -0,0 +1,330 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_get.c
+ * @brief  Testcase for libmicrohttpd GET operations
+ *         TODO: test parsing of query
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+  struct CBC *cbc = ctx;
+
+  if (cbc->pos + size * nmemb > cbc->size)
+    return 0;                   /* overflow */
+  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+  cbc->pos += size * nmemb;
+  return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, unsigned int *upload_data_size,
+          void **unused)
+{
+  static int ptr;
+  const char *me = cls;
+  struct MHD_Response *response;
+  int ret;
+
+  if (0 != strcmp (me, method))
+    return MHD_NO;              /* unexpected method */
+  if (&ptr != *unused)
+    {
+      *unused = &ptr;
+      return MHD_YES;
+    }
+  *unused = NULL;
+  response = MHD_create_response_from_data (strlen (url),
+                                            (void *) url, MHD_NO, MHD_YES);
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  MHD_destroy_response (response);
+  if (ret == MHD_NO)
+    abort ();
+  return ret;
+}
+
+
+static int
+testInternalGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11080/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 2;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 4;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 8;
+  return 0;
+}
+
+static int
+testMultithreadedGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+                        1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 64;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+  return 0;
+}
+
+
+static int
+testExternalGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLM *multi;
+  CURLMcode mret;
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int max;
+  int running;
+  struct CURLMsg *msg;
+  time_t start;
+  struct timeval tv;
+
+  multi = NULL;
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_DEBUG,
+                        1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+  if (d == NULL)
+    return 256;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+  multi = curl_multi_init ();
+  if (multi == NULL)
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 512;
+    }
+  mret = curl_multi_add_handle (multi, c);
+  if (mret != CURLM_OK)
+    {
+      curl_multi_cleanup (multi);
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 1024;
+    }
+  start = time (NULL);
+  while ((time (NULL) - start < 5) && (multi != NULL))
+    {
+      max = 0;
+      FD_ZERO (&rs);
+      FD_ZERO (&ws);
+      FD_ZERO (&es);
+      curl_multi_perform (multi, &running);
+      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+      if (mret != CURLM_OK)
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 2048;
+        }
+      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 4096;
+        }
+      tv.tv_sec = 0;
+      tv.tv_usec = 1000;
+      select (max + 1, &rs, &ws, &es, &tv);
+      curl_multi_perform (multi, &running);
+      if (running == 0)
+        {
+          msg = curl_multi_info_read (multi, &running);
+          if (msg == NULL)
+            break;
+          if (msg->msg == CURLMSG_DONE)
+            {
+              if (msg->data.result != CURLE_OK)
+                printf ("%s failed at %s:%d: `%s'\n",
+                        "curl_multi_perform",
+                        __FILE__,
+                        __LINE__, curl_easy_strerror (msg->data.result));
+              curl_multi_remove_handle (multi, c);
+              curl_multi_cleanup (multi);
+              curl_easy_cleanup (c);
+              c = NULL;
+              multi = NULL;
+            }
+        }
+      MHD_run (d);
+    }
+  if (multi != NULL)
+    {
+      curl_multi_remove_handle (multi, c);
+      curl_easy_cleanup (c);
+      curl_multi_cleanup (multi);
+    }
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 8192;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 16384;
+  return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+
+  oneone = NULL != strstr (argv[0], "11");
+  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    return 2;
+  errorCount += testInternalGet ();
+  errorCount += testMultithreadedGet ();
+  errorCount += testExternalGet ();
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  curl_global_cleanup ();
+  return errorCount != 0;       /* 0 == pass */
+}

Copied: libmicrohttpd/src/testcurl/daemontest_get_chunked.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest_get_chunked.c)
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_get_chunked.c                         
(rev 0)
+++ libmicrohttpd/src/testcurl/daemontest_get_chunked.c 2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -0,0 +1,364 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_get_chunked.c
+ * @brief  Testcase for libmicrohttpd GET operations with chunked content 
encoding
+ *         TODO:
+ *         - how to test that chunking was actually used?
+ *         - use CURLOPT_HEADERFUNCTION to validate
+ *           footer was sent
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+  struct CBC *cbc = ctx;
+
+  if (cbc->pos + size * nmemb > cbc->size)
+    return 0;                   /* overflow */
+  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+  cbc->pos += size * nmemb;
+  return size * nmemb;
+}
+
+/**
+ * MHD content reader callback that returns
+ * data in chunks.
+ */
+static int
+crc (void *cls, size_t pos, char *buf, int max)
+{
+  struct MHD_Response **responseptr = cls;
+
+  if (pos == 128 * 10)
+    {
+      MHD_add_response_header (*responseptr, "Footer", "working");
+      return -1;                /* end of stream */
+    }
+  if (max < 128)
+    abort ();                   /* should not happen in this testcase... */
+  memset (buf, 'A' + (pos / 128), 128);
+  return 128;
+}
+
+/**
+ * Dummy function that does nothing.
+ */
+static void
+crcf (void *ptr)
+{
+  free (ptr);
+}
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, unsigned int *upload_data_size, void **ptr)
+{
+  static int aptr;
+  const char *me = cls;
+  struct MHD_Response *response;
+  struct MHD_Response **responseptr;
+  int ret;
+
+  if (0 != strcmp (me, method))
+    return MHD_NO;              /* unexpected method */
+  if (&aptr != *ptr)
+    {
+      /* do never respond on first call */
+      *ptr = &aptr;
+      return MHD_YES;
+    }
+  responseptr = malloc (sizeof (struct MHD_Response *));
+  response = MHD_create_response_from_callback (-1,
+                                                1024,
+                                                &crc, responseptr, &crcf);
+  *responseptr = response;
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+static int
+validate (struct CBC cbc, int ebase)
+{
+  int i;
+  char buf[128];
+
+  if (cbc.pos != 128 * 10)
+    return ebase;
+
+  for (i = 0; i < 10; i++)
+    {
+      memset (buf, 'A' + i, 128);
+      if (0 != memcmp (buf, &cbc.buf[i * 128], 128))
+        {
+          fprintf (stderr,
+                   "Got  `%.*s'\nWant `%.*s'\n",
+                   128, buf, 128, &cbc.buf[i * 128]);
+          return ebase * 2;
+        }
+    }
+  return 0;
+}
+
+static int
+testInternalGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 2;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  return validate (cbc, 4);
+}
+
+static int
+testMultithreadedGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+                        1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  return validate (cbc, 64);
+}
+
+
+static int
+testExternalGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLM *multi;
+  CURLMcode mret;
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int max;
+  int running;
+  struct CURLMsg *msg;
+  time_t start;
+  struct timeval tv;
+
+  multi = NULL;
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_DEBUG,
+                        1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+  if (d == NULL)
+    return 256;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 5L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+  multi = curl_multi_init ();
+  if (multi == NULL)
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 512;
+    }
+  mret = curl_multi_add_handle (multi, c);
+  if (mret != CURLM_OK)
+    {
+      curl_multi_cleanup (multi);
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 1024;
+    }
+  start = time (NULL);
+  while ((time (NULL) - start < 5) && (multi != NULL))
+    {
+      max = 0;
+      FD_ZERO (&rs);
+      FD_ZERO (&ws);
+      FD_ZERO (&es);
+      curl_multi_perform (multi, &running);
+      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+      if (mret != CURLM_OK)
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 2048;
+        }
+      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 4096;
+        }
+      tv.tv_sec = 0;
+      tv.tv_usec = 1000;
+      select (max + 1, &rs, &ws, &es, &tv);
+      curl_multi_perform (multi, &running);
+      if (running == 0)
+        {
+          msg = curl_multi_info_read (multi, &running);
+          if (msg == NULL)
+            break;
+          if (msg->msg == CURLMSG_DONE)
+            {
+              if (msg->data.result != CURLE_OK)
+                printf ("%s failed at %s:%d: `%s'\n",
+                        "curl_multi_perform",
+                        __FILE__,
+                        __LINE__, curl_easy_strerror (msg->data.result));
+              curl_multi_remove_handle (multi, c);
+              curl_multi_cleanup (multi);
+              curl_easy_cleanup (c);
+              c = NULL;
+              multi = NULL;
+            }
+        }
+      MHD_run (d);
+    }
+  if (multi != NULL)
+    {
+      curl_multi_remove_handle (multi, c);
+      curl_easy_cleanup (c);
+      curl_multi_cleanup (multi);
+    }
+  MHD_stop_daemon (d);
+  return validate (cbc, 8192);
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+
+  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    return 2;
+  errorCount += testInternalGet ();
+  if (0)
+    {
+      errorCount += testMultithreadedGet ();
+      errorCount += testExternalGet ();
+    }
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  curl_global_cleanup ();
+  return errorCount != 0;       /* 0 == pass */
+}

Copied: libmicrohttpd/src/testcurl/daemontest_large_put.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest_large_put.c)
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_large_put.c                           
(rev 0)
+++ libmicrohttpd/src/testcurl/daemontest_large_put.c   2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -0,0 +1,404 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_put.c
+ * @brief  Testcase for libmicrohttpd PUT operations
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+/**
+ * Do not make this much larger since we will hit the
+ * MHD default buffer limit and the test code is not
+ * written for incremental upload processing...
+ */
+#define PUT_SIZE (512 * 1024)
+
+static char *put_buffer;
+
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+};
+
+static size_t
+putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
+{
+  unsigned int *pos = ptr;
+  unsigned int wrt;
+
+  wrt = size * nmemb;
+  if (wrt > PUT_SIZE - (*pos))
+    wrt = PUT_SIZE - (*pos);
+  memcpy (stream, &put_buffer[*pos], wrt);
+  (*pos) += wrt;
+  return wrt;
+}
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+  struct CBC *cbc = ctx;
+
+  if (cbc->pos + size * nmemb > cbc->size)
+    return 0;                   /* overflow */
+  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+  cbc->pos += size * nmemb;
+  return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, unsigned int *upload_data_size,
+          void **unused)
+{
+  int *done = cls;
+  struct MHD_Response *response;
+  int ret;
+
+  if (0 != strcmp ("PUT", method))
+    return MHD_NO;              /* unexpected method */
+  if ((*done) == 0)
+    {
+      if (*upload_data_size != PUT_SIZE)
+        {
+#if 0
+          fprintf (stderr,
+                   "Waiting for more data (%u/%u)...\n",
+                   *upload_data_size, PUT_SIZE);
+#endif
+          return MHD_YES;       /* not yet ready */
+        }
+      if (0 == memcmp (upload_data, put_buffer, PUT_SIZE))
+        {
+          *upload_data_size = 0;
+        }
+      else
+        {
+          printf ("Invalid upload data!\n");
+          return MHD_NO;
+        }
+      *done = 1;
+      return MHD_YES;
+    }
+  response = MHD_create_response_from_data (strlen (url),
+                                            (void *) url, MHD_NO, MHD_YES);
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+
+static int
+testInternalPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
+  char buf[2048];
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1080,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 2;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 4;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 8;
+  return 0;
+}
+
+static int
+testMultithreadedPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
+  char buf[2048];
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+                        1081,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    {
+      free (cbc.buf);
+      return 16;
+    }
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    {
+      fprintf (stderr, "Got invalid response `%.*s'\n", cbc.pos, cbc.buf);
+      return 64;
+    }
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+  return 0;
+}
+
+
+static int
+testExternalPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  struct CBC cbc;
+  CURLM *multi;
+  CURLMcode mret;
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int max;
+  int running;
+  struct CURLMsg *msg;
+  time_t start;
+  struct timeval tv;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  char buf[2048];
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  multi = NULL;
+  d = MHD_start_daemon (MHD_USE_DEBUG,
+                        1082,
+                        NULL, NULL, &ahc_echo, &done_flag,
+                        MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+                        PUT_SIZE * 4, MHD_OPTION_END);
+  if (d == NULL)
+    return 256;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+  multi = curl_multi_init ();
+  if (multi == NULL)
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 512;
+    }
+  mret = curl_multi_add_handle (multi, c);
+  if (mret != CURLM_OK)
+    {
+      curl_multi_cleanup (multi);
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 1024;
+    }
+  start = time (NULL);
+  while ((time (NULL) - start < 5) && (multi != NULL))
+    {
+      max = 0;
+      FD_ZERO (&rs);
+      FD_ZERO (&ws);
+      FD_ZERO (&es);
+      curl_multi_perform (multi, &running);
+      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+      if (mret != CURLM_OK)
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 2048;
+        }
+      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 4096;
+        }
+      tv.tv_sec = 0;
+      tv.tv_usec = 1000;
+      select (max + 1, &rs, &ws, &es, &tv);
+      curl_multi_perform (multi, &running);
+      if (running == 0)
+        {
+          msg = curl_multi_info_read (multi, &running);
+          if (msg == NULL)
+            break;
+          if (msg->msg == CURLMSG_DONE)
+            {
+              if (msg->data.result != CURLE_OK)
+                printf ("%s failed at %s:%d: `%s'\n",
+                        "curl_multi_perform",
+                        __FILE__,
+                        __LINE__, curl_easy_strerror (msg->data.result));
+              curl_multi_remove_handle (multi, c);
+              curl_multi_cleanup (multi);
+              curl_easy_cleanup (c);
+              c = NULL;
+              multi = NULL;
+            }
+        }
+      MHD_run (d);
+    }
+  if (multi != NULL)
+    {
+      curl_multi_remove_handle (multi, c);
+      curl_easy_cleanup (c);
+      curl_multi_cleanup (multi);
+    }
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    {
+      fprintf (stderr, "Got invalid response `%.*s'\n", cbc.pos, cbc.buf);
+      return 8192;
+    }
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 16384;
+  return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+
+  oneone = NULL != strstr (argv[0], "11");
+  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    return 2;
+  put_buffer = malloc (PUT_SIZE);
+  memset (put_buffer, 1, PUT_SIZE);
+  if (0)
+    {
+      errorCount += testInternalPut ();
+      errorCount += testMultithreadedPut ();
+    }
+  errorCount += testExternalPut ();
+  free (put_buffer);
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  curl_global_cleanup ();
+  return errorCount != 0;       /* 0 == pass */
+}

Copied: libmicrohttpd/src/testcurl/daemontest_long_header.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest_long_header.c)
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_long_header.c                         
(rev 0)
+++ libmicrohttpd/src/testcurl/daemontest_long_header.c 2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -0,0 +1,240 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_long_header.c
+ * @brief  Testcase for libmicrohttpd handling of very long headers
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+/**
+ * We will set the memory available per connection to
+ * half of this value, so the actual value does not have
+ * to be big at all...
+ */
+#define VERY_LONG (1024*10)
+
+static int oneone;
+
+static int
+apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen)
+{
+  return MHD_YES;
+}
+
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+  return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, unsigned int *upload_data_size,
+          void **unused)
+{
+  const char *me = cls;
+  struct MHD_Response *response;
+  int ret;
+
+  if (0 != strcmp (me, method))
+    return MHD_NO;              /* unexpected method */
+  response = MHD_create_response_from_data (strlen (url),
+                                            (void *) url, MHD_NO, MHD_YES);
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+
+static int
+testLongUrlGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  char *url;
+  long code;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+                        1080,
+                        &apc_all,
+                        NULL,
+                        &ahc_echo,
+                        "GET",
+                        MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+                        VERY_LONG / 2, MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  c = curl_easy_init ();
+  url = malloc (VERY_LONG);
+  memset (url, 'a', VERY_LONG);
+  url[VERY_LONG - 1] = '\0';
+  memcpy (url, "http://localhost:1080/";, strlen ("http://localhost:1080/";));
+  curl_easy_setopt (c, CURLOPT_URL, url);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK == curl_easy_perform (c))
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      free (url);
+      return 2;
+    }
+  if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code))
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      free (url);
+      return 4;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  free (url);
+  if (code != MHD_HTTP_REQUEST_URI_TOO_LONG)
+    return 8;
+  return 0;
+}
+
+
+static int
+testLongHeaderGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  char *url;
+  long code;
+  struct curl_slist *header = NULL;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+                        1080,
+                        &apc_all,
+                        NULL,
+                        &ahc_echo,
+                        "GET",
+                        MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+                        VERY_LONG / 2, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  url = malloc (VERY_LONG);
+  memset (url, 'a', VERY_LONG);
+  url[VERY_LONG - 1] = '\0';
+  url[VERY_LONG / 2] = ':';
+  url[VERY_LONG / 2 + 1] = ':';
+  header = curl_slist_append (header, url);
+
+  curl_easy_setopt (c, CURLOPT_HTTPHEADER, header);
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK == curl_easy_perform (c))
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      curl_slist_free_all (header);
+      free (url);
+      return 32;
+    }
+  if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code))
+    {
+      curl_slist_free_all (header);
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      free (url);
+      return 64;
+    }
+  curl_slist_free_all (header);
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  free (url);
+  if (code != MHD_HTTP_REQUEST_ENTITY_TOO_LARGE)
+    return 128;
+  return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+
+  oneone = NULL != strstr (argv[0], "11");
+  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    return 2;
+  errorCount += testLongUrlGet ();
+  errorCount += testLongHeaderGet ();
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  curl_global_cleanup ();
+  return errorCount != 0;       /* 0 == pass */
+}

Copied: libmicrohttpd/src/testcurl/daemontest_put.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest_put.c)
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_put.c                         (rev 0)
+++ libmicrohttpd/src/testcurl/daemontest_put.c 2008-04-12 20:45:58 UTC (rev 
6676)
@@ -0,0 +1,375 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_put.c
+ * @brief  Testcase for libmicrohttpd PUT operations
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+};
+
+static size_t
+putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
+{
+  unsigned int *pos = ptr;
+  unsigned int wrt;
+
+  wrt = size * nmemb;
+  if (wrt > 8 - (*pos))
+    wrt = 8 - (*pos);
+  memcpy (stream, &("Hello123"[*pos]), wrt);
+  (*pos) += wrt;
+  return wrt;
+}
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+  struct CBC *cbc = ctx;
+
+  if (cbc->pos + size * nmemb > cbc->size)
+    return 0;                   /* overflow */
+  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+  cbc->pos += size * nmemb;
+  return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, unsigned int *upload_data_size,
+          void **unused)
+{
+  int *done = cls;
+  struct MHD_Response *response;
+  int ret;
+
+  if (0 != strcmp ("PUT", method))
+    return MHD_NO;              /* unexpected method */
+  if ((*done) == 0)
+    {
+      if (*upload_data_size != 8)
+        return MHD_YES;         /* not yet ready */
+      if (0 == memcmp (upload_data, "Hello123", 8))
+        {
+          *upload_data_size = 0;
+        }
+      else
+        {
+          printf ("Invalid upload data `%8s'!\n", upload_data);
+          return MHD_NO;
+        }
+      *done = 1;
+      return MHD_YES;
+    }
+  response = MHD_create_response_from_data (strlen (url),
+                                            (void *) url, MHD_NO, MHD_YES);
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+
+static int
+testInternalPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1080,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 2;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 4;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 8;
+  return 0;
+}
+
+static int
+testMultithreadedPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+                        1081,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 64;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+
+  return 0;
+}
+
+
+static int
+testExternalPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLM *multi;
+  CURLMcode mret;
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int max;
+  int running;
+  struct CURLMsg *msg;
+  time_t start;
+  struct timeval tv;
+  unsigned int pos = 0;
+  int done_flag = 0;
+
+  multi = NULL;
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_DEBUG,
+                        1082,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 256;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+  multi = curl_multi_init ();
+  if (multi == NULL)
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 512;
+    }
+  mret = curl_multi_add_handle (multi, c);
+  if (mret != CURLM_OK)
+    {
+      curl_multi_cleanup (multi);
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 1024;
+    }
+  start = time (NULL);
+  while ((time (NULL) - start < 5) && (multi != NULL))
+    {
+      max = 0;
+      FD_ZERO (&rs);
+      FD_ZERO (&ws);
+      FD_ZERO (&es);
+      curl_multi_perform (multi, &running);
+      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+      if (mret != CURLM_OK)
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 2048;
+        }
+      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 4096;
+        }
+      tv.tv_sec = 0;
+      tv.tv_usec = 1000;
+      select (max + 1, &rs, &ws, &es, &tv);
+      curl_multi_perform (multi, &running);
+      if (running == 0)
+        {
+          msg = curl_multi_info_read (multi, &running);
+          if (msg == NULL)
+            break;
+          if (msg->msg == CURLMSG_DONE)
+            {
+              if (msg->data.result != CURLE_OK)
+                printf ("%s failed at %s:%d: `%s'\n",
+                        "curl_multi_perform",
+                        __FILE__,
+                        __LINE__, curl_easy_strerror (msg->data.result));
+              curl_multi_remove_handle (multi, c);
+              curl_multi_cleanup (multi);
+              curl_easy_cleanup (c);
+              c = NULL;
+              multi = NULL;
+            }
+        }
+      MHD_run (d);
+    }
+  if (multi != NULL)
+    {
+      curl_multi_remove_handle (multi, c);
+      curl_easy_cleanup (c);
+      curl_multi_cleanup (multi);
+    }
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 8192;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 16384;
+  return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+
+  oneone = NULL != strstr (argv[0], "11");
+  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    return 2;
+  errorCount += testInternalPut ();
+  if (0)
+    {
+      errorCount += testMultithreadedPut ();
+      errorCount += testExternalPut ();
+    }
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  curl_global_cleanup ();
+  return errorCount != 0;       /* 0 == pass */
+}

Copied: libmicrohttpd/src/testcurl/daemontest_put_chunked.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest_put_chunked.c)
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_put_chunked.c                         
(rev 0)
+++ libmicrohttpd/src/testcurl/daemontest_put_chunked.c 2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -0,0 +1,383 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_put_chunked.c
+ * @brief Testcase for libmicrohttpd PUT operations with chunked encoding
+ *        for the upload data
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+};
+
+static size_t
+putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
+{
+  unsigned int *pos = ptr;
+  unsigned int wrt;
+
+  wrt = size * nmemb;
+  if (wrt > 8 - (*pos))
+    wrt = 8 - (*pos);
+  if (wrt > 4)
+    wrt = 4;                    /* only send half at first => force multiple 
chunks! */
+  memcpy (stream, &("Hello123"[*pos]), wrt);
+  (*pos) += wrt;
+  return wrt;
+}
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+  struct CBC *cbc = ctx;
+
+  if (cbc->pos + size * nmemb > cbc->size)
+    return 0;                   /* overflow */
+  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+  cbc->pos += size * nmemb;
+  return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, unsigned int *upload_data_size,
+          void **unused)
+{
+  int *done = cls;
+  struct MHD_Response *response;
+  int ret;
+  int have;
+
+  if (0 != strcmp ("PUT", method))
+    return MHD_NO;              /* unexpected method */
+  if ((*done) < 8)
+    {
+      have = *upload_data_size;
+      if (have + *done > 8)
+        {
+          printf ("Invalid upload data `%8s'!\n", upload_data);
+          return MHD_NO;
+        }
+      if (0 == memcmp (upload_data, &"Hello123"[*done], have))
+        {
+          *done += have;
+          *upload_data_size = 0;
+        }
+      else
+        {
+          printf ("Invalid upload data `%8s'!\n", upload_data);
+          return MHD_NO;
+        }
+#if 0
+      fprintf (stderr, "Not ready for response: %u/%u\n", *done, 8);
+#endif
+      return MHD_YES;
+    }
+  response = MHD_create_response_from_data (strlen (url),
+                                            (void *) url, MHD_NO, MHD_YES);
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+
+static int
+testInternalPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        11080,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11080/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  /*
+     // by not giving the file size, we force chunking!
+     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+   */
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 2;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 4;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 8;
+  return 0;
+}
+
+static int
+testMultithreadedPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+                        11081,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  /*
+     // by not giving the file size, we force chunking!
+     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+   */
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 64;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+
+  return 0;
+}
+
+
+static int
+testExternalPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLM *multi;
+  CURLMcode mret;
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int max;
+  int running;
+  struct CURLMsg *msg;
+  time_t start;
+  struct timeval tv;
+  unsigned int pos = 0;
+  int done_flag = 0;
+
+  multi = NULL;
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_DEBUG,
+                        11082,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 256;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11082/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  /*
+     // by not giving the file size, we force chunking!
+     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+   */
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+  multi = curl_multi_init ();
+  if (multi == NULL)
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 512;
+    }
+  mret = curl_multi_add_handle (multi, c);
+  if (mret != CURLM_OK)
+    {
+      curl_multi_cleanup (multi);
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 1024;
+    }
+  start = time (NULL);
+  while ((time (NULL) - start < 5) && (multi != NULL))
+    {
+      max = 0;
+      FD_ZERO (&rs);
+      FD_ZERO (&ws);
+      FD_ZERO (&es);
+      curl_multi_perform (multi, &running);
+      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+      if (mret != CURLM_OK)
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 2048;
+        }
+      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 4096;
+        }
+      tv.tv_sec = 0;
+      tv.tv_usec = 1000;
+      select (max + 1, &rs, &ws, &es, &tv);
+      curl_multi_perform (multi, &running);
+      if (running == 0)
+        {
+          msg = curl_multi_info_read (multi, &running);
+          if (msg == NULL)
+            break;
+          if (msg->msg == CURLMSG_DONE)
+            {
+              if (msg->data.result != CURLE_OK)
+                printf ("%s failed at %s:%d: `%s'\n",
+                        "curl_multi_perform",
+                        __FILE__,
+                        __LINE__, curl_easy_strerror (msg->data.result));
+              curl_multi_remove_handle (multi, c);
+              curl_multi_cleanup (multi);
+              curl_easy_cleanup (c);
+              c = NULL;
+              multi = NULL;
+            }
+        }
+      MHD_run (d);
+    }
+  if (multi != NULL)
+    {
+      curl_multi_remove_handle (multi, c);
+      curl_easy_cleanup (c);
+      curl_multi_cleanup (multi);
+    }
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 8192;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 16384;
+  return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+
+  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    return 2;
+  errorCount += testInternalPut ();
+  if (0)
+    {
+      errorCount += testMultithreadedPut ();
+      errorCount += testExternalPut ();
+    }
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  curl_global_cleanup ();
+  return errorCount != 0;       /* 0 == pass */
+}

Added: libmicrohttpd/src/testzzuf/Makefile.am
===================================================================
--- libmicrohttpd/src/testzzuf/Makefile.am                              (rev 0)
+++ libmicrohttpd/src/testzzuf/Makefile.am      2008-04-12 20:45:58 UTC (rev 
6676)
@@ -0,0 +1,125 @@
+SUBDIRS  = .
+
+INCLUDES = -I$(top_srcdir)/src/include
+
+check_PROGRAMS = \
+  postprocessor_test \
+  daemontest \
+  daemontest_get \
+  daemontest_post \
+  daemontest_postform \
+  daemontest_post_loop \
+  daemontest_put \
+  daemontest_large_put \
+  daemontest_get11 \
+  daemontest_post11 \
+  daemontest_postform11 \
+  daemontest_post_loop11 \
+  daemontest_put11 \
+  daemontest_large_put11 \
+  daemontest_long_header \
+  daemontest_get_chunked \
+  daemontest_put_chunked 
+
+TESTS = $(check_PROGRAMS)
+
+daemontest_SOURCES = \
+  daemontest.c
+daemontest_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la 
+
+postprocessor_test_SOURCES = \
+  postprocessor_test.c
+postprocessor_test_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la 
+
+daemontest_get_SOURCES = \
+  daemontest_get.c
+daemontest_get_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_get_chunked_SOURCES = \
+  daemontest_get_chunked.c
+daemontest_get_chunked_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_post_SOURCES = \
+  daemontest_post.c
+daemontest_post_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_postform_SOURCES = \
+  daemontest_postform.c
+daemontest_postform_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_post_loop_SOURCES = \
+  daemontest_post_loop.c
+daemontest_post_loop_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_put_SOURCES = \
+  daemontest_put.c
+daemontest_put_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_put_chunked_SOURCES = \
+  daemontest_put_chunked.c
+daemontest_put_chunked_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_get11_SOURCES = \
+  daemontest_get.c
+daemontest_get11_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_post11_SOURCES = \
+  daemontest_post.c
+daemontest_post11_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_postform11_SOURCES = \
+  daemontest_postform.c
+daemontest_postform11_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_post_loop11_SOURCES = \
+  daemontest_post_loop.c
+daemontest_post_loop11_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_put11_SOURCES = \
+  daemontest_put.c
+daemontest_put11_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+
+daemontest_large_put_SOURCES = \
+  daemontest_large_put.c
+daemontest_large_put_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_large_put11_SOURCES = \
+  daemontest_large_put.c
+daemontest_large_put11_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 
+
+daemontest_long_header_SOURCES = \
+  daemontest_long_header.c
+daemontest_long_header_LDADD = \
+  $(top_builddir)/src/daemon/libmicrohttpd.la \
+  @LIBCURL@ 

Copied: libmicrohttpd/src/testzzuf/daemontest.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest.c)
===================================================================
--- libmicrohttpd/src/testzzuf/daemontest.c                             (rev 0)
+++ libmicrohttpd/src/testzzuf/daemontest.c     2008-04-12 20:45:58 UTC (rev 
6676)
@@ -0,0 +1,163 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest.c
+ * @brief  Testcase for libmicrohttpd starts and stops
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include "microhttpd.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+
+static int
+testStartError ()
+{
+  struct MHD_Daemon *d;
+
+  d = MHD_start_daemon (MHD_USE_DEBUG, 0, NULL, NULL, NULL, NULL);
+  if (d != NULL)
+    return 1;
+  return 0;
+}
+
+static int
+apc_nothing (void *cls, const struct sockaddr *addr, socklen_t addrlen)
+{
+  return MHD_NO;
+}
+
+static int
+apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen)
+{
+  return MHD_YES;
+}
+
+static int
+ahc_nothing (void *cls,
+             struct MHD_Connection *connection,
+             const char *url,
+             const char *method,
+             const char *version,
+             const char *upload_data, unsigned int *upload_data_size,
+             void **unused)
+{
+  return MHD_NO;
+}
+
+static int
+testStartStop ()
+{
+  struct MHD_Daemon *d;
+
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1080,
+                        &apc_nothing,
+                        NULL, &ahc_nothing, NULL, MHD_OPTION_END);
+  if (d == NULL)
+    return 2;
+  MHD_stop_daemon (d);
+  return 0;
+}
+
+static int
+testExternalRun ()
+{
+  struct MHD_Daemon *d;
+  fd_set rs;
+  int maxfd;
+  int i;
+
+  d = MHD_start_daemon (MHD_USE_DEBUG,
+                        1081,
+                        &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
+
+  if (d == NULL)
+    return 4;
+  i = 0;
+  while (i < 15)
+    {
+      maxfd = 0;
+      FD_ZERO (&rs);
+      MHD_get_fdset (d, &rs, &rs, &rs, &maxfd);
+      if (MHD_run (d) == MHD_NO)
+        {
+          MHD_stop_daemon (d);
+          return 8;
+        }
+      i++;
+    }
+  MHD_stop_daemon (d);
+  return 0;
+}
+
+static int
+testThread ()
+{
+  struct MHD_Daemon *d;
+  d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY,
+                        1082,
+                        &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
+
+  if (d == NULL)
+    return 16;
+  if (MHD_run (d) != MHD_NO)
+    return 32;
+  MHD_stop_daemon (d);
+  return 0;
+}
+
+static int
+testMultithread ()
+{
+  struct MHD_Daemon *d;
+  d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION,
+                        1083,
+                        &apc_all, NULL, &ahc_nothing, NULL, MHD_OPTION_END);
+
+  if (d == NULL)
+    return 64;
+  if (MHD_run (d) != MHD_NO)
+    return 128;
+  MHD_stop_daemon (d);
+  return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+  errorCount += testStartError ();
+  errorCount += testStartStop ();
+  errorCount += testExternalRun ();
+  errorCount += testThread ();
+  errorCount += testMultithread ();
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  return errorCount != 0;       /* 0 == pass */
+}

Copied: libmicrohttpd/src/testzzuf/daemontest_get.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest_get.c)
===================================================================
--- libmicrohttpd/src/testzzuf/daemontest_get.c                         (rev 0)
+++ libmicrohttpd/src/testzzuf/daemontest_get.c 2008-04-12 20:45:58 UTC (rev 
6676)
@@ -0,0 +1,330 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_get.c
+ * @brief  Testcase for libmicrohttpd GET operations
+ *         TODO: test parsing of query
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+  struct CBC *cbc = ctx;
+
+  if (cbc->pos + size * nmemb > cbc->size)
+    return 0;                   /* overflow */
+  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+  cbc->pos += size * nmemb;
+  return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, unsigned int *upload_data_size,
+          void **unused)
+{
+  static int ptr;
+  const char *me = cls;
+  struct MHD_Response *response;
+  int ret;
+
+  if (0 != strcmp (me, method))
+    return MHD_NO;              /* unexpected method */
+  if (&ptr != *unused)
+    {
+      *unused = &ptr;
+      return MHD_YES;
+    }
+  *unused = NULL;
+  response = MHD_create_response_from_data (strlen (url),
+                                            (void *) url, MHD_NO, MHD_YES);
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  MHD_destroy_response (response);
+  if (ret == MHD_NO)
+    abort ();
+  return ret;
+}
+
+
+static int
+testInternalGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11080/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 2;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 4;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 8;
+  return 0;
+}
+
+static int
+testMultithreadedGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+                        1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 64;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+  return 0;
+}
+
+
+static int
+testExternalGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLM *multi;
+  CURLMcode mret;
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int max;
+  int running;
+  struct CURLMsg *msg;
+  time_t start;
+  struct timeval tv;
+
+  multi = NULL;
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_DEBUG,
+                        1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+  if (d == NULL)
+    return 256;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+  multi = curl_multi_init ();
+  if (multi == NULL)
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 512;
+    }
+  mret = curl_multi_add_handle (multi, c);
+  if (mret != CURLM_OK)
+    {
+      curl_multi_cleanup (multi);
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 1024;
+    }
+  start = time (NULL);
+  while ((time (NULL) - start < 5) && (multi != NULL))
+    {
+      max = 0;
+      FD_ZERO (&rs);
+      FD_ZERO (&ws);
+      FD_ZERO (&es);
+      curl_multi_perform (multi, &running);
+      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+      if (mret != CURLM_OK)
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 2048;
+        }
+      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 4096;
+        }
+      tv.tv_sec = 0;
+      tv.tv_usec = 1000;
+      select (max + 1, &rs, &ws, &es, &tv);
+      curl_multi_perform (multi, &running);
+      if (running == 0)
+        {
+          msg = curl_multi_info_read (multi, &running);
+          if (msg == NULL)
+            break;
+          if (msg->msg == CURLMSG_DONE)
+            {
+              if (msg->data.result != CURLE_OK)
+                printf ("%s failed at %s:%d: `%s'\n",
+                        "curl_multi_perform",
+                        __FILE__,
+                        __LINE__, curl_easy_strerror (msg->data.result));
+              curl_multi_remove_handle (multi, c);
+              curl_multi_cleanup (multi);
+              curl_easy_cleanup (c);
+              c = NULL;
+              multi = NULL;
+            }
+        }
+      MHD_run (d);
+    }
+  if (multi != NULL)
+    {
+      curl_multi_remove_handle (multi, c);
+      curl_easy_cleanup (c);
+      curl_multi_cleanup (multi);
+    }
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 8192;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 16384;
+  return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+
+  oneone = NULL != strstr (argv[0], "11");
+  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    return 2;
+  errorCount += testInternalGet ();
+  errorCount += testMultithreadedGet ();
+  errorCount += testExternalGet ();
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  curl_global_cleanup ();
+  return errorCount != 0;       /* 0 == pass */
+}

Copied: libmicrohttpd/src/testzzuf/daemontest_get_chunked.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest_get_chunked.c)
===================================================================
--- libmicrohttpd/src/testzzuf/daemontest_get_chunked.c                         
(rev 0)
+++ libmicrohttpd/src/testzzuf/daemontest_get_chunked.c 2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -0,0 +1,364 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_get_chunked.c
+ * @brief  Testcase for libmicrohttpd GET operations with chunked content 
encoding
+ *         TODO:
+ *         - how to test that chunking was actually used?
+ *         - use CURLOPT_HEADERFUNCTION to validate
+ *           footer was sent
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+  struct CBC *cbc = ctx;
+
+  if (cbc->pos + size * nmemb > cbc->size)
+    return 0;                   /* overflow */
+  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+  cbc->pos += size * nmemb;
+  return size * nmemb;
+}
+
+/**
+ * MHD content reader callback that returns
+ * data in chunks.
+ */
+static int
+crc (void *cls, size_t pos, char *buf, int max)
+{
+  struct MHD_Response **responseptr = cls;
+
+  if (pos == 128 * 10)
+    {
+      MHD_add_response_header (*responseptr, "Footer", "working");
+      return -1;                /* end of stream */
+    }
+  if (max < 128)
+    abort ();                   /* should not happen in this testcase... */
+  memset (buf, 'A' + (pos / 128), 128);
+  return 128;
+}
+
+/**
+ * Dummy function that does nothing.
+ */
+static void
+crcf (void *ptr)
+{
+  free (ptr);
+}
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, unsigned int *upload_data_size, void **ptr)
+{
+  static int aptr;
+  const char *me = cls;
+  struct MHD_Response *response;
+  struct MHD_Response **responseptr;
+  int ret;
+
+  if (0 != strcmp (me, method))
+    return MHD_NO;              /* unexpected method */
+  if (&aptr != *ptr)
+    {
+      /* do never respond on first call */
+      *ptr = &aptr;
+      return MHD_YES;
+    }
+  responseptr = malloc (sizeof (struct MHD_Response *));
+  response = MHD_create_response_from_callback (-1,
+                                                1024,
+                                                &crc, responseptr, &crcf);
+  *responseptr = response;
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+static int
+validate (struct CBC cbc, int ebase)
+{
+  int i;
+  char buf[128];
+
+  if (cbc.pos != 128 * 10)
+    return ebase;
+
+  for (i = 0; i < 10; i++)
+    {
+      memset (buf, 'A' + i, 128);
+      if (0 != memcmp (buf, &cbc.buf[i * 128], 128))
+        {
+          fprintf (stderr,
+                   "Got  `%.*s'\nWant `%.*s'\n",
+                   128, buf, 128, &cbc.buf[i * 128]);
+          return ebase * 2;
+        }
+    }
+  return 0;
+}
+
+static int
+testInternalGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 2;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  return validate (cbc, 4);
+}
+
+static int
+testMultithreadedGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+                        1081, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  return validate (cbc, 64);
+}
+
+
+static int
+testExternalGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLM *multi;
+  CURLMcode mret;
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int max;
+  int running;
+  struct CURLMsg *msg;
+  time_t start;
+  struct timeval tv;
+
+  multi = NULL;
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_DEBUG,
+                        1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+  if (d == NULL)
+    return 256;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 5L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+  multi = curl_multi_init ();
+  if (multi == NULL)
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 512;
+    }
+  mret = curl_multi_add_handle (multi, c);
+  if (mret != CURLM_OK)
+    {
+      curl_multi_cleanup (multi);
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 1024;
+    }
+  start = time (NULL);
+  while ((time (NULL) - start < 5) && (multi != NULL))
+    {
+      max = 0;
+      FD_ZERO (&rs);
+      FD_ZERO (&ws);
+      FD_ZERO (&es);
+      curl_multi_perform (multi, &running);
+      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+      if (mret != CURLM_OK)
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 2048;
+        }
+      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 4096;
+        }
+      tv.tv_sec = 0;
+      tv.tv_usec = 1000;
+      select (max + 1, &rs, &ws, &es, &tv);
+      curl_multi_perform (multi, &running);
+      if (running == 0)
+        {
+          msg = curl_multi_info_read (multi, &running);
+          if (msg == NULL)
+            break;
+          if (msg->msg == CURLMSG_DONE)
+            {
+              if (msg->data.result != CURLE_OK)
+                printf ("%s failed at %s:%d: `%s'\n",
+                        "curl_multi_perform",
+                        __FILE__,
+                        __LINE__, curl_easy_strerror (msg->data.result));
+              curl_multi_remove_handle (multi, c);
+              curl_multi_cleanup (multi);
+              curl_easy_cleanup (c);
+              c = NULL;
+              multi = NULL;
+            }
+        }
+      MHD_run (d);
+    }
+  if (multi != NULL)
+    {
+      curl_multi_remove_handle (multi, c);
+      curl_easy_cleanup (c);
+      curl_multi_cleanup (multi);
+    }
+  MHD_stop_daemon (d);
+  return validate (cbc, 8192);
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+
+  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    return 2;
+  errorCount += testInternalGet ();
+  if (0)
+    {
+      errorCount += testMultithreadedGet ();
+      errorCount += testExternalGet ();
+    }
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  curl_global_cleanup ();
+  return errorCount != 0;       /* 0 == pass */
+}

Copied: libmicrohttpd/src/testzzuf/daemontest_large_put.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest_large_put.c)
===================================================================
--- libmicrohttpd/src/testzzuf/daemontest_large_put.c                           
(rev 0)
+++ libmicrohttpd/src/testzzuf/daemontest_large_put.c   2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -0,0 +1,404 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_put.c
+ * @brief  Testcase for libmicrohttpd PUT operations
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+/**
+ * Do not make this much larger since we will hit the
+ * MHD default buffer limit and the test code is not
+ * written for incremental upload processing...
+ */
+#define PUT_SIZE (512 * 1024)
+
+static char *put_buffer;
+
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+};
+
+static size_t
+putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
+{
+  unsigned int *pos = ptr;
+  unsigned int wrt;
+
+  wrt = size * nmemb;
+  if (wrt > PUT_SIZE - (*pos))
+    wrt = PUT_SIZE - (*pos);
+  memcpy (stream, &put_buffer[*pos], wrt);
+  (*pos) += wrt;
+  return wrt;
+}
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+  struct CBC *cbc = ctx;
+
+  if (cbc->pos + size * nmemb > cbc->size)
+    return 0;                   /* overflow */
+  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+  cbc->pos += size * nmemb;
+  return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, unsigned int *upload_data_size,
+          void **unused)
+{
+  int *done = cls;
+  struct MHD_Response *response;
+  int ret;
+
+  if (0 != strcmp ("PUT", method))
+    return MHD_NO;              /* unexpected method */
+  if ((*done) == 0)
+    {
+      if (*upload_data_size != PUT_SIZE)
+        {
+#if 0
+          fprintf (stderr,
+                   "Waiting for more data (%u/%u)...\n",
+                   *upload_data_size, PUT_SIZE);
+#endif
+          return MHD_YES;       /* not yet ready */
+        }
+      if (0 == memcmp (upload_data, put_buffer, PUT_SIZE))
+        {
+          *upload_data_size = 0;
+        }
+      else
+        {
+          printf ("Invalid upload data!\n");
+          return MHD_NO;
+        }
+      *done = 1;
+      return MHD_YES;
+    }
+  response = MHD_create_response_from_data (strlen (url),
+                                            (void *) url, MHD_NO, MHD_YES);
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+
+static int
+testInternalPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
+  char buf[2048];
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1080,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 2;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 4;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 8;
+  return 0;
+}
+
+static int
+testMultithreadedPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
+  char buf[2048];
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+                        1081,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    {
+      free (cbc.buf);
+      return 16;
+    }
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    {
+      fprintf (stderr, "Got invalid response `%.*s'\n", cbc.pos, cbc.buf);
+      return 64;
+    }
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+  return 0;
+}
+
+
+static int
+testExternalPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  struct CBC cbc;
+  CURLM *multi;
+  CURLMcode mret;
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int max;
+  int running;
+  struct CURLMsg *msg;
+  time_t start;
+  struct timeval tv;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  char buf[2048];
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  multi = NULL;
+  d = MHD_start_daemon (MHD_USE_DEBUG,
+                        1082,
+                        NULL, NULL, &ahc_echo, &done_flag,
+                        MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+                        PUT_SIZE * 4, MHD_OPTION_END);
+  if (d == NULL)
+    return 256;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+  multi = curl_multi_init ();
+  if (multi == NULL)
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 512;
+    }
+  mret = curl_multi_add_handle (multi, c);
+  if (mret != CURLM_OK)
+    {
+      curl_multi_cleanup (multi);
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 1024;
+    }
+  start = time (NULL);
+  while ((time (NULL) - start < 5) && (multi != NULL))
+    {
+      max = 0;
+      FD_ZERO (&rs);
+      FD_ZERO (&ws);
+      FD_ZERO (&es);
+      curl_multi_perform (multi, &running);
+      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+      if (mret != CURLM_OK)
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 2048;
+        }
+      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 4096;
+        }
+      tv.tv_sec = 0;
+      tv.tv_usec = 1000;
+      select (max + 1, &rs, &ws, &es, &tv);
+      curl_multi_perform (multi, &running);
+      if (running == 0)
+        {
+          msg = curl_multi_info_read (multi, &running);
+          if (msg == NULL)
+            break;
+          if (msg->msg == CURLMSG_DONE)
+            {
+              if (msg->data.result != CURLE_OK)
+                printf ("%s failed at %s:%d: `%s'\n",
+                        "curl_multi_perform",
+                        __FILE__,
+                        __LINE__, curl_easy_strerror (msg->data.result));
+              curl_multi_remove_handle (multi, c);
+              curl_multi_cleanup (multi);
+              curl_easy_cleanup (c);
+              c = NULL;
+              multi = NULL;
+            }
+        }
+      MHD_run (d);
+    }
+  if (multi != NULL)
+    {
+      curl_multi_remove_handle (multi, c);
+      curl_easy_cleanup (c);
+      curl_multi_cleanup (multi);
+    }
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    {
+      fprintf (stderr, "Got invalid response `%.*s'\n", cbc.pos, cbc.buf);
+      return 8192;
+    }
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 16384;
+  return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+
+  oneone = NULL != strstr (argv[0], "11");
+  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    return 2;
+  put_buffer = malloc (PUT_SIZE);
+  memset (put_buffer, 1, PUT_SIZE);
+  if (0)
+    {
+      errorCount += testInternalPut ();
+      errorCount += testMultithreadedPut ();
+    }
+  errorCount += testExternalPut ();
+  free (put_buffer);
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  curl_global_cleanup ();
+  return errorCount != 0;       /* 0 == pass */
+}

Copied: libmicrohttpd/src/testzzuf/daemontest_long_header.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest_long_header.c)
===================================================================
--- libmicrohttpd/src/testzzuf/daemontest_long_header.c                         
(rev 0)
+++ libmicrohttpd/src/testzzuf/daemontest_long_header.c 2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -0,0 +1,240 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_long_header.c
+ * @brief  Testcase for libmicrohttpd handling of very long headers
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+/**
+ * We will set the memory available per connection to
+ * half of this value, so the actual value does not have
+ * to be big at all...
+ */
+#define VERY_LONG (1024*10)
+
+static int oneone;
+
+static int
+apc_all (void *cls, const struct sockaddr *addr, socklen_t addrlen)
+{
+  return MHD_YES;
+}
+
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+};
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+  return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, unsigned int *upload_data_size,
+          void **unused)
+{
+  const char *me = cls;
+  struct MHD_Response *response;
+  int ret;
+
+  if (0 != strcmp (me, method))
+    return MHD_NO;              /* unexpected method */
+  response = MHD_create_response_from_data (strlen (url),
+                                            (void *) url, MHD_NO, MHD_YES);
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+
+static int
+testLongUrlGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  char *url;
+  long code;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+                        1080,
+                        &apc_all,
+                        NULL,
+                        &ahc_echo,
+                        "GET",
+                        MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+                        VERY_LONG / 2, MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  c = curl_easy_init ();
+  url = malloc (VERY_LONG);
+  memset (url, 'a', VERY_LONG);
+  url[VERY_LONG - 1] = '\0';
+  memcpy (url, "http://localhost:1080/";, strlen ("http://localhost:1080/";));
+  curl_easy_setopt (c, CURLOPT_URL, url);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK == curl_easy_perform (c))
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      free (url);
+      return 2;
+    }
+  if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code))
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      free (url);
+      return 4;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  free (url);
+  if (code != MHD_HTTP_REQUEST_URI_TOO_LONG)
+    return 8;
+  return 0;
+}
+
+
+static int
+testLongHeaderGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  char *url;
+  long code;
+  struct curl_slist *header = NULL;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ ,
+                        1080,
+                        &apc_all,
+                        NULL,
+                        &ahc_echo,
+                        "GET",
+                        MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+                        VERY_LONG / 2, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  url = malloc (VERY_LONG);
+  memset (url, 'a', VERY_LONG);
+  url[VERY_LONG - 1] = '\0';
+  url[VERY_LONG / 2] = ':';
+  url[VERY_LONG / 2 + 1] = ':';
+  header = curl_slist_append (header, url);
+
+  curl_easy_setopt (c, CURLOPT_HTTPHEADER, header);
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK == curl_easy_perform (c))
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      curl_slist_free_all (header);
+      free (url);
+      return 32;
+    }
+  if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code))
+    {
+      curl_slist_free_all (header);
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      free (url);
+      return 64;
+    }
+  curl_slist_free_all (header);
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  free (url);
+  if (code != MHD_HTTP_REQUEST_ENTITY_TOO_LARGE)
+    return 128;
+  return 0;
+}
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+
+  oneone = NULL != strstr (argv[0], "11");
+  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    return 2;
+  errorCount += testLongUrlGet ();
+  errorCount += testLongHeaderGet ();
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  curl_global_cleanup ();
+  return errorCount != 0;       /* 0 == pass */
+}

Copied: libmicrohttpd/src/testzzuf/daemontest_put.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest_put.c)
===================================================================
--- libmicrohttpd/src/testzzuf/daemontest_put.c                         (rev 0)
+++ libmicrohttpd/src/testzzuf/daemontest_put.c 2008-04-12 20:45:58 UTC (rev 
6676)
@@ -0,0 +1,375 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_put.c
+ * @brief  Testcase for libmicrohttpd PUT operations
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+static int oneone;
+
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+};
+
+static size_t
+putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
+{
+  unsigned int *pos = ptr;
+  unsigned int wrt;
+
+  wrt = size * nmemb;
+  if (wrt > 8 - (*pos))
+    wrt = 8 - (*pos);
+  memcpy (stream, &("Hello123"[*pos]), wrt);
+  (*pos) += wrt;
+  return wrt;
+}
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+  struct CBC *cbc = ctx;
+
+  if (cbc->pos + size * nmemb > cbc->size)
+    return 0;                   /* overflow */
+  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+  cbc->pos += size * nmemb;
+  return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, unsigned int *upload_data_size,
+          void **unused)
+{
+  int *done = cls;
+  struct MHD_Response *response;
+  int ret;
+
+  if (0 != strcmp ("PUT", method))
+    return MHD_NO;              /* unexpected method */
+  if ((*done) == 0)
+    {
+      if (*upload_data_size != 8)
+        return MHD_YES;         /* not yet ready */
+      if (0 == memcmp (upload_data, "Hello123", 8))
+        {
+          *upload_data_size = 0;
+        }
+      else
+        {
+          printf ("Invalid upload data `%8s'!\n", upload_data);
+          return MHD_NO;
+        }
+      *done = 1;
+      return MHD_YES;
+    }
+  response = MHD_create_response_from_data (strlen (url),
+                                            (void *) url, MHD_NO, MHD_YES);
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+
+static int
+testInternalPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1080,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 2;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 4;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 8;
+  return 0;
+}
+
+static int
+testMultithreadedPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+                        1081,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 64;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+
+  return 0;
+}
+
+
+static int
+testExternalPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLM *multi;
+  CURLMcode mret;
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int max;
+  int running;
+  struct CURLMsg *msg;
+  time_t start;
+  struct timeval tv;
+  unsigned int pos = 0;
+  int done_flag = 0;
+
+  multi = NULL;
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_DEBUG,
+                        1082,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 256;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1082/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+  multi = curl_multi_init ();
+  if (multi == NULL)
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 512;
+    }
+  mret = curl_multi_add_handle (multi, c);
+  if (mret != CURLM_OK)
+    {
+      curl_multi_cleanup (multi);
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 1024;
+    }
+  start = time (NULL);
+  while ((time (NULL) - start < 5) && (multi != NULL))
+    {
+      max = 0;
+      FD_ZERO (&rs);
+      FD_ZERO (&ws);
+      FD_ZERO (&es);
+      curl_multi_perform (multi, &running);
+      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+      if (mret != CURLM_OK)
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 2048;
+        }
+      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 4096;
+        }
+      tv.tv_sec = 0;
+      tv.tv_usec = 1000;
+      select (max + 1, &rs, &ws, &es, &tv);
+      curl_multi_perform (multi, &running);
+      if (running == 0)
+        {
+          msg = curl_multi_info_read (multi, &running);
+          if (msg == NULL)
+            break;
+          if (msg->msg == CURLMSG_DONE)
+            {
+              if (msg->data.result != CURLE_OK)
+                printf ("%s failed at %s:%d: `%s'\n",
+                        "curl_multi_perform",
+                        __FILE__,
+                        __LINE__, curl_easy_strerror (msg->data.result));
+              curl_multi_remove_handle (multi, c);
+              curl_multi_cleanup (multi);
+              curl_easy_cleanup (c);
+              c = NULL;
+              multi = NULL;
+            }
+        }
+      MHD_run (d);
+    }
+  if (multi != NULL)
+    {
+      curl_multi_remove_handle (multi, c);
+      curl_easy_cleanup (c);
+      curl_multi_cleanup (multi);
+    }
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 8192;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 16384;
+  return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+
+  oneone = NULL != strstr (argv[0], "11");
+  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    return 2;
+  errorCount += testInternalPut ();
+  if (0)
+    {
+      errorCount += testMultithreadedPut ();
+      errorCount += testExternalPut ();
+    }
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  curl_global_cleanup ();
+  return errorCount != 0;       /* 0 == pass */
+}

Copied: libmicrohttpd/src/testzzuf/daemontest_put_chunked.c (from rev 6670, 
libmicrohttpd/src/daemon/daemontest_put_chunked.c)
===================================================================
--- libmicrohttpd/src/testzzuf/daemontest_put_chunked.c                         
(rev 0)
+++ libmicrohttpd/src/testzzuf/daemontest_put_chunked.c 2008-04-12 20:45:58 UTC 
(rev 6676)
@@ -0,0 +1,383 @@
+/*
+     This file is part of libmicrohttpd
+     (C) 2007 Christian Grothoff
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file daemontest_put_chunked.c
+ * @brief Testcase for libmicrohttpd PUT operations with chunked encoding
+ *        for the upload data
+ * @author Christian Grothoff
+ */
+
+#include "config.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifndef WINDOWS
+#include <unistd.h>
+#endif
+
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+};
+
+static size_t
+putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
+{
+  unsigned int *pos = ptr;
+  unsigned int wrt;
+
+  wrt = size * nmemb;
+  if (wrt > 8 - (*pos))
+    wrt = 8 - (*pos);
+  if (wrt > 4)
+    wrt = 4;                    /* only send half at first => force multiple 
chunks! */
+  memcpy (stream, &("Hello123"[*pos]), wrt);
+  (*pos) += wrt;
+  return wrt;
+}
+
+static size_t
+copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
+{
+  struct CBC *cbc = ctx;
+
+  if (cbc->pos + size * nmemb > cbc->size)
+    return 0;                   /* overflow */
+  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
+  cbc->pos += size * nmemb;
+  return size * nmemb;
+}
+
+static int
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, unsigned int *upload_data_size,
+          void **unused)
+{
+  int *done = cls;
+  struct MHD_Response *response;
+  int ret;
+  int have;
+
+  if (0 != strcmp ("PUT", method))
+    return MHD_NO;              /* unexpected method */
+  if ((*done) < 8)
+    {
+      have = *upload_data_size;
+      if (have + *done > 8)
+        {
+          printf ("Invalid upload data `%8s'!\n", upload_data);
+          return MHD_NO;
+        }
+      if (0 == memcmp (upload_data, &"Hello123"[*done], have))
+        {
+          *done += have;
+          *upload_data_size = 0;
+        }
+      else
+        {
+          printf ("Invalid upload data `%8s'!\n", upload_data);
+          return MHD_NO;
+        }
+#if 0
+      fprintf (stderr, "Not ready for response: %u/%u\n", *done, 8);
+#endif
+      return MHD_YES;
+    }
+  response = MHD_create_response_from_data (strlen (url),
+                                            (void *) url, MHD_NO, MHD_YES);
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+
+static int
+testInternalPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        11080,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 1;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11080/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  /*
+     // by not giving the file size, we force chunking!
+     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+   */
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 2;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 4;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 8;
+  return 0;
+}
+
+static int
+testMultithreadedPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+                        11081,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  /*
+     // by not giving the file size, we force chunking!
+     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+   */
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 64;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+
+  return 0;
+}
+
+
+static int
+testExternalPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLM *multi;
+  CURLMcode mret;
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int max;
+  int running;
+  struct CURLMsg *msg;
+  time_t start;
+  struct timeval tv;
+  unsigned int pos = 0;
+  int done_flag = 0;
+
+  multi = NULL;
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_DEBUG,
+                        11082,
+                        NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END);
+  if (d == NULL)
+    return 256;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11082/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  /*
+     // by not giving the file size, we force chunking!
+     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+   */
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+
+  multi = curl_multi_init ();
+  if (multi == NULL)
+    {
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 512;
+    }
+  mret = curl_multi_add_handle (multi, c);
+  if (mret != CURLM_OK)
+    {
+      curl_multi_cleanup (multi);
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 1024;
+    }
+  start = time (NULL);
+  while ((time (NULL) - start < 5) && (multi != NULL))
+    {
+      max = 0;
+      FD_ZERO (&rs);
+      FD_ZERO (&ws);
+      FD_ZERO (&es);
+      curl_multi_perform (multi, &running);
+      mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+      if (mret != CURLM_OK)
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 2048;
+        }
+      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
+        {
+          curl_multi_remove_handle (multi, c);
+          curl_multi_cleanup (multi);
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 4096;
+        }
+      tv.tv_sec = 0;
+      tv.tv_usec = 1000;
+      select (max + 1, &rs, &ws, &es, &tv);
+      curl_multi_perform (multi, &running);
+      if (running == 0)
+        {
+          msg = curl_multi_info_read (multi, &running);
+          if (msg == NULL)
+            break;
+          if (msg->msg == CURLMSG_DONE)
+            {
+              if (msg->data.result != CURLE_OK)
+                printf ("%s failed at %s:%d: `%s'\n",
+                        "curl_multi_perform",
+                        __FILE__,
+                        __LINE__, curl_easy_strerror (msg->data.result));
+              curl_multi_remove_handle (multi, c);
+              curl_multi_cleanup (multi);
+              curl_easy_cleanup (c);
+              c = NULL;
+              multi = NULL;
+            }
+        }
+      MHD_run (d);
+    }
+  if (multi != NULL)
+    {
+      curl_multi_remove_handle (multi, c);
+      curl_easy_cleanup (c);
+      curl_multi_cleanup (multi);
+    }
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 8192;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 16384;
+  return 0;
+}
+
+
+
+int
+main (int argc, char *const *argv)
+{
+  unsigned int errorCount = 0;
+
+  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    return 2;
+  errorCount += testInternalPut ();
+  if (0)
+    {
+      errorCount += testMultithreadedPut ();
+      errorCount += testExternalPut ();
+    }
+  if (errorCount != 0)
+    fprintf (stderr, "Error (code: %u)\n", errorCount);
+  curl_global_cleanup ();
+  return errorCount != 0;       /* 0 == pass */
+}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]