[Top][All Lists]
[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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
- 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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, ©Buffer);
+ 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 */
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r6676 - in libmicrohttpd: . doc src src/daemon src/examples src/testcurl src/testzzuf,
gnunet <=