summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2010-11-21 17:01:59 +0000
committerPaul Buetow <paul@buetow.org>2010-11-21 17:01:59 +0000
commitb891420946d5269cc326d67555c6aab3db41a01a (patch)
treef6c5e7d6dbf18ec8c0ea9ec0b037251df46b4cbb
parenta537e8323d932125232c305f9573daef89aef0df (diff)
added yhttpd and ycurses trunk versions
-rw-r--r--ycurses/COPYING338
-rw-r--r--ycurses/Makefile69
-rw-r--r--ycurses/README382
-rw-r--r--ycurses/SHORTDESC3
-rw-r--r--ycurses/TODO3
-rwxr-xr-xycurses/configure77
-rw-r--r--ycurses/scripts/README6
-rwxr-xr-xycurses/scripts/astyle.sh14
-rwxr-xr-xycurses/scripts/buildnr.pl26
-rwxr-xr-xycurses/scripts/checkperl.sh13
-rwxr-xr-xycurses/scripts/config.pl144
-rw-r--r--ycurses/scripts/modules/file.pm28
-rwxr-xr-xycurses/scripts/screen.sh3
-rwxr-xr-xycurses/scripts/setglobvals.pl32
-rwxr-xr-xycurses/scripts/stats.pl95
-rwxr-xr-xycurses/scripts/version.sh11
-rw-r--r--ycurses/src/Makefile.in21
-rwxr-xr-xycurses/src/configure330
-rw-r--r--ycurses/src/curses/attributes.cpp80
-rw-r--r--ycurses/src/curses/attributes.h70
-rw-r--r--ycurses/src/curses/color.cpp54
-rw-r--r--ycurses/src/curses/color.h39
-rw-r--r--ycurses/src/curses/coordinate.cpp134
-rw-r--r--ycurses/src/curses/coordinate.h43
-rw-r--r--ycurses/src/curses/coordinate.impl17
-rw-r--r--ycurses/src/curses/curses.cpp86
-rw-r--r--ycurses/src/curses/curses.h55
-rw-r--r--ycurses/src/curses/cursor.cpp32
-rw-r--r--ycurses/src/curses/cursor.h30
-rw-r--r--ycurses/src/curses/dummy.cpp11
-rw-r--r--ycurses/src/curses/dummy.h11
-rw-r--r--ycurses/src/curses/hidden.cpp29
-rw-r--r--ycurses/src/curses/hidden.h21
-rw-r--r--ycurses/src/curses/incl.h8
-rw-r--r--ycurses/src/curses/menu.cpp117
-rw-r--r--ycurses/src/curses/menu.h28
-rw-r--r--ycurses/src/curses/pwindow.cpp99
-rw-r--r--ycurses/src/curses/pwindow.h37
-rw-r--r--ycurses/src/curses/tool.cpp37
-rw-r--r--ycurses/src/curses/tool.h15
-rw-r--r--ycurses/src/curses/window.cpp367
-rw-r--r--ycurses/src/curses/window.h85
-rw-r--r--ycurses/src/curses/ycurses.h6
-rw-r--r--ycurses/src/examples/example1.cpp80
-rw-r--r--ycurses/src/examples/example1.h8
-rw-r--r--ycurses/src/examples/example2.cpp52
-rw-r--r--ycurses/src/examples/example2.h8
-rw-r--r--ycurses/src/examples/example3.cpp45
-rw-r--r--ycurses/src/examples/example3.h8
-rw-r--r--ycurses/src/examples/example4.cpp22
-rw-r--r--ycurses/src/examples/example4.h8
-rw-r--r--ycurses/src/glob.h21
-rw-r--r--ycurses/src/main.cpp110
-rw-r--r--ycurses/src/msgs.h11
-rw-r--r--yhttpd/COPYING338
-rw-r--r--yhttpd/INSTALL1
-rw-r--r--yhttpd/Makefile90
-rw-r--r--yhttpd/README462
-rw-r--r--yhttpd/RELEASES43
-rw-r--r--yhttpd/SHORTDESC2
-rw-r--r--yhttpd/VERSION1
-rwxr-xr-xyhttpd/configure77
-rw-r--r--yhttpd/etc/yhttpd.conf126
-rw-r--r--yhttpd/html/index.html27
-rw-r--r--yhttpd/html/notfound.html12
-rw-r--r--yhttpd/html/style.css48
-rw-r--r--yhttpd/html/test.cgi9
-rw-r--r--yhttpd/log/.keepme0
-rw-r--r--yhttpd/log/access_log41
-rw-r--r--yhttpd/log/system_log114
-rw-r--r--yhttpd/scripts/README6
-rwxr-xr-xyhttpd/scripts/astyle.sh14
-rwxr-xr-xyhttpd/scripts/buildnr.pl26
-rwxr-xr-xyhttpd/scripts/checkperl.sh13
-rwxr-xr-xyhttpd/scripts/config.pl133
-rwxr-xr-xyhttpd/scripts/makedist.sh27
-rw-r--r--yhttpd/scripts/modules/file.pm28
-rwxr-xr-xyhttpd/scripts/screen.sh3
-rwxr-xr-xyhttpd/scripts/setglobvals.pl32
-rwxr-xr-xyhttpd/scripts/stats.pl95
-rwxr-xr-xyhttpd/scripts/version.sh11
-rw-r--r--yhttpd/src/Makefile.in21
-rw-r--r--yhttpd/src/cli/cli.cpp300
-rw-r--r--yhttpd/src/cli/cli.h61
-rw-r--r--yhttpd/src/conf/conf.cpp186
-rw-r--r--yhttpd/src/conf/conf.h29
-rwxr-xr-xyhttpd/src/configure350
-rw-r--r--yhttpd/src/contrib/README5
-rw-r--r--yhttpd/src/contrib/xml/README504
-rw-r--r--yhttpd/src/contrib/xml/tinyxml.cpp1428
-rw-r--r--yhttpd/src/contrib/xml/tinyxml.h1630
-rw-r--r--yhttpd/src/contrib/xml/tinyxmlerror.cpp51
-rw-r--r--yhttpd/src/contrib/xml/tinyxmlparser.cpp1553
-rw-r--r--yhttpd/src/glob.h198
-rw-r--r--yhttpd/src/html.cpp133
-rw-r--r--yhttpd/src/html.h38
-rw-r--r--yhttpd/src/incl.h13
-rw-r--r--yhttpd/src/logd.cpp175
-rw-r--r--yhttpd/src/logd.h37
-rw-r--r--yhttpd/src/main.cpp101
-rw-r--r--yhttpd/src/maps/hashmap.h53
-rw-r--r--yhttpd/src/maps/hashmap.tmpl126
-rw-r--r--yhttpd/src/maps/mtools.h11
-rw-r--r--yhttpd/src/maps/mtools.tmpl12
-rw-r--r--yhttpd/src/maps/nhashmap.h21
-rw-r--r--yhttpd/src/maps/nhashmap.tmpl11
-rw-r--r--yhttpd/src/maps/shashmap.h49
-rw-r--r--yhttpd/src/maps/shashmap.tmpl157
-rw-r--r--yhttpd/src/monitor/dump.cpp109
-rw-r--r--yhttpd/src/monitor/dump.h62
-rw-r--r--yhttpd/src/monitor/stats.cpp102
-rw-r--r--yhttpd/src/monitor/stats.h36
-rw-r--r--yhttpd/src/msgs.h145
-rw-r--r--yhttpd/src/name.cpp49
-rw-r--r--yhttpd/src/name.h24
-rw-r--r--yhttpd/src/ncur/menu.cpp117
-rw-r--r--yhttpd/src/ncur/menu.h39
-rw-r--r--yhttpd/src/ncur/ncur.cpp259
-rw-r--r--yhttpd/src/ncur/ncur.h51
-rw-r--r--yhttpd/src/reqp.cpp285
-rw-r--r--yhttpd/src/reqp.h41
-rw-r--r--yhttpd/src/sign.cpp54
-rw-r--r--yhttpd/src/sign.h21
-rw-r--r--yhttpd/src/sock/sock.cpp473
-rw-r--r--yhttpd/src/sock/sock.h91
-rw-r--r--yhttpd/src/sock/sslsock.cpp141
-rw-r--r--yhttpd/src/sock/sslsock.h41
-rw-r--r--yhttpd/src/thrd/pool.cpp157
-rw-r--r--yhttpd/src/thrd/pool.h55
-rw-r--r--yhttpd/src/thrd/thro.cpp43
-rw-r--r--yhttpd/src/thrd/thro.h30
-rw-r--r--yhttpd/src/time/timo.cpp38
-rw-r--r--yhttpd/src/time/timo.h22
-rw-r--r--yhttpd/src/time/timr.cpp177
-rw-r--r--yhttpd/src/time/timr.h64
-rw-r--r--yhttpd/src/tool/dir.cpp66
-rw-r--r--yhttpd/src/tool/dir.h35
-rw-r--r--yhttpd/src/tool/tool.cpp240
-rw-r--r--yhttpd/src/tool/tool.h29
-rw-r--r--yhttpd/src/wrap.cpp121
-rw-r--r--yhttpd/src/wrap.h105
141 files changed, 15833 insertions, 0 deletions
diff --git a/ycurses/COPYING b/ycurses/COPYING
new file mode 100644
index 0000000..27058a5
--- /dev/null
+++ b/ycurses/COPYING
@@ -0,0 +1,338 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ycurses/Makefile b/ycurses/Makefile
new file mode 100644
index 0000000..6e1e203
--- /dev/null
+++ b/ycurses/Makefile
@@ -0,0 +1,69 @@
+MAKE=`tail -n 1 make.version`
+PREFIX=`grep "define PREFIX" src/glob.h | cut -d'"' -f2`
+all: version base
+ @echo If you want to help the ycurses project please run gmake mail
+ @echo so that the developers receive an email about the platform
+ @echo being used.
+ @echo WARNING! This software is EXPERIMENTAL!
+mail:
+ @echo "VERSION:" > mail.tmp
+ @${MAKE} version >> mail.tmp
+ @echo >> mail.tmp
+ @echo "UNAME:" >> mail.tmp
+ @uname -a >> mail.tmp
+ @echo >> mail.tmp
+ @echo "DATE:" >> mail.tmp
+ @date >> mail.tmp
+ @echo >> mail.tmp
+ @echo "COMPILER AND MAKE:" >> mail.tmp
+ @cat g++.version make.version >> mail.tmp
+ @cat mail.tmp | mail -s "Successfull build of ycurses" successfullbuild@yhttpd.org
+ @rm -f mail.tmp
+install: deinstall
+uninstall: deinstall
+deinstall:
+ @echo Install/deinstall is not supported!
+ @echo Start ycurses with ./bin/ycurses instead!
+ @exit 1
+base:
+ @if test -f bin/ycurses; then echo "Backing up old binary";if test -f bin/ycurses.old; then rm -f bin/ycurses.old; fi; mv bin/ycurses bin/ycurses.old; fi
+ @perl ./scripts/buildnr.pl
+ @perl ./scripts/setglobvals.pl
+ @${MAKE} -C ./src
+clean_base:
+ @${MAKE} -C ./src clean
+stats:
+ @perl scripts/stats.pl
+run:
+ ./bin/ycurses
+base_start: base
+ ./bin/ycurses
+gpl:
+ @more COPYING
+clean: clean_base
+help:
+ @echo "You may run ${MAKE} with the following parameters:"
+ @grep "^ ${MAKE} " README
+ @echo "For more questions read the README file or contact mail@ycurses.org!"
+setup:
+ @./configure
+ @${MAKE}
+config:
+ @sh -c "scripts/config.sh"
+ @echo If you run ${MAKE} config from the command line then you may need
+ @echo to rerun ./configure and recompile all now!
+
+mrproper: clean
+ @if test -f src/glob.h.org; then mv -f src/glob.h.org src/glob.h;fi
+ @if test -f g++.version; then rm -f g++.version; fi
+ @if test -f make.version; then rm -f make.version; fi
+ @if test -f src/Makefile; then rm -f src/Makefile; fi
+ @if test -f bin/ycurses; then find bin/ -name "ycurses*" | xargs rm -f; fi
+ @find . -name "*.add" | xargs rm -f
+ @ls | grep core | xargs rm -f
+version:
+ @./scripts/version.sh
+debug:
+ @gdb bin/ycurses ycurses.core
+confdebug:
+ ./configure -g3 -ggdb
diff --git a/ycurses/README b/ycurses/README
new file mode 100644
index 0000000..e2e9237
--- /dev/null
+++ b/ycurses/README
@@ -0,0 +1,382 @@
+yCurses; Version 0.1-CURRENT
+
+Copyright (C) 2005 EXA Digital Solutions GbR
+-----------------------------------------------------------------
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-----------------------------------------------------------------
+
+YCURSES TABLE OF CONTENTS:
+
+1.0.0 REQUIREMENTS
+2.0.0 LICENSE
+
+1.0.0 REQUIREMENTS:
+
+- GNU GCC G++
+ The GNU C++ compiler version 3.1 or up.
+
+- GNU make 3.80 (gmake) or higher
+ If you dont have a gmake executable but make is gnu make then you need
+ to add a symlink or alias from gmake to make.
+ yChat Makefiles only have been tested with GNU make and may not work with
+ other make versions.
+
+- ncurses 5.x
+ Includes libncurses and the ncurses.h header files.
+
+- Perl 5.x
+ Is needed for some scripts. Is not needed if you use precompiled binaries.
+
+2.0.0 LICENSE
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ycurses/SHORTDESC b/ycurses/SHORTDESC
new file mode 100644
index 0000000..ac17c13
--- /dev/null
+++ b/ycurses/SHORTDESC
@@ -0,0 +1,3 @@
+ycurses is a small C++ wrapper around the C ncurses API designed to be used in
+the yChat core.
+
diff --git a/ycurses/TODO b/ycurses/TODO
new file mode 100644
index 0000000..53c0ef4
--- /dev/null
+++ b/ycurses/TODO
@@ -0,0 +1,3 @@
+Adopt ychat coding style.
+Message box
+Curses obj counter
diff --git a/ycurses/configure b/ycurses/configure
new file mode 100755
index 0000000..9aab971
--- /dev/null
+++ b/ycurses/configure
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+if ! ./scripts/checkperl.sh
+then
+ exit 1
+fi
+
+perl -e '
+ use strict;
+ $|=1;
+ sub check_gcc {
+ my $f = shift;
+ my $s = shift;
+ my $r = 0;
+ print "Checking for GNU G++ $f.$s\n";
+ if ( `g++ -v 2> g++.version && tail -n 1 g++.version` =~ / $f\.$s/ ) {
+ `echo $f.$s >> g++.version`;
+ `echo g++ >> g++.version`;
+ $r = 1;
+ } else {
+ if (`g++$f$s -v 2> g++.version && tail -n 1 g++.version` =~ / $f\.$s/) {
+ `echo $f.$s >> g++.version`;
+ `echo g++$f$s >> g++.version`;
+ $r = 1;
+ }
+ }
+ print "No " if $r == 0;
+ print "GNU G++ $f.$s found!\n";
+ return $r;
+ }
+ sub check_make {
+ print "Checking for GNU make\n";
+ my $err = "No GNU make found.\nPlease install a version of GNU make!\n";
+ my $make;
+ if (`which gmake`) {
+ $make = "gmake";
+ } elsif ( `which make` ) {
+ $make = "make";
+ } else {
+ print $err;
+ exit(1);
+ }
+
+ `sh -c "$make -v > make.version 2>/dev/null"`;
+ if ( `cat make.version` =~ /GNU Make/ ) {
+ `echo $make >> make.version`;
+ } else {
+ print $err;
+ exit(1);
+ }
+ }
+ &check_make;
+ print "Checking compiler version\n";
+ my $r = 0;
+ for (my $i = 4; $i > 0 && $r == 0; --$i ) {
+ $r = &check_gcc(3,$i);
+ }
+ if ($r == 0) {
+ print "No suitable g++ compiler found!\n";
+ print "Please install a right version of GNU G++!\n";
+ exit(1);
+ }
+
+ system("perl \"scripts/config.pl\"");
+ chdir("src");
+ system("./configure ".join(" ", @ARGV));
+ chdir("..");
+
+ exit(0);
+' `echo "$*" | sed "s/-//g"`
+
+if test -f err
+then
+ rm -f err
+else
+ echo You are ready to type gmake now!
+fi
diff --git a/ycurses/scripts/README b/ycurses/scripts/README
new file mode 100644
index 0000000..e44cc2d
--- /dev/null
+++ b/ycurses/scripts/README
@@ -0,0 +1,6 @@
+All scripts should be run from the ycurses main directory, example:
+
+./scripts/makeycurses.pl
+
+
+A ./makeycurses.pl WILL NOT work :)
diff --git a/ycurses/scripts/astyle.sh b/ycurses/scripts/astyle.sh
new file mode 100755
index 0000000..f986cde
--- /dev/null
+++ b/ycurses/scripts/astyle.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+# The ycurses Project (2004)
+#
+# This uses "astyle" to format C++ code into a specific code style!
+
+for f in h cpp tmpl
+do
+ for i in `find . -name "*.$f"`
+ do
+ echo $i
+ astyle --style=ansi -s2 $i
+ rm -f $i.orig
+ done
+done
diff --git a/ycurses/scripts/buildnr.pl b/ycurses/scripts/buildnr.pl
new file mode 100755
index 0000000..7867787
--- /dev/null
+++ b/ycurses/scripts/buildnr.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+
+# The ycurses Project (2003)
+#
+# This script increases the BUILNR of src/msgs.h each time the ycurses
+# gets recompiled!
+
+use strict;
+
+open MSGS, "src/msgs.h";
+my @msgs = <MSGS>;
+close MSGS;
+
+foreach (@msgs)
+{
+ if ( /define BUILDNR/ )
+ {
+ s/(BUILDNR )(.+)$/$1.($2+1)/e;
+ print;
+ next;
+ }
+}
+
+open MSGS, ">src/msgs.h";
+print MSGS @msgs;
+close MSGS;
diff --git a/ycurses/scripts/checkperl.sh b/ycurses/scripts/checkperl.sh
new file mode 100755
index 0000000..418087f
--- /dev/null
+++ b/ycurses/scripts/checkperl.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+# The ycurses Project (2005)
+#
+# This scripts checks for a perl installation
+
+if ! which perl >/dev/null
+then
+ echo You need to have Perl in your PATH!
+ exit 1
+fi
+
+echo Using `which perl`
+exit 0
diff --git a/ycurses/scripts/config.pl b/ycurses/scripts/config.pl
new file mode 100755
index 0000000..afb4d76
--- /dev/null
+++ b/ycurses/scripts/config.pl
@@ -0,0 +1,144 @@
+#!/usr/bin/perl
+
+# The ycurses Project (2004, 2005)
+#
+# This script modifues the src/glob.h file.
+
+use strict;
+use scripts::modules::file;
+
+print <<END;
+Welcome to the ycurses configurator!
+You may also edit the src/glob.h file manually instead of using
+this configurator option. Please also notice that this are only
+before-compile options. All setups which can be made after com-
+iling are placed in the ycurses configuration file.
+END
+
+my $sep = "================================================================\n";
+my $stdin;
+
+for (;;)
+{
+ print "$sep Do you want to use the default before-compile options?\n";
+ print " (yes/no) [default is NO] ";
+ $stdin = <STDIN>;
+ chomp $stdin;
+ prove_if_default(\$stdin);
+ print "\n";
+
+ if ( $stdin eq "yes")
+ {
+ print " You chose to use all the default before-compile options. Exiti-\n";
+ print " ng the configurator now!\n";
+ print $sep;
+ exit(0);
+ }
+
+ last if $stdin eq "no" or $stdin eq "";
+ print " Wrong input: You need to specify yes or no!\n";
+} # for
+
+`cp src/glob.h src/glob.h.org` unless -f "src/glob.h.org";
+
+my @glob = fopen("src/glob.h.org");
+my $flag = 0;
+
+for (@glob)
+{
+ if ( $flag == 0 && /- CONFIG -/ )
+ {
+ print $sep;
+ $flag = 1;
+ next;
+ }
+
+ elsif ( $flag == 1 )
+ {
+ if ( /\*\// )
+ {
+ $flag = 2;
+ }
+
+ else
+ {
+ print;
+ }
+
+ next;
+ }
+
+ elsif ( $flag == 2 )
+ {
+ if ( /#define (.+) (.+)/ )
+ {
+ my $def = $1;
+ my $val = $2;
+ my $flg = 0;
+
+ $flg = 1 if $val =~ s/"//g;
+
+ print " [Press enter to use default value: $val] ";
+ $stdin = <STDIN>;
+ chomp $stdin;
+
+ unless ( prove_if_default(\$stdin) )
+ {
+ $stdin = "\"$stdin\"" if $flg == 1;
+ $_ = "#define $def $stdin\n";
+ }
+
+ print "\n";
+ $flag = 0;
+ next;
+ }
+
+ elsif ( /#define .+/ )
+ {
+ my $default = "true";
+ my $stdin;
+
+ for (;;)
+ {
+ $default = "false" if /\/\/#define/;
+
+ print " [Press enter to use default value: $default] ";
+ $stdin = <STDIN>;
+ chomp $stdin;
+
+ last if $stdin eq "" || $stdin eq "true" || $stdin eq "false";
+ print " Wrong input: You need to specify true or false!\n";
+ }
+
+ if ( $default eq "true" )
+ {
+ $_ = "//$_"
+ unless prove_if_default(\$stdin);
+ }
+
+ else
+ {
+ s/^\/\///
+ unless prove_if_default(\$stdin);
+ }
+
+ print "\n";
+ $flag = 0;
+ next;
+ }
+ }
+} // for
+
+ fwrite("src/glob.h", @glob);
+
+sub prove_if_default
+{
+ my $val = shift;
+ if ( $$val eq "" )
+ {
+ print " -> Using default option!\n";
+ return 1;
+ }
+ print " -> Using new option $$val!\n";
+ return 0;
+}
diff --git a/ycurses/scripts/modules/file.pm b/ycurses/scripts/modules/file.pm
new file mode 100644
index 0000000..b11e2b3
--- /dev/null
+++ b/ycurses/scripts/modules/file.pm
@@ -0,0 +1,28 @@
+sub dopen
+{
+ my $shift = shift;
+ opendir DIR, $shift or die "$shift: $!\n";
+ my @dir = readdir(DIR);
+ closedir DIR;
+ return @dir;
+}
+
+sub fopen
+{
+ my $shift = shift;
+ open FILE, $shift or die "$shift: $!\n";
+ my @file = <FILE>;
+ close FILE;
+ return @file;
+}
+
+sub fwrite
+{
+ my $shift = shift;
+ my @file = @_;
+ open FILE, ">$shift" or die "$shift: $!\n";
+ print FILE @file;
+ close FILE;
+}
+
+1;
diff --git a/ycurses/scripts/screen.sh b/ycurses/scripts/screen.sh
new file mode 100755
index 0000000..23d4e66
--- /dev/null
+++ b/ycurses/scripts/screen.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+screen -S ycurses ./bin/ycurses
diff --git a/ycurses/scripts/setglobvals.pl b/ycurses/scripts/setglobvals.pl
new file mode 100755
index 0000000..f0763ac
--- /dev/null
+++ b/ycurses/scripts/setglobvals.pl
@@ -0,0 +1,32 @@
+#!/usr/bin/perl
+
+# The ycurses Project (2003)
+#
+# This script sets up some variables in src/glob.h
+
+use strict;
+
+use scripts::modules::file;
+
+my $file = 'src/glob.h';
+my $gmake = `which gmake`;
+my @glob = fopen($file);
+chomp($gmake);
+
+print "-> Setting values in $file\n";
+
+my $modified = 0;
+foreach (@glob)
+{
+ if (/^(#define GMAKE) "(.*)"/)
+ {
+ if ($2 ne "$gmake \\0")
+ {
+ s/^$1 "$2"/#define GMAKE "$gmake \\0"/;
+ print " -> Set $gmake\n";
+ fwrite($file,@glob);
+ last;
+ }
+ }
+}
+
diff --git a/ycurses/scripts/stats.pl b/ycurses/scripts/stats.pl
new file mode 100755
index 0000000..222c16e
--- /dev/null
+++ b/ycurses/scripts/stats.pl
@@ -0,0 +1,95 @@
+#!/usr/bin/perl
+
+# The ycurses Project (2003 - 2004)
+#
+# This script generates source code and project statistics
+
+use strict;
+
+use scripts::modules::file;
+
+my %stats;
+my $param = shift;
+
+&recursive(".");
+
+$stats{"Lines total"} = $stats{"Lines of source"}
+ + $stats{"Lines of scripts"}
+ + $stats{"Lines of text"}
+ + $stats{"Lines of HTML"};
+
+unless (defined $param) {
+
+ print "$_ = " . $stats{$_} . "\n"
+ for ( sort keys %stats );
+
+} else {
+
+ print $stats{$_} . " "
+ for sort keys %stats;
+
+}
+
+print "\n";
+
+sub recursive
+{
+ my $shift = shift;
+ my @dir = &dopen($shift);
+
+ foreach (@dir)
+ {
+ next if /^\.$/ or /^\.{2}$/;
+
+ if ( -f "$shift/$_" )
+ {
+ $stats{"Number of files total"}++;
+ &filestats("$shift/$_");
+ }
+ elsif ( -d "$shift/$_" )
+ {
+ $stats{"Number of dirs total"}++;
+ &recursive("$shift/$_");
+ }
+ }
+}
+
+sub filestats
+{
+ my $shift = shift;
+ if ( $shift =~ /\.(cpp|h|tmpl)$/ )
+ {
+ $stats{"Number of source files"}++;
+ $stats{"Lines of source"} += countlines($shift);
+ }
+ elsif ( $shift =~ /\.(html|css)$/ )
+ {
+ $stats{"Number of HTML files"}++;
+ $stats{"Lines of HTML"} += countlines($shift);
+ }
+ elsif ( $shift =~ /\.(gif|png|jpg)$/ )
+ {
+ $stats{"Number of gfx files"}++;
+ }
+ elsif ( $shift =~ /(\.pl|\.sh|configure.*|Makefile.*)$/ )
+ {
+ $stats{"Number of script files"}++;
+ $stats{"Lines of scripts"} += countlines($shift);
+ }
+ elsif ( $shift =~ /(\.txt|README|INSTALL|COPYING|NEWS|SNAPSHOT|CHANGES|RELEASES)$/ )
+ {
+ $stats{"Number of text files"}++;
+ $stats{"Lines of text"} += countlines($shift);
+ }
+ elsif ( $shift =~ /\.so$/ )
+ {
+ $stats{"Number of compiled module files"}++;
+ }
+}
+
+sub countlines
+{
+ my $shift = shift;
+ my @file = fopen($shift);
+ return $#file;
+}
diff --git a/ycurses/scripts/version.sh b/ycurses/scripts/version.sh
new file mode 100755
index 0000000..8bb9bdd
--- /dev/null
+++ b/ycurses/scripts/version.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# The ycurses Project (2005)
+#
+# This script shows ycurses VERSION-BRANCH Build BUILDNUMBER
+
+version=`grep VERSION src/msgs.h | head -n 1 | cut -d'"' -f2`
+branch=`grep BRANCH src/msgs.h | head -n 1 | cut -d'"' -f2`
+build=`grep BUILD src/msgs.h | tail -n 1 | cut -d' ' -f3`
+echo "ycurses $version-$branch Build $build"
+
+
diff --git a/ycurses/src/Makefile.in b/ycurses/src/Makefile.in
new file mode 100644
index 0000000..7723d45
--- /dev/null
+++ b/ycurses/src/Makefile.in
@@ -0,0 +1,21 @@
+SRCS=WILLBEADDEDBYCONFIGURE
+OBJS=$(addprefix ../obj/,$(SRCS:.cpp=.o))
+CC=WILLBEADDEDBYCONFIGURE
+LIBADD=`cat libs.add`
+LDFLAGS=$(LIBADD) -lstdc++
+LDADD=
+INCLUDES=`cat includes.add`
+CFLAGS=-fno-inline -fno-default-inline -frepo
+all: ycurses
+$(SRCS):
+ $(CC) $(INCLUDES) $(CFLAGS) -c $*.cpp
+infotext:
+ @echo Compiling base
+ycurses: infotext $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDADD)
+ @mv ycurses ../bin
+ @echo -n "Size of linked executable: "
+ @du -hc ../bin/ycurses | tail -n 1
+clean:
+ @echo Cleaning base obj
+ @if test -d ../obj; then rm -Rf ../obj; fi
diff --git a/ycurses/src/configure b/ycurses/src/configure
new file mode 100755
index 0000000..cb7c9ff
--- /dev/null
+++ b/ycurses/src/configure
@@ -0,0 +1,330 @@
+#!/bin/sh
+
+#
+# The ycurses Project (2003 - 2005)
+#
+
+if ! ../scripts/checkperl.sh
+then
+ exit 1
+fi
+
+if ! test -f ../g++.version
+then
+ echo You need to run ./configure of the top level source dir first
+ exit 1
+fi
+
+perl -e '
+ use strict;
+ $|=1;
+
+ my %libadd;
+ my %incadd;
+ my $deepness = 500;
+
+ my @headers = (
+ "ncurses.h",
+ "menu.h",
+ "panel.h"
+ );
+
+ my @libs = (
+ "libpanel.so",
+ "libmenu.so",
+ "libncurses.so"
+ );
+
+ my @headerpaths = (
+ $ENV{HOME}."/include",
+ $ENV{HOME}."/usr/include",
+ "/include",
+ "/usr/include",
+ "/usr/local/include",
+ "/usr/lib/",
+ "/usr/pkg/include",
+ "/opt/include",
+ "/opt/local/include"
+ );
+
+ my @libpaths = (
+ $ENV{HOME}."/lib",
+ $ENV{HOME}."/usr/lib",
+ "/lib",
+ "/usr/lib",
+ "/usr/local/lib",
+ "/usr/pkg/lib",
+ "/opt/lib",
+ "/opt/local/lib"
+ );
+
+ open FILE, "glob.h" or die "glob.h: $!\n";
+ while(<FILE>)
+ {
+ if ( /\/\/#define DATABASE/ )
+ {
+ remove_from_array("mysql/mysql.h",\@headers);
+ remove_from_array("libmysqlclient.so",\@libs);
+ }
+
+ elsif ( /\/\/#define NCURSES/ )
+ {
+ remove_from_array("ncurses.h",\@headers);
+ remove_from_array("libncurses.so",\@libs);
+ }
+ }
+ close FILE;
+
+ if ( defined $ENV{YHTTPDHEADERPATHS} )
+ {
+ map { print "Adding $_...\n";
+ unshift @headerpaths, $_ } split /:/, $ENV{YHTTPDHEADERPATHS};
+ }
+
+ if ( defined $ENV{YHTTPDLIBPATHS} )
+ {
+ map { print "Adding $_...\n";
+ unshift @libpaths, $_ } split /:/, $ENV{YHTTPDLIBPATHS};
+ }
+
+
+ print "Headers:\n";
+
+ my $testit = 0;
+ map { $incadd{&check($deepness, $_, @headerpaths)}++ }
+ @headers;
+
+ $testit = 0;
+ print "Libraries:\n";
+ map { $libadd{&check($deepness, $_, @libpaths)}++ }
+ @libs;
+
+ my $incadd = &make_add("-I", \%incadd);
+ my $libadd = &make_add("-L", \%libadd);
+
+ for ( @libs )
+ {
+ $libadd .= "-l$_ " if s/^lib// and s/\.so$//;
+ }
+
+ print "Incadd: $incadd\n";
+ print "Libadd: $libadd\n";
+
+ `echo $incadd > includes.add`;
+ `echo $libadd > libs.add`;
+
+ print "Creating new base Makefile...\n";
+ unlink("Makefile") if -f "Makefile";
+ unlink("../err") if -f "../err";
+ open Fin, "Makefile.in" or die "Makefile.in: $!\n";
+ open Fout, ">Makefile" or die "Makefile: $!\n";
+
+# my $cpp = `echo *.cpp */*.cpp contrib/*/*.cpp | sort`;
+ my $cpp = `echo *.cpp */*.cpp | sort`;
+ my $compiler = `tail -n 1 ../g++.version`;
+ my $version = `tail -n 2 ../g++.version | head -n 1`;
+ my $uname = `uname -srm`;
+ my $compopt = join "; ", split /\n/, `cat ../g++.version`;
+
+ chomp $uname;
+ chomp $compopt;
+
+ print "Configuring for $uname...\n";
+ chomp $cpp;
+ chomp $version;
+
+ while (<Fin>)
+ {
+ s/^(CC=).*\n/$1$compiler/;
+ s/^(SRCS=).*/$1$cpp/;
+ s/ -frepo//; # unless $version =~ /3\.4/;
+ if ( $uname !~ /Linux/i ) {
+ print "Disabling -ldl flag...\n" if s/ -ldl//;
+ }
+ print Fout;
+ }
+ close Fin;
+
+ my $args = join(" -",@ARGV);
+ $args = "-".$args unless $args eq "";
+
+ for my $cppfile (split / /, $cpp)
+ {
+ my $ofile = $cppfile;
+ $ofile =~ s/\.cpp/\.o/;
+ print Fout "../obj/$ofile: $cppfile\n";
+ print Fout "\t\@if ! test -d `dirname ../obj/$ofile`; then mkdir -p `dirname ../obj/$ofile`; fi\n";
+ my $class = $ofile;
+ $class =~ s/\.o//;
+ if ( $class =~ /contrib\/.+/ )
+ {
+ my $dirname = `dirname $class`;
+ print Fout "\t\@echo -n \"Compiling contributed class $class \"\n";
+ }
+
+ else
+ {
+ print Fout "\t\@echo -n \"Compiling base class $class \"\n";
+ }
+
+ print Fout "\t\@\$(CC) \$(CFLAGS) \$(INCLUDES) $args -c -o ../obj/$ofile $cppfile\n";
+ print Fout "\t\@du -hc ../obj/$ofile | tail -n 1 | sed s/total// | sed \"s/ //g\"\n";
+ }
+
+ close Fout;
+
+ open F, "msgs.h" or die "msgs.h: $!\n";
+ my @msgs = <F>;
+ close F;
+ unlink("msgs.h");
+ open F, ">msgs.h" or die "msgs.h: $!\n";
+
+ for (@msgs)
+ {
+ s/(UNAME)(.+)$/UNAME "$uname"/;
+ s/(COMPOPT)(.+)$/COMPOPT "$compopt"/;
+ print F;
+ }
+ close F;
+
+ if ( -d "mods" )
+ {
+ chdir("mods");
+ my $cflags = "-fno-inline -fno-default-inline";
+
+ $cflags .= " -nostdlib" if $uname =~ /FreeBSD/i && `uname -r` =~ /^4\./;
+
+ system("echo $cflags > cflags.add");
+ system("./configure");
+ chdir("..");
+ }
+
+ sub remove_from_array
+ {
+ my $elem = shift;
+ my $array = shift;
+
+ for ( my $i = 0; $i <= $#$array; ++$i )
+ {
+ if ( $$array[$i] eq $elem )
+ {
+ splice(@$array,$i,1);
+ last;
+ }
+ } # for
+ }
+
+ sub check {
+ my $deep = shift;
+
+ if ($deep == 0) {
+ print "Looking too deep! ($deepness)\n";
+ exit(1);
+ }
+
+ my $check = shift;
+ $testit = 1 if $check =~ s/::test:://;
+
+ my $print = 1;
+ if ( $_[-1] eq "subsearch" ) {
+ $print = 0;
+ pop(@_);
+ }
+
+ if ($print)
+ {
+ print "Checking for $check...";
+ print "\n" if $testit;
+ }
+
+ for (@_)
+ {
+ if ( -f "$_/$check" )
+ {
+ if ($testit)
+ {
+ return $_ if test_include($_, $check);
+ return "";
+ }
+
+ else
+ {
+ print "OK\n";
+ return "" if $_ eq "/usr/lib" or $_ eq "/usr/include";
+ return $_;
+ }
+ }
+ }
+
+ for (@_)
+ {
+ next unless -d $_;
+ opendir D, $_ or warn "$_: $!\n";
+ my @dir = readdir(D);
+ closedir D;
+
+ for my $dir ( @dir )
+ {
+ next if $dir =~ /^\.+$/ or !-d "$_/$dir";
+ my $path = &check($deep-1, $check, "$_/$dir", "subsearch");
+ return $path if $path ne "";
+ }
+ }
+
+ if ($print)
+ {
+ print "NOT OK\n";
+ print "Please make sure that you have the needed software installed!\n";
+ print "If you have a special path for your includes then edit src/configure!\n";
+ print "Or set the environment variables YHTTPDHEADERPATHS and YHTTPDLIBPATHS.\n";
+ print " Example: setenv YHTTPDHEADERPATHS \"/your/header/includes:/a/includes\"\n";
+ print "(The environment variables have to be seperated by an :)\n";
+ print "PS: You may use the locate and/or find command to search for files.\n";
+ exit(1);
+ }
+
+ `touch ../err`;
+ return "";
+ }
+
+ sub make_add {
+ my $flag = shift;
+ my $add = shift;
+ my $ret = "";
+
+ for (reverse keys %$add) {
+ next unless /.+/;
+ $ret .= "$flag$_ ";
+ }
+ return $ret;
+ }
+
+ sub test_include
+ {
+ my $shift = shift;
+ my $check = shift;
+ my $return = 0;
+ print "Testing $shift/$check...";
+
+ `echo "\#include \\"maps/hashmap.h\\"" > __test.cpp`;
+ `echo "int main(void){return 0;}" >> __test.cpp`;
+ my $cmd = "`tail -n 1 ../g++.version` -I$shift __test.cpp -o /dev/null 2>/dev/null";
+ system $cmd;
+
+ unless ($?)
+ {
+ print "OK\n";
+ $return = 1;
+ }
+
+ else
+ {
+ print "Not OK\n";
+ }
+
+ unlink "__test.cpp" if -f "__test.cpp";
+ return $return;
+ }
+
+ exit(0);
+' `echo "$*" | sed "s/-//g"`
diff --git a/ycurses/src/curses/attributes.cpp b/ycurses/src/curses/attributes.cpp
new file mode 100644
index 0000000..b859da0
--- /dev/null
+++ b/ycurses/src/curses/attributes.cpp
@@ -0,0 +1,80 @@
+#ifndef ATTRIBUTES_CPP
+#define ATTRIBUTES_CPP
+
+#include "attributes.h"
+
+attributes::attributes()
+{
+ init();
+}
+
+attributes::attributes(int i_attr)
+{
+ init();
+ set(true, i_attr);
+}
+
+attributes::attributes(color& r_color)
+{
+ init();
+ set_color(r_color);
+}
+
+void
+attributes::init()
+{
+ p_color = 0;
+}
+
+void
+attributes::use_wattron(WINDOW* p_window)
+{
+ std::set<int>::iterator iter;
+ for (iter = set_attr.begin(); iter != set_attr.end(); ++iter)
+ wattron(p_window, *iter);
+
+ if (p_color)
+ wattron(p_window, COLOR_PAIR(p_color->get_num()));
+}
+
+void
+attributes::use_wattroff(WINDOW* p_window)
+{
+ std::set<int>::iterator iter;
+ for (iter = set_attr.begin(); iter != set_attr.end(); ++iter)
+ wattroff(p_window, *iter);
+
+ if (p_color)
+ wattroff(p_window, COLOR_PAIR(p_color->get_num()));
+}
+
+
+void
+attributes::unset_all()
+{
+ set_attr.clear();
+ p_color = 0;
+}
+
+bool
+attributes::get(int i_attr)
+{
+ return set_attr.find(i_attr) != set_attr.end();
+}
+
+void
+attributes::set(bool b, int i_attr)
+{
+ if ((set_attr.find(i_attr) != set_attr.end() ) == b)
+ return;
+
+ set_attr.insert(i_attr);
+}
+
+void
+attributes::set_color(color& r_color)
+{
+ this->p_color = &r_color;
+}
+
+#endif
diff --git a/ycurses/src/curses/attributes.h b/ycurses/src/curses/attributes.h
new file mode 100644
index 0000000..2bc58d6
--- /dev/null
+++ b/ycurses/src/curses/attributes.h
@@ -0,0 +1,70 @@
+#ifndef ATTRIBUTES_H
+#define ATTRIBUTES_H
+
+#include <set>
+#include "incl.h"
+#include "color.h"
+
+using namespace std;
+
+const int Normal = A_NORMAL;
+const int Standout = A_STANDOUT;
+const int Underline = A_UNDERLINE;
+const int Reverse = A_REVERSE;
+const int Blink = A_BLINK;
+const int Dim = A_DIM;
+const int Bold = A_BOLD;
+const int Protect = A_PROTECT;
+const int Invis = A_INVIS;
+const int AltCharSet = A_ALTCHARSET;
+const int CharText = A_CHARTEXT;
+
+class attributes
+{
+private:
+ void init();
+ set<int> set_attr;
+ bool get(int i_attr);
+ void set(bool b, int i_attr);
+ color* p_color;
+
+ friend class window;
+ void use_wattron(WINDOW* p_window);
+ void use_wattroff(WINDOW* p_window);
+
+public:
+ attributes();
+ attributes(int i_attr);
+ attributes(color& r_color);
+
+ void set(int i_attr) { set(true, i_attr); }
+ void unset(int i_attr ) { set(false, i_attr); }
+ void unset_all();
+ void set_color(color& r_color);
+
+ void set_normal(bool b) { set(b, Normal); }
+ void set_standout(bool b) { set(b, Standout); }
+ void set_underline(bool b) { set(b, Underline); }
+ void set_reverse(bool b) { set(b, Reverse); }
+ void set_blink(bool b) { set(b, Blink); }
+ void set_dim(bool b) { set(b, Dim); }
+ void set_bold(bool b) { set(b, Bold); }
+ void set_protect(bool b) { set(b, Protect); }
+ void set_invisible(bool b) { set(b, Invis); }
+ void set_altcharset(bool b) { set(b, AltCharSet); }
+ void set_chartext(bool b) { set(b, CharText); }
+
+ bool get_normal() { return get(Normal); }
+ bool get_standout() { return get(Standout); }
+ bool get_underline() { return get(Underline); }
+ bool get_reverse() { return get(Reverse); }
+ bool get_blink() { return get(Blink); }
+ bool get_dim() { return get(Dim); }
+ bool get_bold() { return get(Bold); }
+ bool get_protect() { return get(Protect); }
+ bool get_invisible() { return get(Invis); }
+ bool get_altcharset() { return get(AltCharSet); }
+ bool get_chartext() { return get(CharText); }
+};
+
+#endif
diff --git a/ycurses/src/curses/color.cpp b/ycurses/src/curses/color.cpp
new file mode 100644
index 0000000..190d343
--- /dev/null
+++ b/ycurses/src/curses/color.cpp
@@ -0,0 +1,54 @@
+#ifndef COLOR_CPP
+#define COLOR_CPP
+
+#include "color.h"
+
+bool color::b_activated = false;
+int color::i_pair_count = 0;
+
+color::color(short i, short j)
+ : i_foreground(i), i_background(j)
+{
+ init();
+
+ i_pair = ++i_pair_count;
+
+ /*
+ * Simple color assignment. color pair 0 cannot
+ * be redefined.
+ */
+ init_pair(i_pair, i_foreground, i_background);
+}
+
+color::~color()
+{
+}
+
+void
+color::init()
+{
+ if ( !b_activated )
+ {
+ if (has_colors())
+ {
+ start_color();
+ b_activated = true;
+ }
+ }
+}
+
+void
+color::enable()
+{
+ attron(COLOR_PAIR(i_pair));
+}
+
+void
+color::disable()
+{
+ attroff(COLOR_PAIR(i_pair));
+}
+
+
+#endif
+
diff --git a/ycurses/src/curses/color.h b/ycurses/src/curses/color.h
new file mode 100644
index 0000000..a59727c
--- /dev/null
+++ b/ycurses/src/curses/color.h
@@ -0,0 +1,39 @@
+
+#ifndef COLOR_H
+#define COLOR_H
+
+#include "incl.h"
+
+using namespace std;
+
+const short Red = COLOR_RED;
+const short Green = COLOR_GREEN;
+const short Yellow = COLOR_YELLOW;
+const short Blue = COLOR_BLUE;
+const short Cyan = COLOR_CYAN;
+const short Magenta = COLOR_MAGENTA;
+const short White = COLOR_WHITE;
+const short Black = COLOR_BLACK;
+
+class color
+{
+ private:
+ void init();
+
+ static int i_pair_count;
+ short i_pair;
+ short i_foreground;
+ short i_background;
+ static bool b_activated;
+
+ friend class curses;
+
+ public:
+ color(short i, short j);
+ ~color();
+ void enable();
+ void disable();
+ short get_num() { return i_pair; }
+};
+
+#endif
diff --git a/ycurses/src/curses/coordinate.cpp b/ycurses/src/curses/coordinate.cpp
new file mode 100644
index 0000000..efdf9e2
--- /dev/null
+++ b/ycurses/src/curses/coordinate.cpp
@@ -0,0 +1,134 @@
+#ifndef COORDONATE_CPP
+#define COORDONATE_CPP
+
+#include "coordinate.h"
+
+coordinate::coordinate()
+{
+ y = x = 0;
+}
+
+coordinate::coordinate(coordinate_type type, dummy_window& r_win)
+{
+ set(type, r_win);
+}
+
+coordinate::coordinate(coordinate_type type)
+{
+ set(type);
+}
+
+coordinate::coordinate(int y, int x)
+{
+ this->y = y;
+ this->x = x;
+}
+
+coordinate&
+coordinate::set(coordinate_type type, dummy_window& r_win)
+{
+ switch (type)
+ {
+ case Absolutecoord:
+ getyx(r_win.get_WINDOW(), y, x);
+ break;
+
+ case Relativecoord:
+ getparyx(r_win.get_WINDOW(), y, x);
+ break;
+
+ case Beginningcoord:
+ getbegyx(r_win.get_WINDOW(), y, x);
+ break;
+
+ case windowSize:
+ getmaxyx(r_win.get_WINDOW(), y, x);
+ break;
+
+ default:
+ set(type);
+ }
+
+ return *this;
+}
+
+coordinate&
+coordinate::set(coordinate_type type)
+{
+ switch (type)
+ {
+ case TerminalSize:
+ y = COLS;
+ x = LINES;
+ break;
+
+ case TerminalCenter:
+ y = static_cast<int>(COLS / 2);
+ x = static_cast<int>(LINES / 2);
+ break;
+ }
+
+ return *this;
+}
+
+coordinate&
+coordinate::left()
+{
+ return left(1);
+}
+
+coordinate&
+coordinate::right()
+{
+ return right(1);
+}
+
+coordinate&
+coordinate::up()
+{
+ return up(1);
+}
+
+coordinate&
+coordinate::down()
+{
+ return down(1);
+}
+
+coordinate&
+coordinate::left(int i)
+{
+ x -= i;
+ return *this;
+}
+
+coordinate&
+coordinate::right(int i)
+{
+ x += i;
+ return *this;
+}
+
+coordinate&
+coordinate::up(int i)
+{
+ y -= i;
+ return *this;
+}
+
+coordinate&
+coordinate::down(int i)
+{
+ y += i;
+ return *this;
+}
+
+coordinate&
+coordinate::displace(int i_y, int i_x)
+{
+ y += i_y;
+ x += i_x;
+ return *this;
+}
+
+#endif
diff --git a/ycurses/src/curses/coordinate.h b/ycurses/src/curses/coordinate.h
new file mode 100644
index 0000000..c17b36b
--- /dev/null
+++ b/ycurses/src/curses/coordinate.h
@@ -0,0 +1,43 @@
+#ifndef COORDINATE_H
+#define COORDINATE_H
+
+#include "incl.h"
+#include "dummy.h"
+
+using namespace std;
+
+enum coordinate_type
+{
+ Absolutecoord,
+ Relativecoord,
+ Beginningcoord,
+ windowSize,
+ TerminalSize,
+ TerminalCenter
+};
+
+
+struct coordinate
+{
+ int y, x;
+
+ coordinate();
+ coordinate(coordinate_type type, dummy_window& r_win);
+ coordinate(coordinate_type type);
+ coordinate(int y, int x);
+
+ coordinate& set(coordinate_type type, dummy_window& r_win);
+ coordinate& set(coordinate_type type);
+ coordinate& left();
+ coordinate& right();
+ coordinate& up();
+ coordinate& down();
+ coordinate& left(int i);
+ coordinate& right(int i);
+ coordinate& up(int i);
+ coordinate& down(int i);
+ coordinate& displace(int i_y, int i_x);
+
+};
+
+#endif
diff --git a/ycurses/src/curses/coordinate.impl b/ycurses/src/curses/coordinate.impl
new file mode 100644
index 0000000..8bdf17c
--- /dev/null
+++ b/ycurses/src/curses/coordinate.impl
@@ -0,0 +1,17 @@
+template<class T>
+coordinate
+create_coordinate(dummy_window& d_window)
+{
+ coordinate coord;
+ T(d_window, coord.x, coord.y);
+ return coord;
+}
+
+template<class T>
+coordinate
+create_coordinate()
+{
+ coordinate coord;
+ T(coord.x, coord.y);
+ return coord;
+}
diff --git a/ycurses/src/curses/curses.cpp b/ycurses/src/curses/curses.cpp
new file mode 100644
index 0000000..3605e59
--- /dev/null
+++ b/ycurses/src/curses/curses.cpp
@@ -0,0 +1,86 @@
+#ifndef CURSES_CPP
+#define CURSES_CPP
+
+#include "curses.h"
+
+int curses::i_self_counter = 0;
+
+curses::curses()
+{
+ if ( ++i_self_counter == 1 )
+ {
+ initscr();
+ raw();
+ keypad(stdscr, TRUE);
+ noecho();
+ }
+}
+
+curses::~curses()
+{
+ if ( --i_self_counter == 0 )
+ {
+/*
+ Factory<attributes>::destroyAll();
+ Factory<color>::destroyAll();
+ Factory<window>::destroyAll();
+ Factory<menu>::destroyAll();
+ Factory<pwindow>::destroyAll();
+ */
+ clear();
+ endwin();
+ }
+}
+
+void
+curses::finish()
+{
+}
+
+int
+curses::get_char()
+{
+ return getch();
+}
+
+string
+curses::get_string()
+{
+ char c[1024];
+ getstr(c);
+ return string(c);
+}
+
+void
+curses::pause()
+{
+ getch();
+}
+
+void
+curses::disable()
+{
+ refresh();
+ def_prog_mode();
+ endwin();
+}
+
+void
+curses::enable()
+{
+ reset_prog_mode();
+ refresh();
+}
+
+void
+curses::clear()
+{
+ coordinate coord(LINES, COLS);
+ for ( int i = 0; i < coord.y; ++i )
+ for ( int j = 0; j < coord.x; ++j )
+ mvaddch(i, j, ' ');
+
+ refresh();
+}
+
+#endif
diff --git a/ycurses/src/curses/curses.h b/ycurses/src/curses/curses.h
new file mode 100644
index 0000000..04ed707
--- /dev/null
+++ b/ycurses/src/curses/curses.h
@@ -0,0 +1,55 @@
+#ifndef CURSES_H
+#define CURSES_H
+
+#include "attributes.h"
+#include "incl.h"
+#include "color.h"
+#include "cursor.h"
+#include "menu.h"
+#include "pwindow.h"
+#include "tool.h"
+#include "window.h"
+#include "coordinate.h"
+
+using namespace std;
+
+/* This class is representing the base of curses, it has to be instantiated
+ * in order to use curses.
+ */
+class curses
+{
+ private:
+ static int i_self_counter;
+
+ public:
+ /* Initializes curses before its first use */
+ curses();
+
+ /* Removes all curses elements, all objects (such as window, color etc)
+ * be finished as well!
+ */
+ ~curses();
+
+ /* Waits for user intput and returns the ASCII code being typed */
+ static int get_char();
+
+ /* Returns the string being typed until the first return */
+ static string get_string();
+
+ /* Waits intil the user hits a key */
+ static void pause();
+
+ static void disable();
+ static void enable();
+
+ /* Removes all curses elements, all objects (such as window, color etc) will
+ * be finished as well! This method will be called by ~curses internally.
+ * You can also use this method instead of the destructor if you wanna use
+ * another shutdown routine like catching SIGINT first, deleting your own
+ * stuff, and then running curses::finish();!
+ */
+ static void finish();
+ static void clear();
+};
+
+#endif
diff --git a/ycurses/src/curses/cursor.cpp b/ycurses/src/curses/cursor.cpp
new file mode 100644
index 0000000..eaa10a7
--- /dev/null
+++ b/ycurses/src/curses/cursor.cpp
@@ -0,0 +1,32 @@
+#ifndef CURSOR_CPP
+#define CURSOR_CPP
+
+#include "cursor.h"
+
+cursor::cursor()
+{
+}
+
+cursor::cursor(cursorType t)
+{
+ set(t);
+}
+
+cursor::cursor(coordinate& r_coord)
+{
+ set(r_coord);
+}
+
+void
+cursor::set(cursorType t)
+{
+ curs_set(t);
+}
+
+void
+cursor::set(coordinate& r_coord)
+{
+ move(r_coord.y, r_coord.x);
+}
+
+#endif
diff --git a/ycurses/src/curses/cursor.h b/ycurses/src/curses/cursor.h
new file mode 100644
index 0000000..504a44c
--- /dev/null
+++ b/ycurses/src/curses/cursor.h
@@ -0,0 +1,30 @@
+#ifndef CURSOR_H
+#define CURSOR_H
+
+#include "incl.h"
+#include "coordinate.h"
+
+using namespace std;
+
+enum cursorType
+{
+ Invisible = 0,
+ Visible,
+ VeryVisible
+};
+
+struct cursor
+{
+ cursor();
+ cursor(cursorType t);
+ cursor(coordinate& r_coord);
+
+ static void set(cursorType t);
+ static void set(coordinate& r_coord);
+
+ static void set_invisible() { set(Invisible); }
+ static void setVisible() { set(Visible); }
+ static void setVeryVisible() { set(VeryVisible); }
+};
+
+#endif
diff --git a/ycurses/src/curses/dummy.cpp b/ycurses/src/curses/dummy.cpp
new file mode 100644
index 0000000..eab2b13
--- /dev/null
+++ b/ycurses/src/curses/dummy.cpp
@@ -0,0 +1,11 @@
+#ifndef DUMMY_CPP
+#define DUMMY_CPP
+
+#include "dummy.h"
+
+WINDOW* dummy_window::get_WINDOW()
+{
+ return 0;
+}
+
+#endif
diff --git a/ycurses/src/curses/dummy.h b/ycurses/src/curses/dummy.h
new file mode 100644
index 0000000..d691e1c
--- /dev/null
+++ b/ycurses/src/curses/dummy.h
@@ -0,0 +1,11 @@
+#ifndef DUMMY_H
+#define DUMMY_H
+
+#include "incl.h"
+
+struct dummy_window
+{
+ virtual WINDOW* get_WINDOW();
+};
+
+#endif
diff --git a/ycurses/src/curses/hidden.cpp b/ycurses/src/curses/hidden.cpp
new file mode 100644
index 0000000..9f9b39f
--- /dev/null
+++ b/ycurses/src/curses/hidden.cpp
@@ -0,0 +1,29 @@
+#ifndef HIDDEN_CPP
+#define HIDDEN_CPP
+
+#include "hidden.h"
+
+hidden::hidden()
+{
+ show();
+}
+
+void
+hidden::hide()
+{
+ b_hidden = true;
+}
+
+void
+hidden::show()
+{
+ b_hidden = false;
+}
+
+bool
+hidden::is_hidden()
+{
+ return b_hidden;
+}
+
+#endif
diff --git a/ycurses/src/curses/hidden.h b/ycurses/src/curses/hidden.h
new file mode 100644
index 0000000..f0f632a
--- /dev/null
+++ b/ycurses/src/curses/hidden.h
@@ -0,0 +1,21 @@
+#ifndef HIDDEN_H
+#define HIDDEN_H
+
+#include "incl.h"
+
+using namespace std;
+
+class hidden
+{
+ private:
+ bool b_hidden;
+
+ public:
+ hidden();
+ virtual void hide();
+ virtual void show();
+ bool is_hidden();
+};
+
+#endif
+
diff --git a/ycurses/src/curses/incl.h b/ycurses/src/curses/incl.h
new file mode 100644
index 0000000..b31d1ff
--- /dev/null
+++ b/ycurses/src/curses/incl.h
@@ -0,0 +1,8 @@
+#include <iostream>
+#include <map>
+#include <string>
+#include <vector>
+
+#include <ncurses.h>
+#include <menu.h>
+#include <panel.h>
diff --git a/ycurses/src/curses/menu.cpp b/ycurses/src/curses/menu.cpp
new file mode 100644
index 0000000..e240566
--- /dev/null
+++ b/ycurses/src/curses/menu.cpp
@@ -0,0 +1,117 @@
+#ifndef MENU_CPP
+#define MENU_CPP
+
+#include "menu.h"
+
+menu::menu(vector<string>& vec_choices)
+{
+ init(vec_choices);
+}
+
+menu::~menu()
+{
+ if (p_items)
+ {
+ for (int i = 0; i < i_choices; ++i)
+ free_item(p_items[i]);
+
+ delete [] p_items;
+ p_items = 0;
+ }
+
+ if (p_menu)
+ {
+ free_menu(p_menu);
+ p_menu = 0;
+ }
+
+ if (p_win)
+ {
+ delete p_win;
+ p_win = 0;
+ }
+}
+
+void
+menu::init(vector<string>& vec_choices)
+{
+ i_choices = vec_choices.size();
+ i_current = 0;
+
+ int i_choices = vec_choices.size();
+ int iMaxLen = 0;
+ p_items = new ITEM*[i_choices];
+
+ for (int i = 0; i < i_choices; ++i)
+ {
+ p_items[i] = new_item(vec_choices.at(i).c_str(), "");
+ int iLen = vec_choices.at(i).length();
+ if (iLen > iMaxLen)
+ iMaxLen = iLen;
+ }
+
+ p_menu = new_menu(p_items);
+
+ p_win = new window(i_choices+2, iMaxLen+4, 4, 4);
+ WINDOW* p_window = p_win->get_WINDOW();
+
+ set_menu_win(p_menu, p_window);
+ set_menu_sub(p_menu, derwin(p_window, i_choices, iMaxLen+2, 1, 1));
+
+ refresh();
+ post_menu(p_menu);
+ wrefresh(p_window);
+}
+
+window&
+menu::get_window()
+{
+ return *p_win;
+}
+
+int
+menu::run()
+{
+ WINDOW* p_window = p_win->get_WINDOW();
+ keypad(p_window, 1);
+ int i_choice;
+
+ while( (i_choice = wgetch(p_window)) )
+ {
+ switch(i_choice)
+ {
+ case KEY_DOWN:
+ case 'j': // Vi mode
+ if ( i_current < i_choices-1 )
+ ++i_current;
+ menu_driver(p_menu, REQ_DOWN_ITEM);
+ break;
+
+ case KEY_UP:
+ case 'k': // Vi mode
+ if ( i_current > 0 )
+ --i_current;
+ menu_driver(p_menu, REQ_UP_ITEM);
+ break;
+
+ case 'h': // Vi mode
+ case 'q': // Vi mode
+ case 27: // ESC
+ i_current = i_choices-1; // Select last entry.
+
+ case 'l': // Vi mode
+ case 10: // Enter
+ case 32: // Space
+ keypad(p_window, 0);
+ return i_current;
+ }
+
+// window win_root(root);
+// win_root.print(i_choice);
+
+ wrefresh(p_window);
+ }
+}
+
+#endif
+
diff --git a/ycurses/src/curses/menu.h b/ycurses/src/curses/menu.h
new file mode 100644
index 0000000..3b672c3
--- /dev/null
+++ b/ycurses/src/curses/menu.h
@@ -0,0 +1,28 @@
+#ifndef MENU_H
+#define MENU_H
+
+#include "incl.h"
+#include "window.h"
+
+using namespace std;
+
+class menu
+{
+ private:
+ void init(vector<string>& vec_choices);
+
+ int i_choices, i_current;
+ ITEM** p_items;
+ MENU* p_menu;
+ window* p_win;
+
+ public:
+ menu(vector<string>& vec_choices);
+ menu(string s_name, vector<string>& vec_choices);
+ ~menu();
+
+ window& get_window();
+ int run();
+};
+
+#endif
diff --git a/ycurses/src/curses/pwindow.cpp b/ycurses/src/curses/pwindow.cpp
new file mode 100644
index 0000000..9ef2d80
--- /dev/null
+++ b/ycurses/src/curses/pwindow.cpp
@@ -0,0 +1,99 @@
+#ifndef PANEL_CPP
+#define PANEL_CPP
+
+#include "pwindow.h"
+
+pwindow::pwindow(window& r_win)
+{
+ p_window = &r_win;
+ init();
+}
+
+void
+pwindow::reinit(window& r_win)
+{
+ p_window = &r_win;
+ init();
+}
+
+pwindow::~pwindow()
+{
+ remove();
+}
+
+void
+pwindow::remove()
+{
+ if (p_panel)
+ {
+ del_panel(p_panel);
+ p_panel = 0;
+ }
+
+ update();
+}
+
+void
+pwindow::init()
+{
+ p_panel = new_panel(p_window->get_WINDOW());
+ update();
+}
+
+void
+pwindow::update()
+{
+ update_panels();
+ doupdate();
+}
+
+void
+pwindow::on_bottom()
+{
+ bottom_panel(p_panel);
+ update();
+}
+
+void
+pwindow::on_top()
+{
+ top_panel(p_panel);
+ update();
+}
+
+void
+pwindow::hide()
+{
+ hidden::hide();
+ hide_panel(p_panel);
+ update();
+}
+
+void
+pwindow::show()
+{
+ hidden::show();
+ show_panel(p_panel);
+ update();
+}
+
+void
+pwindow::move(coordinate& r_coord)
+{
+ move(r_coord.y, r_coord.x);
+}
+
+void
+pwindow::move(int y, int x)
+{
+ move_panel(p_panel, y, x);
+ update();
+}
+
+PANEL*
+pwindow::get_PANEL()
+{
+ return p_panel;
+}
+
+#endif
diff --git a/ycurses/src/curses/pwindow.h b/ycurses/src/curses/pwindow.h
new file mode 100644
index 0000000..49b1d75
--- /dev/null
+++ b/ycurses/src/curses/pwindow.h
@@ -0,0 +1,37 @@
+#ifndef PWINDOW_H
+#define PWINDOW_H
+
+using namespace std;
+
+#include "incl.h"
+#include "coordinate.h"
+#include "hidden.h"
+#include "window.h"
+
+class pwindow : public hidden
+{
+
+ private:
+ PANEL* p_panel;
+ window* p_window;
+ void init();
+
+ public:
+ pwindow(window& r_win);
+ ~pwindow();
+ void init(window& r_win);
+ void reinit(window& r_win);
+
+ void remove();
+ void on_bottom();
+ void on_top();
+ void hide();
+ void show();
+ void move(int y, int x);
+ void move(coordinate& r_coord);
+
+ static void update();
+ PANEL* get_PANEL();
+};
+
+#endif
diff --git a/ycurses/src/curses/tool.cpp b/ycurses/src/curses/tool.cpp
new file mode 100644
index 0000000..1bce76f
--- /dev/null
+++ b/ycurses/src/curses/tool.cpp
@@ -0,0 +1,37 @@
+#ifndef TOOL_CPP
+#define TOOL_CPP
+
+#include "tool.h"
+
+string
+tool::int2string(int i_int)
+{
+ char buf[64];
+ sprintf(buf, "%d", i_int);
+ return buf;
+}
+
+int
+tool::string2int(string s)
+{
+ const char *p = s.c_str();
+ int i_res = 0;
+
+ // Convert each digit char and add into result.
+ while (*p >= '0' && *p <='9')
+ {
+ i_res = (i_res * 10) + (*p - '0');
+ p++;
+ }
+
+ // Check that there were no non-digits at end.
+ if (*p != 0)
+ {
+ return -1;
+ }
+
+ return i_res;
+}
+
+#endif
+
diff --git a/ycurses/src/curses/tool.h b/ycurses/src/curses/tool.h
new file mode 100644
index 0000000..130bd09
--- /dev/null
+++ b/ycurses/src/curses/tool.h
@@ -0,0 +1,15 @@
+#ifndef TOOL_H
+#define TOOL_H
+
+#include "incl.h"
+
+using namespace std;
+
+class tool
+{
+public:
+ static string int2string( int i_int );
+ static int string2int( string s );
+};
+
+#endif
diff --git a/ycurses/src/curses/window.cpp b/ycurses/src/curses/window.cpp
new file mode 100644
index 0000000..d5ce37c
--- /dev/null
+++ b/ycurses/src/curses/window.cpp
@@ -0,0 +1,367 @@
+#ifndef WINDOW_CPP
+#define WINDOW_CPP
+
+#include "window.h"
+
+bool window::b_is_rootoot = false;
+
+window::window(window_type t)
+{
+ b_is_rootoot = true;
+ init();
+ p_window = stdscr;
+}
+
+window::window(int i_height, int i_width)
+{
+ init();
+
+ this->i_height = i_height;
+ this->i_width = i_width;
+ this->i_start_y = (LINES - i_height) / 2;
+ this->i_start_x = (COLS - i_width) / 2;
+
+ p_window = create_new_win(i_height, i_width, i_start_y, i_start_x);
+}
+
+window::window(int i_height, int i_width, coordinate& r_coord)
+{
+ init();
+
+ this->i_height = i_height;
+ this->i_width = i_width;
+ this->i_start_y = r_coord.y;
+ this->i_start_x = r_coord.x;
+
+ p_window = create_new_win(i_height, i_width, i_start_y, i_start_x);
+}
+
+window::window(int i_height, int i_width, int i_start_y, int i_start_x)
+{
+ init();
+
+ this->i_height = i_height;
+ this->i_width = i_width;
+ this->i_start_y = i_start_y;
+ this->i_start_x = i_start_x;
+
+ p_window = create_new_win(i_height, i_width, i_start_y, i_start_x);
+}
+
+window::~window()
+{
+ if (p_window)
+ {
+ if(!is_root_win())
+ destroy_win(p_window);
+
+ p_window = 0;
+ }
+}
+
+bool
+window::is_root_win()
+{
+ return b_is_rootoot;
+}
+
+void
+window::init()
+{
+}
+
+WINDOW*
+window::create_new_win(int i_height, int i_width, int i_start_y, int i_start_x)
+{
+ WINDOW *p_local_win = newwin(i_height, i_width, i_start_y, i_start_x);
+ box(p_local_win, 0 , 0); /* 0, 0 gives default characters
+ * for the vertical and horizontal
+ * lines */
+ wrefresh(p_local_win); /* Show that box */
+
+ return p_local_win;
+}
+
+void
+window::destroy_win(WINDOW *p_local_win)
+{
+ /* box(local_win, ' ', ' '); : This won't produce the desired
+ * result of erasing the window. It will leave it's four corners
+ * and so an ugly remnant of window.
+ */
+
+ wborder(p_local_win, ' ', ' ', ' ',' ',' ',' ',' ',' ');
+ /* The parameters taken are
+ * 1. win: the window on which to operate
+ * 2. ls: character to be used for the left side of the window
+ * 3. rs: character to be used for the right side of the window
+ * 4. ts: character to be used for the top side of the window
+ * 5. bs: character to be used for the bottom side of the window
+ * 6. tl: character to be used for the top left corner of the window
+ * 7. tr: character to be used for the top right corner of the window
+ * 8. bl: character to be used for the bottom left corner of the window
+ * 9. br: character to be used for the bottom right corner of the window
+ */
+
+ wrefresh(p_local_win);
+ delwin(p_local_win);
+}
+
+void
+window::hide()
+{
+ hidden::hide();
+
+ if (p_window)
+ destroy_win(p_window);
+}
+
+void
+window::show()
+{
+ if (!is_hidden())
+ return;
+
+ hidden::show();
+
+ p_window = create_new_win(i_height, i_width, i_start_y, i_start_x);
+
+ refresh();
+}
+
+void
+window::refresh()
+{
+ wrefresh(p_window);
+}
+
+void
+window::set_attributes(attributes& r_attr)
+{
+ r_attr.use_wattron(p_window);
+}
+
+void
+window::unset_attributes(attributes& r_attr)
+{
+ r_attr.use_wattroff(p_window);
+}
+
+int
+window::save_attributes()
+{
+ return attr_get(&sr_attributes, &sr_pair, sr_options);
+}
+
+int
+window::restore_attributes()
+{
+ return attr_set(sr_attributes, sr_pair, sr_options);
+}
+
+void
+window::print(int i)
+{
+ print(tool::int2string(i));
+}
+
+void
+window::print(coordinate &r_coord, string s)
+{
+ print(r_coord.y, r_coord.x, s);
+}
+
+void
+window::print(int i_y, int i_x, int i)
+{
+ print(i_y, i_x, tool::int2string(i));
+}
+
+void
+window::print(coordinate &r_coord, int i)
+{
+ print(r_coord, tool::int2string(i));
+}
+
+void
+window::println(int i)
+{
+ println(tool::int2string(i));
+}
+
+void
+window::println(coordinate &r_coord, string s)
+{
+ println(r_coord.y, r_coord.x, s);
+}
+
+void
+window::println(int i_y, int i_x, int i)
+{
+ println(i_y, i_x, tool::int2string(i));
+}
+
+void
+window::println(coordinate &r_coord, int i)
+{
+ println(r_coord, tool::int2string(i));
+}
+
+void
+window::print(string s)
+{
+ wprintw(p_window, const_cast<char*>(s.c_str()));
+ refresh();
+}
+
+void
+window::print(int i_y, int i_x, string s)
+{
+ mvwprintw(p_window, i_y, i_x, const_cast<char*>(s.c_str()));
+ refresh();
+}
+
+void
+window::println(string s)
+{
+ wprintw(p_window, const_cast<char*>((s+"\n").c_str()));
+ refresh();
+}
+
+void
+window::println(int i_y, int i_x, string s)
+{
+ mvwprintw(p_window, i_y, i_x, const_cast<char*>((s+"\n").c_str()));
+ refresh();
+}
+
+void
+window::print(int i, attributes& r_attr)
+{
+ save_attributes();
+ set_attributes(r_attr);
+ print(tool::int2string(i));
+ restore_attributes();
+}
+
+void
+window::print(coordinate &r_coord, string s, attributes& r_attr)
+{
+ save_attributes();
+ set_attributes(r_attr);
+ print(r_coord.y, r_coord.x, s);
+ restore_attributes();
+}
+
+void
+window::print(int i_y, int i_x, int i, attributes& r_attr)
+{
+ save_attributes();
+ set_attributes(r_attr);
+ print(i_y, i_x, tool::int2string(i));
+ restore_attributes();
+}
+
+void
+window::print(coordinate &r_coord, int i, attributes& r_attr)
+{
+ save_attributes();
+ set_attributes(r_attr);
+ print(r_coord, tool::int2string(i));
+ restore_attributes();
+}
+
+void
+window::println(int i, attributes& r_attr)
+{
+ save_attributes();
+ set_attributes(r_attr);
+ println(tool::int2string(i));
+ restore_attributes();
+}
+
+void
+window::println(coordinate &r_coord, string s, attributes& r_attr)
+{
+ save_attributes();
+ set_attributes(r_attr);
+ println(r_coord.y, r_coord.x, s);
+ restore_attributes();
+}
+
+void
+window::println(int i_y, int i_x, int i, attributes& r_attr)
+{
+ save_attributes();
+ set_attributes(r_attr);
+ println(i_y, i_x, tool::int2string(i));
+ restore_attributes();
+}
+
+void
+window::println(coordinate &r_coord, int i, attributes& r_attr)
+{
+ save_attributes();
+ set_attributes(r_attr);
+ println(r_coord, tool::int2string(i));
+ restore_attributes();
+}
+
+void
+window::print(string s, attributes& r_attr)
+{
+ save_attributes();
+ set_attributes(r_attr);
+ wprintw(p_window, const_cast<char*>(s.c_str()));
+ refresh();
+ restore_attributes();
+}
+
+void
+window::print(int i_y, int i_x, string s, attributes& r_attr)
+{
+ save_attributes();
+ set_attributes(r_attr);
+ mvwprintw(p_window, i_y, i_x, const_cast<char*>(s.c_str()));
+ refresh();
+ restore_attributes();
+}
+
+void
+window::println(string s, attributes& r_attr)
+{
+ save_attributes();
+ set_attributes(r_attr);
+ wprintw(p_window, const_cast<char*>((s+"\n").c_str()));
+ refresh();
+ restore_attributes();
+}
+
+void
+window::println(int i_y, int i_x, string s, attributes& r_attr)
+{
+ save_attributes();
+ set_attributes(r_attr);
+ mvwprintw(p_window, i_y, i_x, const_cast<char*>((s+"\n").c_str()));
+ refresh();
+ restore_attributes();
+}
+
+void
+window::move_cursor(coordinate& r_coord)
+{
+ move_cursor(r_coord.y, r_coord.x);
+}
+
+void
+window::move_cursor(int i_y, int i_x)
+{
+ if (!p_window)
+ return;
+
+ wmove(p_window, i_y, i_x);
+ refresh();
+}
+
+
+#endif
diff --git a/ycurses/src/curses/window.h b/ycurses/src/curses/window.h
new file mode 100644
index 0000000..d194e2f
--- /dev/null
+++ b/ycurses/src/curses/window.h
@@ -0,0 +1,85 @@
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include "attributes.h"
+#include "color.h"
+#include "coordinate.h"
+#include "dummy.h"
+#include "hidden.h"
+#include "incl.h"
+#include "tool.h"
+
+using namespace std;
+
+enum window_type
+{
+ root
+};
+
+class window : public dummy_window, hidden
+{
+ private:
+ WINDOW* p_window;
+ int i_height, i_width, i_start_y, i_start_x;
+ static bool b_is_rootoot;
+
+ /* For save_attributes and restore_attributes */
+ attr_t sr_attributes; short sr_pair; void *sr_options;
+
+ WINDOW *create_new_win(int i_height, int i_width, int i_start_y, int i_start_x);
+ void destroy_win(WINDOW *p_local_win);
+
+ /* Called by the constructors */
+ void init();
+
+ public:
+ window(window_type t);
+ window(int i_height, int i_width, coordinate& r_coord);
+ window(int i_height, int i_width, int i_start_y, int i_start_x);
+ window(int i_height, int i_width);
+ ~window();
+
+ void hide();
+ void show();
+ void refresh();
+ void set_attributes(attributes& r_attr);
+ void unset_attributes(attributes& r_attr);
+ bool is_root_win();
+
+ WINDOW* get_WINDOW() { return p_window; }
+
+ int save_attributes();
+ int restore_attributes();
+
+ void move_cursor(coordinate& r_coord);
+ void move_cursor(int i_y, int i_x);
+
+ void print(string s);
+ void print(int i_y, int i_x, string s);
+ void println(string s);
+ void println(int i_y, int i_x, string s);
+ void print(int i);
+ void print(coordinate &r_coord, string s);
+ void print(int i_y, int i_x, int i);
+ void print(coordinate &r_coord, int i);
+ void println(int i);
+ void println(coordinate &r_coord, string s);
+ void println(int i_y, int i_x, int i);
+ void println(coordinate &r_coord, int i);
+
+ void print(string s, attributes& r_attr);
+ void print(int i_y, int i_x, string s, attributes& r_attr);
+ void println(string s, attributes& r_attr);
+ void println(int i_y, int i_x, string s, attributes& r_attr);
+ void print(int i, attributes& r_attr);
+ void print(coordinate &r_coord, string s, attributes& r_attr);
+ void print(int i_y, int i_x, int i, attributes& r_attr);
+ void print(coordinate &r_coord, int i, attributes& r_attr);
+ void println(int i, attributes& r_attr);
+ void println(coordinate &r_coord, string s, attributes& r_attr);
+ void println(int i_y, int i_x, int i, attributes& r_attr);
+ void println(coordinate &r_coord, int i, attributes& r_attr);
+};
+
+#endif
+
diff --git a/ycurses/src/curses/ycurses.h b/ycurses/src/curses/ycurses.h
new file mode 100644
index 0000000..1699e96
--- /dev/null
+++ b/ycurses/src/curses/ycurses.h
@@ -0,0 +1,6 @@
+#ifndef YCURSES_H
+#define YCURSES_H
+
+#include "curses.h"
+
+#endif
diff --git a/ycurses/src/examples/example1.cpp b/ycurses/src/examples/example1.cpp
new file mode 100644
index 0000000..239e476
--- /dev/null
+++ b/ycurses/src/examples/example1.cpp
@@ -0,0 +1,80 @@
+#include "example1.h"
+
+int example1()
+{
+ /* Initialize the ycurses object at first! You MUST also delete this as the last! */
+ curses cur;
+
+ /* Make the cursor invisible.
+ * All available options are:
+ * Invisible
+ * Visible
+ * VeryVisible
+ */
+ cursor::set_invisible();
+
+ /* Get the root-window */
+ window win_root(root);
+
+ /*
+ * There are standard colors defined which can be mixed together to
+ * get foreground/background color pairs:
+ * Red, Green, Yellow, Blue, Cyan, Magenta and White
+ */
+ color col1(Cyan, Blue); // 1. With implicit Name.
+ // color col1("col1", Cyan, Blue); // 2. With explicit Name.
+
+ /* Now we define attributes, and pass them the color */
+ attributes attr1(col1);
+ win_root.set_attributes(attr1);
+
+ /* Print out some text on the cursor location, with line break */
+ win_root.println(0, 0, "Hello, welcome to ncurses in cyan-blue");
+
+ win_root.unset_attributes(attr1);
+
+ /* Create a new centeralized window with the specified height and width */
+ window win1(20, 78);
+
+ color col2(Yellow, Black);
+ attributes attr2(col2);
+ attr1.set_bold(true);
+
+ win1.set_attributes(attr2);
+ win1.print(2, 2, "Print into window at pos 2-2 w/out newline in yellow-black-bold!");
+
+ /* Create yet another window */
+ window win2(10, 20);
+
+ /* Print out the y and the x component of the absolute coordinates of win1 */
+ coordinate coord_win(Absolutecoord,win1);
+ coordinate coord_text(10,11);
+
+ /* Other available coordinates
+ *
+ * coordinate(Absolutecoord,win1); // Gets window's absolute position.
+ * coordinate(Relativecoord,win1); // Gets window's relative position.
+ * coordinate(Beginningcoord,win1); // Gets window's beginning coords.
+ * coordinate(windowSize,win1); // Gets window's size.
+ * coordinate(TerminalSize); // Gets the total terminal size.
+ * coordinate(TerminalCenter); // Gets the center of the terminal
+ */
+
+ attributes attr_bold(Bold);
+ // Hint: you can use Normal instead of Bold to set all attributes to default.
+
+ win_root.print(coord_text, "Demonstration output", attr_bold);
+ win_root.print(coord_text.down(), "coordinate y:");
+ win_root.print(coord_text.displace(1,1), coord_win.y, attr_bold);
+ win_root.print(coord_text.displace(1,-1), "coordinate x:");
+ win_root.print(coord_text.displace(1,1), coord_win.x, attr_bold);
+
+ /* Wait for user key stroke */
+ cur.pause();
+
+ /* Deletes all curses elements from memory, also all pointers
+ Because the ycurses Objekt will get out of scope now.
+ */
+ return 0;
+}
+
diff --git a/ycurses/src/examples/example1.h b/ycurses/src/examples/example1.h
new file mode 100644
index 0000000..dc5e753
--- /dev/null
+++ b/ycurses/src/examples/example1.h
@@ -0,0 +1,8 @@
+#ifndef EXAMPLE1_H
+#define EXAMPLE1_H
+
+#include "../curses/ycurses.h"
+
+int example1();
+
+#endif
diff --git a/ycurses/src/examples/example2.cpp b/ycurses/src/examples/example2.cpp
new file mode 100644
index 0000000..c93d79c
--- /dev/null
+++ b/ycurses/src/examples/example2.cpp
@@ -0,0 +1,52 @@
+#include "example2.h"
+
+int example2()
+{
+ curses cur;
+ cursor::set_invisible();
+
+ window win_root(root);
+ win_root.print(1, 1, "Press any key to continue...");
+
+ coordinate coord(2, 0);;
+
+ window win1(10, 40, coord);
+ window win2(10, 40, coord.displace(3, 6));
+ window win3(10, 40, coord.displace(3, 6));
+
+ win1.print(1, 1, "window 1");
+ win2.print(1, 1, "window 2");
+ win3.print(1, 1, "window 3");
+
+ /* Initialize pwindows. */
+ pwindow pwindow1(win1);
+ pwindow pwindow2(win2);
+ pwindow pwindow3(win3);
+
+
+ /* Remove pwindow3, pwindow3 doesnt contain a valid pwindow any more!
+ * DONT USE THIS OBJECT AGAIN until re-init!!!
+ */
+ pwindow3.remove();
+
+ /* Re-init a new pwindow, using the old variable. Now the object
+ * can be used again.
+ */
+ pwindow3.reinit(win3);
+ cur.pause();
+
+ /* Remove the center pwindow. */
+ pwindow2.remove();
+ win3.print(2, 1, "pwindow 2 removed!");
+ cur.pause();
+
+ win1.print(2, 1, "Some text!");
+ cur.pause();
+
+ pwindow3.remove();
+ win1.print(3, 1, "pwindow 3 removed!");
+ cur.pause();
+
+ return 0;
+}
+
diff --git a/ycurses/src/examples/example2.h b/ycurses/src/examples/example2.h
new file mode 100644
index 0000000..fbdc6c7
--- /dev/null
+++ b/ycurses/src/examples/example2.h
@@ -0,0 +1,8 @@
+#ifndef EXAMPLE2_H
+#define EXAMPLE2_H
+
+#include "../curses/ycurses.h"
+
+int example2();
+
+#endif
diff --git a/ycurses/src/examples/example3.cpp b/ycurses/src/examples/example3.cpp
new file mode 100644
index 0000000..5fee1f8
--- /dev/null
+++ b/ycurses/src/examples/example3.cpp
@@ -0,0 +1,45 @@
+#include "example3.h"
+
+int example3()
+{
+ curses cur;
+ cursor::set_invisible();
+
+ window win_root(root);
+ win_root.print(1, 1, "Press any key to continue...");
+
+ coordinate coord(2, 0);;
+ window win1(10, 30, coord);
+ window win2(10, 30, coord.displace(3, 6));
+
+ win1.print(1, 1, "pwindow 1");
+ win2.print(1, 1, "pwindow 2");
+
+ pwindow pwindow1(win1);
+ pwindow pwindow2(win2);
+
+ cur.pause();
+
+ pwindow1.hide();
+ win2.print(2, 1, "pwindow 1 hidden");
+ cur.pause();
+
+ pwindow1.show();
+ pwindow1.on_bottom();
+ win2.print(3, 1, "pwindow 1 back");
+ cur.pause();
+
+ win1.print(2, 1, "Some pwindow 1 text");
+ cur.pause();
+
+ pwindow1.on_top();
+ win1.print(3, 1, "pwindow 2 is on bottom");
+ cur.pause();
+
+ win1.print(4, 1, "Moved pwindow 2 to 10-10");
+ pwindow2.move(10,10);
+ cur.pause();
+
+ return 0;
+}
+
diff --git a/ycurses/src/examples/example3.h b/ycurses/src/examples/example3.h
new file mode 100644
index 0000000..80f1575
--- /dev/null
+++ b/ycurses/src/examples/example3.h
@@ -0,0 +1,8 @@
+#ifndef EXAMPLE3_H
+#define EXAMPLE3_H
+
+#include "../curses/ycurses.h"
+
+int example3();
+
+#endif
diff --git a/ycurses/src/examples/example4.cpp b/ycurses/src/examples/example4.cpp
new file mode 100644
index 0000000..7e0e317
--- /dev/null
+++ b/ycurses/src/examples/example4.cpp
@@ -0,0 +1,22 @@
+#include "example4.h"
+
+int example4()
+{
+ curses cur;
+ cursor::set_invisible();
+
+ window win_root(root);
+ win_root.print(1, 1, "Class menu example...");
+
+ vector<string> vec_choices;
+ vec_choices.push_back("Hallo das ist asd asdas d asd asda sd asd asd a");
+ vec_choices.push_back("Bdsfsdsa das d asd asd asd as das djf");
+ vec_choices.push_back("s das d asd saa sdCsdfsdf");
+ menu menu1(vec_choices);
+
+ menu1.run();
+
+ return 0;
+}
+
+
diff --git a/ycurses/src/examples/example4.h b/ycurses/src/examples/example4.h
new file mode 100644
index 0000000..1bf0cbb
--- /dev/null
+++ b/ycurses/src/examples/example4.h
@@ -0,0 +1,8 @@
+#ifndef EXAMPLE4_H
+#define EXAMPLE4_H
+
+#include "../curses/ycurses.h"
+
+int example4();
+
+#endif
diff --git a/ycurses/src/glob.h b/ycurses/src/glob.h
new file mode 100644
index 0000000..d37ae37
--- /dev/null
+++ b/ycurses/src/glob.h
@@ -0,0 +1,21 @@
+/*
+ Notice:
+
+ All #defines which start with an CONFIG can be edited through
+ gmake config in the main directory!
+*/
+
+// global variables.
+#ifndef GLOB_H
+#define GLOB_H
+
+// Definition of boolean values.
+#define true 1
+#define false 0
+
+/* - DISABLED -
+ Enable debugging options.
+*/
+//#define DEBUG
+
+#endif
diff --git a/ycurses/src/main.cpp b/ycurses/src/main.cpp
new file mode 100644
index 0000000..1ede8da
--- /dev/null
+++ b/ycurses/src/main.cpp
@@ -0,0 +1,110 @@
+#include <iostream>
+#include <signal.h>
+
+#include "curses/ycurses.h"
+#include "examples/example1.h"
+#include "examples/example2.h"
+#include "examples/example3.h"
+#include "examples/example4.h"
+
+using namespace std;
+
+static void finish_demo(int i_signal);
+
+int main(int argc, char* argv[])
+{
+ /* Catch SIGINT for proper shutdown */
+ signal(SIGINT, finish_demo);
+
+ curses cur;
+
+ color col(Red,Black);
+ attributes attr(col);
+ attr.set_bold(true);
+
+ coordinate coord(5,5);
+
+ for (;;)
+ {
+ cursor::set_invisible();
+
+ window win_root(root);
+ win_root.print(1, 2, "Examples of ycurses", attr);
+ win_root.print(2, 2, "See src/examples/* for the sample code!");
+
+ vector<string> vec_choices;
+ vec_choices.push_back("1. Example with mixed stuff");
+ vec_choices.push_back("2. Class pwindow basic usage");
+ vec_choices.push_back("3. Class pwindow usage #2");
+ vec_choices.push_back("4. Class menu usage");
+ vec_choices.push_back("5. Move menu left");
+ vec_choices.push_back("6. Move menu right");
+ vec_choices.push_back("7. Move menu up");
+ vec_choices.push_back("8. Move menu down");
+ vec_choices.push_back("9. Exit");
+
+ menu menu(vec_choices);
+ window& menu_window = menu.get_window();
+ pwindow pan(menu_window);
+ pan.move(coord);
+
+ switch ( menu.run() )
+ {
+ case 0:
+ cur.clear();
+ pan.hide();
+ example1();
+ break;
+
+ case 1:
+ pan.hide();
+ cur.clear();
+ example2();
+ break;
+
+ case 2:
+ pan.hide();
+ cur.clear();
+ example3();
+ break;
+
+ case 3:
+ pan.hide();
+ cur.clear();
+ example4();
+ break;
+
+ case 4:
+ pan.move(coord.left());
+ break;
+
+ case 5:
+ pan.move(coord.right());
+ break;
+
+ case 6:
+ pan.move(coord.up());
+ break;
+
+ case 7:
+ pan.move(coord.down());
+ break;
+
+ case 8:
+ return 0;
+ }
+
+ cur.clear();
+ pan.show();
+ }
+
+ return 0;
+}
+
+static void finish_demo(int i_signal)
+{
+ curses::finish();
+
+ cout << "Process received SIGINT" << endl;
+ exit(0);
+}
diff --git a/ycurses/src/msgs.h b/ycurses/src/msgs.h
new file mode 100644
index 0000000..355aa45
--- /dev/null
+++ b/ycurses/src/msgs.h
@@ -0,0 +1,11 @@
+#ifndef MSGS_H
+#define MSGS_H
+
+#define APPNAME "curses"
+#define VERSION "0.1"
+#define BRANCH "CURRENT"
+#define BUILDNR 1661
+#define UNAME "FreeBSD 5.3-RELEASE-p15 i386"
+#define COMPOPT "Using built-in specs.; Configured with: FreeBSD/i386 system compiler; Thread model: posix; gcc version 3.4.2 [FreeBSD] 20040728; 3.4; g++"
+
+#endif
diff --git a/yhttpd/COPYING b/yhttpd/COPYING
new file mode 100644
index 0000000..27058a5
--- /dev/null
+++ b/yhttpd/COPYING
@@ -0,0 +1,338 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/yhttpd/INSTALL b/yhttpd/INSTALL
new file mode 100644
index 0000000..b112205
--- /dev/null
+++ b/yhttpd/INSTALL
@@ -0,0 +1 @@
+See the README file.
diff --git a/yhttpd/Makefile b/yhttpd/Makefile
new file mode 100644
index 0000000..a33780f
--- /dev/null
+++ b/yhttpd/Makefile
@@ -0,0 +1,90 @@
+MAKE=`tail -n 1 make.version`
+PREFIX=`grep "define PREFIX" src/glob.h | cut -d'"' -f2`
+all: version base modules
+ @echo "Now edit the yhttpd.conf and run yhttpd!"
+ @echo "The config file is searched in the following order:"
+ @echo " ./yhttpd.conf "
+ @echo " ~/.yhttpd/yhttpd.conf "
+ @echo " ./etc/yhttpd.conf "
+ @echo " /etc/yhttpd.conf "
+ @echo " $(PREFIX)/etc/yhttpd.conf "
+ @echo If you want to help the yhttpd project please run gmake mail
+ @echo so that the developers receive an email about the platform
+ @echo being used.
+ @echo WARNING! This software is EXPERIMENTAL!
+mail:
+ @echo "VERSION:" > mail.tmp
+ @${MAKE} version >> mail.tmp
+ @echo >> mail.tmp
+ @echo "UNAME:" >> mail.tmp
+ @uname -a >> mail.tmp
+ @echo >> mail.tmp
+ @echo "DATE:" >> mail.tmp
+ @date >> mail.tmp
+ @echo >> mail.tmp
+ @echo "COMPILER AND MAKE:" >> mail.tmp
+ @cat g++.version make.version >> mail.tmp
+ @cat mail.tmp | mail -s "Successfull build of yhttpd" successfullbuild@yChat.org
+ @rm -f mail.tmp
+install: deinstall
+uninstall: deinstall
+deinstall:
+ @echo Install/deinstall is not supported!
+ @echo Start yhttpd with ./bin/yhttpd instead!
+ @exit 1
+modules:
+ @if test -d ./src/mods; then ${MAKE} -C ./src/mods; fi
+clean_modules:
+ @if test -d ./src/mods; then ${MAKE} -C ./src/mods clean; fi
+base:
+ @if test -f bin/yhttpd; then echo "Backing up old binary";if test -f bin/yhttpd.old; then rm -f bin/yhttpd.old; fi; mv bin/yhttpd bin/yhttpd.old; fi
+ @perl ./scripts/buildnr.pl
+ @perl ./scripts/setglobvals.pl
+ @${MAKE} -C ./src
+clean_base:
+ @${MAKE} -C ./src clean
+stats:
+ @perl scripts/stats.pl
+run:
+ ./bin/yhttpd
+base_start: base
+ ./bin/yhttpd
+gpl:
+ @more COPYING
+clean: clean_base clean_modules
+help:
+ @echo "You may run ${MAKE} with the following parameters:"
+ @grep "^ ${MAKE} " README
+ @echo "For more questions read the README file or contact mail@yChat.org!"
+setup:
+ @./configure
+ @${MAKE}
+config:
+ @sh -c "scripts/config.sh"
+ @echo If you run ${MAKE} config from the command line then you may need
+ @echo to rerun ./configure and recompile all now!
+
+mrproper: clean
+ @if test -f src/glob.h.org; then mv -f src/glob.h.org src/glob.h;fi
+ @if test -f g++.version; then rm -f g++.version; fi
+ @if test -f make.version; then rm -f make.version; fi
+ @if test -f src/Makefile; then rm -f src/Makefile; fi
+ @if test -f bin/yhttpd; then find bin/ -name "*yhttpd*" | xargs rm -f; fi
+ @if test -d src/mods; then find src/mods/*/ -name Makefile | xargs rm -f; fi
+ @find . -name "*.add" | xargs rm -f
+ @ls | grep core | xargs rm -f
+version:
+ @./scripts/version.sh
+debug:
+ @gdb bin/yhttpd yhttpd.core
+confdebug:
+ ./configure -g3 -ggdb
+dist:
+ @./scripts/makedist.sh
+ssltest:
+ openssl genrsa -des3 -out privkey.pem 2048
+ openssl req -new -x509 -key privkey.pem -out cert.pem -days 1095
+ @mv -f privkey.pem cert.pem etc
+
+
+
diff --git a/yhttpd/README b/yhttpd/README
new file mode 100644
index 0000000..5fa183e
--- /dev/null
+++ b/yhttpd/README
@@ -0,0 +1,462 @@
+yhttpd; Homepage: www.yChat.org; Version 0.8-CURRENT
+
+Copyright (C) 2003 Paul C. Buetow, Volker Richter
+Copyright (C) 2004 Paul C. Buetow
+Copyright (C) 2005 EXA Digital Solutions GbR
+-----------------------------------------------------------------
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-----------------------------------------------------------------
+
+YHTTPD TABLE OF CONTENTS:
+
+1.0 GENERAL
+1.1 ABOUT DEVELS
+2.0 INSTALLATION AND SETUP
+2.1 REQUIREMENTS
+2.2 TESTED PLATFORMS
+2.3 HOW TO OBTAIN YHTTPD
+2.4 INSTALLATION QUICK-START
+2.4 INSTALLATION
+2.3 HOW TO USE OPENSSL WITH YHTTPD
+2.3 HOW TO USE SCREEN WITH YHTTPD
+2.3 HOW TO USE SIGNALS WITH YHTTPD
+2.4 CONFIGURING YHTTPD
+3.0 EXTENDING YHTTPD
+3.1 SOURCE FILES
+4.0 DIVERSE
+4.1 WRITING BUG REPORTS
+4.2 CONTACT ADDRESSES
+4.3 CREDITS
+
+1.0 GENERAL
+
+1.1 ABOUT DEVELS
+
+There are several projects involved:
+
+- The chat -
+Its a HTTP based chat server written in C++. Clients are normal web browsers
+such as MSIE or Gecko based browsers using only CSS, HTML and JavaScript.
+
+- The httpd -
+Its a small http server based on the chat's socket and threading engine.
+yhttpd does not have as much features but is easy to use and faster than
+apache. yhttpd is a subset of the chat. It can be generated using the
+srcipts/yhttpdbase.pl script in the chat's source tree.
+
+- The ycurses -
+ycurses is a easy to use and small C++ wrapper around the C ncurses API.
+
+There are different branches:
+
+- CURRENT -
+The CURRENT branch is unstable, this is the bleeding developing edge with
+all the new experimental features.
+
+A DEVEL of CURRENT can be referred as CURRENTDEVEL.
+
+- STABLE -
+The STABLE branch is more stable than CURRENT. This branch may get new
+features as well. But those will be more conservative compared to
+CURRENT.
+
+A DEVEL of STABLE can be referred as STABLDEVEL.
+
+- LEGACY -
+The LEGACY branch has no real support. This branch may get bugfixes and
+updates and might get minor improvements. But there is no garuantee to
+be bug free and stable at all. LEGACY versions are of historic meaning.
+
+- DEVEL -
+DEVEL is only a meta name. If a version is labeled with DEVEL, then its
+currently undefined if this is a CURRENT, STABLE or LEGACY branch. It
+can be everything. Commonly DEVEL versions are CURRENT.
+
+There are also releases made:
+
+- DEVEL -
+There can be DEVELs made out of each branch. While a branch can get
+new features, a DEVEL can not. A DEVEL of a branch is just like
+a snapshot. DEVELs are complete versions to test and use. But keep
+in mind, that a DEVEL of the STABLE branch is recommended over a
+DEVEL of a CURRENT or a LEGACY branch in a production environment.
+DEVELs of CURRENT are still the bleeding edge and DEVELs of LEGACY
+may be out of date.
+
+- Short names -
+
+In addition, each description also has short names: (short names are needed
+if your text space is limited which happens very fast in IRC channel topics)
+
+CURRENT aka CUR aka C
+DEVEL aka REL aka R
+LEGACY aka LEG aka L
+STABLE aka SBL aka S
+DEVEL aka DEV aka D
+PRE aka P
+
+STABLDEVEL aka STBREL aka SR
+DEVEL aka PREREL aka PR
+PRELEGACYDEVEL aka PRELEGREL aka PLR
+etc...
+
+The short name of the chat is "yC"
+The short name of the httpd is "yh"
+The short name of ycurses is "yu"
+
+- Versioning -
+In general, versions are made up like X.Y.Z.W. X specifies the major version,
+Y specifies the branch of the major version, Z specifies a sub revision
+of a specific branch. The optional W can be used to specify a maintenance
+revision which only changes small issues. Version numbers can be also normal
+alphabetic characters. Example: Version 0.7.A follows 0.7. Version 0.T.Y.2
+would be also valid.
+
+Therefore: The lowest value is 0, the highest possible value is Z.
+
+
+2.0 INSTALLATION AND SETUP
+
+2.1 REQUIREMENTS:
+
+- GNU GCC G++
+ The GNU C++ compiler version 3.1 or up.
+
+- GNU make 3.80 (gmake) or higher
+ If you dont have a gmake executable but make is gnu make then you need
+ to add a symlink or alias from gmake to make.
+ yhttpd Makefiles only have been tested with GNU make and may not work with
+ other make versions.
+
+- SGI STL extension
+ Includes ext/hash_map which may be already default on every Linux distro.
+ On *BSD you have to install it first before compiling. On FreeBSD
+ /usr/ports/devel/stlport is your friend.
+
+- OpenSSL
+ Includes libssl and the ssl header files of the open source SSL library.
+ OpenSSL is only needed if you chose to compile yhttpd w/OpenSSL support.
+
+- ncurses 5.x
+ Includes libncurses and the ncurses.h header files.
+
+- Screen
+ Only needed if yhttpd should run in background with
+ ncurses or CLI enabled.
+
+- Perl 5.x
+ Is needed for some scripts. Is not needed if you use precompiled binaries.
+
+2.1 TESTED PLATFORMS:
+
+The following platforms have been tested with success. If you find out that
+a listed platform did not work at all please contact me:
+
+ Operating system (arch) GNU G++ GNU make
+- FreeBSD 5.4-DEVEL (i386) 3.4 3.80
+- FreeBSD 5.3-DEVEL (i386) 3.4 3.80
+
+ Tested longer time before:
+- FreeBSD 5.2-DEVEL (i386) 3.3 3.80
+- FreeBSD 4.10-DEVEL (i386) 3.4 3.80
+- FreeBSD 4.9-DEVEL (i386) 3.3 3.80
+- Gentoo Linux 2004 (i386) 3.3 3.80
+- OpenBSD 3.6 SMP (i386) 3.3 3.80
+- Red Hat Linux 8.0 SMP (i386) 3.2-7 3.79
+- Slackware Linux 10.0 (i386) 3.4 3.80
+- SUSE Linux 9.0 (i386) 3.3 3.80
+- SUSE Linux 8.1 (i386) 3.2 3.79
+
+Other platforms like Linux based systems, other BSD-Systems or UNICES
+are very likely to work too.
+
+2.3 HOW TO OBTAIN YHTTPD:
+
+yhttpd can be downloaded as a source package or through CVS.
+
+The packages are located at http://www.yChat.org -> Sourcecode ->
+Packages or go to http://pub.buetow.org/yhttpd/yhttpd .
+
+For CVS download type:
+
+cvs -d:pserver:anonymous@buetow.org:/usr/home/cvs/cvsroot login
+( You will be asked for a password. Use "just enter" ).
+
+vs -z3 -d:pserver:anonymous@buetow.org:/usr/home/cvs/cvsroot co BRANCH
+( The sources will be copied into your local folder )
+
+cvs -d:pserver:anonymous@buetow.org:/usr/home/cvs/cvsroot logout
+( Logs your CVS session out ).
+
+Now you may continue with the installation.
+
+here are different branches in the CVS:
+
+yhttpd: This is the latest CURRENT branch of yhttpd.
+yhttpd-stable: This is the latest STABLE branch of yhttpd.
+yhttpd-X.Y: This is the branch with the specified version prefix.
+yhttpd: This is the latest CURRENT snapshot of yhttpd.
+
+The CURRENT branch of yhttpd is mostly untested and unstable, so don't
+cry if you get errors.
+
+2.4 INSTALLATION QUICK START
+
+If you in hury, then you may just type gmake setup. In the yhttpd configurator
+you may just choose all the default values. If done, yhttpd will get compiled
+and is ready to run with ./bin/yhttpd! If you chose OpenSSL support, then
+also run gmake ssltest before starting yhttpd.
+
+2.3 INSTALLATION
+
+Invoke "./configure". Afterwards you will get prompted with the before-compile
+options of yhttpd. After choosing those options you are ready to type "gmake"
+afterwards. See below what gmake is doing.
+
+
+You may also invoke gmake with the following options (the PREFIX can be set
+in the yhttpd configurator which will be launched by the top configure script
+or gmake config):
+
+ gmake or gmake all (compiles everything, also modules and runs "gmake mail")
+ gmake base (only compiles the base)
+ gmake base_start (only compiles the base and starts the server)
+ gmake clean (cleans everything)
+ gmake clean_base (only cleans the base obj and rpo files)
+ gmake clean_modules (only cleans the modules .so files)
+ gmake confdebug (runs ./configure with enabling debugging)
+ gmake config (runs yhttpd configurator)
+ gmake debug (runs gdb on ./yhttpd.core)
+ gmake dist (creates a .tar.bz2 ball)
+ gmake gpl (shows the GNU General Public License)
+ gmake help (shows all available yhttpd gmake targets)
+ gmake mail (sends a mail to the yhttpd developers containing build opts.)
+ gmake modules (only compiles modules)
+ gmake mrproper (same as gmake clean plus removing all temp files)
+ gmake setup (runs all configure scripts and afterwards gmake all)
+ gmake stats (generates yhttpd statistics)
+ gmake ssltest (generates a self signed ssl test certificate)
+ gmake version (shows the current version of yhttpd)
+
+Example: "gmake all install clean" compiles everything, installs it to PREFIX
+and cleans the source directories.
+
+Now its time to run the server with ./bin/yhttpd.
+
+Aferwards point your webbrowser to http://yourip:port !
+
+... have fun :-).
+
+2.3 HOW TO USE OPENSSL WITH YHTTPD
+
+If you chose to use OpenSSL support you have to have a valid SSL private and
+public key. If you are in hurry, use the gmake ssltest command from the top
+source tree directory and follow the instructions. Otherwise type the
+following commands manually:
+
+The private key can be created w/the following command:
+
+ openssl genrsa -des3 -out privkey.pem 2048
+
+Afterwards, you can create a self-signed test certificate using the following
+command:
+
+ openssl req -new -x509 -key privkey.pem -out cert.pem -days 1095
+
+Be sure to move the privkey.pem and cert.pem files into the ./etc directory
+or edit the path names in the ./etc/yhttpd.conf file. yhttpd wont start if there
+are no valid files found.
+
+To learn more about SSL certificates, visit http://www.openssl.org/docs/HOWTO/.
+
+Now use https:// and NOT http:// to connect to the yhttpd server.
+
+
+2.3 HOW TO USE SCREEN WITH YHTTPD:
+
+If you are running yhttpd in ncurses mode you might want to install
+the tool which is called "screen". This will enable you putting the
+ncurses interface into the background, closing the terminal session
+and reusing the interface later through another terminal.
+
+Just do:
+
+ screen -S yhttpd ./bin/yhttpd ( creates a new session and starts yhttpd in it )
+ ctrl+d+a ( will detach the yhttpd session )
+ ( closing the terminal )
+ ( opening a new terminal )
+ screen -r yhttpd ( will return you to the yhttpd process )
+
+Screen will terminate automaticaly if all processes in its sessions are
+terminated.
+
+For a closer look read the screen manual page ( man screen ).
+
+2.3 HOW TO USE SIGNALS WITH YHTTPD:
+
+You can send UNIX signals to yhttpd. This becomes very interesting if you
+don't use the command line interface or the ncurses interface and you
+don't have access to the options below.
+
+Run one of the following commands to send the signal you want:
+($PID is here the process id of the current yhttpd process)
+
+kill -USR1 $PID # yhttpd clears the HTML template cache
+kill -HUP $PID # yhttpd will shutdown savely
+
+2.4 CONFIGURING YHTTPD:
+
+If you like to customize the design/layout/language of yhttpd, you will have
+to edit src/msgs.h and src/glob.h before you compile the sources. Afterwards
+you can change the html-template files which are placed in the html/
+subdirectory and the language-templates which are placed in the XML config
+file (etc/yhttpd.conf).
+
+Notice, that you dont have to edit the src/glob.h file by hand any more, its
+already done by the top ./configure script for you.
+
+You can edit the etc/yhttpd.conf to fit your needs. If you dont want to change
+the config file, then you also can use yhttpd start parameters.
+
+Exmpl: ./bin/yhttpd -o chat.database.password secretpassword
+
+You can also use multiple words for a specific option.
+
+Exmpl: ./bin/yhttpd -o yhttpd.version "word1 word2 word3"
+
+will overwrite the default database password value of the yhttpd.conf. You can
+do this with every configuration element by adding several -o option value
+arguments to the start command.
+
+Dynamic loadable modules can be found in the mods/ subdirectory. (chat
+commands are realized through modules too). Sources of modules can be found
+in src/mods instead. If you want to create a new module just create a new
+.cpp file and run in src/mods the ./configure script again. Next time
+you run gmake your new module gets compiled.
+
+All messages defined in the msgs.h file contain server messages only ( a chat
+user never wont read them, only the administrator will get to see them ).
+
+Read also section 3.0 of this README.
+
+
+3.0 EXTENDING YHTTPD
+
+3.1 SOURCE FILES
+
+This list is not complete. Only the most important files are listed here!
+
+etc/yhttpd.conf - The yhttpd configuration file
+html/* - The html template files
+src/* - The yhttpd base sources
+src/mods/* - The dynamic loadable modules sources
+scripts/* - Some nice scripts needed for building & co.
+
+The following is created by building yhttpd:
+obj/* - The object files of the compiled yhttpd base
+mods/* - The compiled dynamic loadable modules
+bin/yhttpd - The yhttpd binary (linked by the object files)
+
+Customizable source files (if changed you need to run gmake clean all)
+src/glob.h - Contains some global building options
+src/msgs.h - Defines some server side messages
+
+
+4.0 DIVERSE
+
+4.1 WRITING BUG REPORTS
+
+How to submit a good bug report?
+
+Send them to Mail at yhttpd dot org.
+
+First you should give the following information:
+- yhttpd version, if CVS (or devel. tarball) then which day?
+- operating system / distribution and it's version
+- when did it crash? did you do something? can you reproduce the crash?
+
+Getting backtrace of the crash also helps a lot, especially if yhttpd crashes
+randomly. If after crash you see text:
+
+ "segmentation fault (core dumped)"
+
+It writes a file named "core" or "yhttpd.core" depending on your OS to directory
+where you started yhttpd. If it doesn't print the "(core dumped)" or you can't
+find the core file, you'll have to raise the limit for max. core file size
+before running yhttpd. To do this, say:
+
+ ulimit -c unlimited
+
+So, if you have the core file and GNU debugger (gdb), you can get the
+backtrace with:
+
+ gdb ./bin/yhttpd yhttpd.core
+ bt
+
+Paste all the lines starting from line having #0 at the beginning.
+
+Here's an example session:
+
+ in reqp::parse(thrd*, std::string, std::map<std::string, std::string,
+ std::less<std::string>, std::allocator<std::pair<std::string const, std::string> > >&) ()
+ (gdb) bt
+ #0 0x0805c287 in reqp::parse(thrd*, std::string, std::map<std::string,
+ std::string, std::less<std::string>, std::allocator<std::pair<std::string
+ const, std::string> > >&) ()
+ #1 0x0806060f in sock::read_write(thrd*, int) ()
+ #2 0x080612ba in thrd::run() ()
+ #3 0x0805a3b8 in pool::run_func(void*) ()
+ #4 0x0805a375 in pool::tpool_thread(void*) ()
+ #5 0x281d44ae in _thread_start () from /usr/lib/libc_r.so.5
+ (gdb)
+
+If you dont get such a gdb output, you need to recompile the yhttpd using
+debuggig symbols. You can do it this way:
+
+gmake clean confdebug all run
+
+4.2 CONTACT ADDRESSES
+
+You may contact us through the following addresses:
+
+- Homepage
+ The yhttpd homepage is located at http://www.yChat.org
+ The EXA Digital Solutions homepage is located at http://www.exa-ds.com
+
+- E-Mail
+ Paul C. Buetow: buetow at yhttpd point org ( core developer )
+ Mail at yhttpd dot org ( reaches everybody of yhttpd )
+
+- ICQ
+ Paul C. Buetow: 11655527
+
+- IRC
+ #Ychat and #Coding at irc.german-elite.net
+
+- EXA Digital Solutions GbR
+ Laubenstr. 16b
+ D-44866 Bochum
+ Germany
+
+4.2 CREDITS
+
+Thanks to the following persons. Without them yhttpd would not be like today:
+
+- Volker Richter <volker at exa-ds dot de> of EXA Digital Solutions GbR
+ for adding initial MySQL support and lots of more code.
+
+- Joshua Teitelbaum <joshuat at cryptomail.org> of CryptpMail.org for adding
+ initial OpenSSL support and lots of security patches in the HTTP header
+ handling.
diff --git a/yhttpd/RELEASES b/yhttpd/RELEASES
new file mode 100644
index 0000000..4096d8e
--- /dev/null
+++ b/yhttpd/RELEASES
@@ -0,0 +1,43 @@
+Release table
+
+Release date Release name and version Release focus
+
+Planing: yhttpd 0.7.9.5-STABLERELEASE Maintenance
+Planing: ycurses 0.1-RELEASE________ Initial release
+Planing: yhttpd 0.8-RELEASE_________ Features
+Planing: yhttpd 0.9.0-RELEASE________ Major rewrite
+Planing: yhttpd 0.8.3-RELEASE________ Not yet defined
+
+Aug 04th 05: yhttpd 0.8.2-RELEASE Minor enhancements
+May 26th 05: yhttpd 0.7.9.4-STABLERELEASE Minor bugfixes
+Jun 21st 05: yhttpd 0.8.1-RELEASE Major features
+May 25th 05: yhttpd 0.8.0-RELEASE Major features
+May 08th 05: yhttpd 0.7.9.3-STABLERELEASE Security bugfixes
+Apr 11th 05: yhttpd 0.5.5-STABLERELEASE__ Minor security fixes
+Apr 10th 05: yhttpd 0.7.9.2-RELEASE______ Major security fixes
+Apr 07th 05: yhttpd 0.7.9.1-RELEASE______ Minor bugfixes
+Mar 11th 05: yhttpd 0.7.9-RELEASE________
+Mar 08th 05: yhttpd 0.5.4-STABLERELEASE__
+Mar 05th 05 yhttpd 0.7.8-RELEASE________
+Mar 02th 05 yhttpd 0.5.3-LEGACYRELEASE__
+Feb 27th 05 yhttpd 0.5.2-LEGACYRELEASE__
+Feb 24th 05 yhttpd 0.7.7.1-RELEASE______ Major bugfixes
+Feb 21th 05 yhttpd 0.7.7-RELEASE________
+Feb 18th 05 yhttpd 0.7.6-RELEASE________
+Feb 15th 05 yhttpd 0.7.5-RELEASE________
+Feb 14th 05 yhttpd 0.7.4.1-RELEASE______ Major bugfixes
+Feb 12th 05 yhttpd 0.7.4-RELEASE________
+Feb 10th 05 yhttpd 0.7.4-PRERELEASE_____
+Dec 29th 04 yhttpd 0.7.3-RELEASE________
+Nov 09th 04 yhttpd 0.7.2-RELEASE________
+Nov 06th 04 yhttpd 0.7.1-RELEASE_______
+Nov 06th 04 yhttpd 0.7.1-RELEASE________
+Nov 01st 04 yhttpd 0.7-RELEASE_________ Initial release
+Oct 31st 04 yhttpd 0.7-RELEASE__________
+Jan 03rd 04 yhttpd 0.5.1-RELEASE________
+Sep 15th 03 yhttpd 0.6-RELEASE__________
+Sep 15th 03 yhttpd 0.5.0-RELEASE________
+Apr 26th 03 yhttpd 0.4-RELEASE__________
+Mar 30th 03 yhttpd 0.3-RELEASE__________
+Mar 24th 03 yhttpd 0.2-RELEASE__________
+Mar 20th 03 yhttpd 0.1-RELEASE__________ Initial release
diff --git a/yhttpd/SHORTDESC b/yhttpd/SHORTDESC
new file mode 100644
index 0000000..f16c9de
--- /dev/null
+++ b/yhttpd/SHORTDESC
@@ -0,0 +1,2 @@
+The yhttpd 0.8 branch is marked as CURRENT. All brand new stuff will go into
+this branch.
diff --git a/yhttpd/VERSION b/yhttpd/VERSION
new file mode 100644
index 0000000..691d30f
--- /dev/null
+++ b/yhttpd/VERSION
@@ -0,0 +1 @@
+yhttpd 0.8.3-CURRENT Build 4003
diff --git a/yhttpd/configure b/yhttpd/configure
new file mode 100755
index 0000000..9aab971
--- /dev/null
+++ b/yhttpd/configure
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+if ! ./scripts/checkperl.sh
+then
+ exit 1
+fi
+
+perl -e '
+ use strict;
+ $|=1;
+ sub check_gcc {
+ my $f = shift;
+ my $s = shift;
+ my $r = 0;
+ print "Checking for GNU G++ $f.$s\n";
+ if ( `g++ -v 2> g++.version && tail -n 1 g++.version` =~ / $f\.$s/ ) {
+ `echo $f.$s >> g++.version`;
+ `echo g++ >> g++.version`;
+ $r = 1;
+ } else {
+ if (`g++$f$s -v 2> g++.version && tail -n 1 g++.version` =~ / $f\.$s/) {
+ `echo $f.$s >> g++.version`;
+ `echo g++$f$s >> g++.version`;
+ $r = 1;
+ }
+ }
+ print "No " if $r == 0;
+ print "GNU G++ $f.$s found!\n";
+ return $r;
+ }
+ sub check_make {
+ print "Checking for GNU make\n";
+ my $err = "No GNU make found.\nPlease install a version of GNU make!\n";
+ my $make;
+ if (`which gmake`) {
+ $make = "gmake";
+ } elsif ( `which make` ) {
+ $make = "make";
+ } else {
+ print $err;
+ exit(1);
+ }
+
+ `sh -c "$make -v > make.version 2>/dev/null"`;
+ if ( `cat make.version` =~ /GNU Make/ ) {
+ `echo $make >> make.version`;
+ } else {
+ print $err;
+ exit(1);
+ }
+ }
+ &check_make;
+ print "Checking compiler version\n";
+ my $r = 0;
+ for (my $i = 4; $i > 0 && $r == 0; --$i ) {
+ $r = &check_gcc(3,$i);
+ }
+ if ($r == 0) {
+ print "No suitable g++ compiler found!\n";
+ print "Please install a right version of GNU G++!\n";
+ exit(1);
+ }
+
+ system("perl \"scripts/config.pl\"");
+ chdir("src");
+ system("./configure ".join(" ", @ARGV));
+ chdir("..");
+
+ exit(0);
+' `echo "$*" | sed "s/-//g"`
+
+if test -f err
+then
+ rm -f err
+else
+ echo You are ready to type gmake now!
+fi
diff --git a/yhttpd/etc/yhttpd.conf b/yhttpd/etc/yhttpd.conf
new file mode 100644
index 0000000..690f82d
--- /dev/null
+++ b/yhttpd/etc/yhttpd.conf
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="ISO-8859-1" standalone="yes" ?>
+<config>
+<category name="httpd">
+ <option name="serverport">
+ <value>2000</value>
+ <descr>Local port on which the server listens</descr>
+ </option>
+ <option name="enablecgi">
+ <value>false</value>
+ <descr>Support for CGI scripts</descr>
+ </option>
+ <option name="startsite">
+ <value>index.html</value>
+ <descr>Specifies the standard start HTML-template</descr>
+ </option>
+ <option name="templatedir">
+ <value>html/</value>
+ <descr>If set to false, yhttpd strips all html tags from incoming messages</descr>
+ </option>
+ <option name="ipcachesize">
+ <value>50</value>
+ <descr>Specifies the IP cache size. If set to 0, the IP cache will be cleared every 10 minutes. Otherwise, the IP cache will be cleared every 10 minutes only if there are more IPs in the cache than the specified amount.</descr>
+ </option>
+ <category name="html">
+ <option name="notfound">
+ <value>notfound.html</value>
+ <descr>The HTML site which will be displayed if the requested file does not exists</descr>
+ </option>
+ </category>
+ <category name="thread">
+ <option name="initpoolsize">
+ <value>10</value>
+ <descr>Initial number of threads running at the same time. If there are less than 5 threads in the pool waiting, the thread pool will resize to 10.</descr>
+ </option>
+ <option name="maxpoolsize">
+ <value>0</value>
+ <descr>Maximum amount of parallel running threads. Change this to 0 if you want to use unlimited threads. If you have set a number not equal to 0, then there have to be at least 2 waiting threads to allow a new user login. A maxpoolsize of 52 means a max user limit of 50 users.</descr>
+ </option>
+ </category>
+ <category name="stats">
+ <option name="rusagehistory">
+ <value>7</value>
+ <descr>Number of days to track the system resource usage. You can check the history in the CLI mode</descr>
+ </option>
+ </category>
+ <category name="system">
+ <option name="shell">
+ <value>tcsh</value>
+ <descr>The external command for the system shell which can be selected in the CLI mode</descr>
+ </option>
+ </category>
+ <category name="modules">
+ <option name="commandsdir">
+ <value>mods/commands/</value>
+ <descr>Specifies the relative or absolute path to the command&apos;s .so module files which can be loaded and unloaded at runtime</descr>
+ </option>
+ <option name="htmldir">
+ <value>mods/html/</value>
+ <descr>Specifies the relative or absolute path to the html&apos;s .so module files which can be loaded and unloaded at runtime</descr>
+ </option>
+ <option name="preloadcommands">
+ <value>true</value>
+ <descr>If set to true, all command modules will be preloaded at server startup</descr>
+ </option>
+ <option name="preloadhtml">
+ <value>true</value>
+ <descr>If set to true, all html modules will be preloaded at server startup</descr>
+ </option>
+ </category>
+ <category name="logging">
+ <option name="accessfile">
+ <value>log/access_log</value>
+ <descr>Specifies the relative or absolute path to the apache combined style log file</descr>
+ </option>
+ <option name="systemfile">
+ <value>log/system_log</value>
+ <descr>Specifies the relative or absolute path to the system messsage log file</descr>
+ </option>
+ <option name="accesslines">
+ <value>0</value>
+ <descr>Number of access log lines which will be buffered in the main memory until they will be written into the file</descr>
+ </option>
+ <option name="systemlines">
+ <value>0</value>
+ <descr>Number of system log lines which will be buffered in the main memory until they will be written into the file</descr>
+ </option>
+ </category>
+ <category name="contenttypes">
+ <option name="htm">
+ <value>text/html</value>
+ </option>
+ <option name="html">
+ <value>text/html</value>
+ </option>
+ <option name="gif">
+ <value>image/gif</value>
+ </option>
+ <option name="jpg">
+ <value>image/jpeg</value>
+ </option>
+ <option name="jpe">
+ <value>image/jpeg</value>
+ </option>
+ <option name="jpeg">
+ <value>image/jpeg</value>
+ </option>
+ <option name="png">
+ <value>image/png</value>
+ </option>
+ <option name="txt">
+ <value>text/plain</value>
+ </option>
+ <option name="default">
+ <value>text/html</value>
+ </option>
+ </category>
+ <category name="ssl">
+ <option name="certificatepath">
+ <value>etc/cert.pem</value>
+ </option>
+ <option name="privatekeypath">
+ <value>etc/privkey.pem</value>
+ </option>
+ </category>
+</category>
+</config>
diff --git a/yhttpd/html/index.html b/yhttpd/html/index.html
new file mode 100644
index 0000000..66dca39
--- /dev/null
+++ b/yhttpd/html/index.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>
+ %%yhttpd.version%%
+</title>
+<link rel=stylesheet href="style.css" type=text/css>
+</head>
+<body>
+<table align=center width=500>
+<tr>
+<td align=center class=header>%%yhttpd.version%%<br><br>%%INFO%%</td>
+</tr>
+<tr>
+<td colspan=2>&nbsp;</td>
+</tr>
+<tr>
+<td align=center colspan=2>
+This is the demo website provided by yhttpd :-)
+</td>
+</tr>
+</table>
+<br><br>
+<center><span class="signature">yhttpd is OpenSource - get it at <a class="fancy" target="_blank" href="http://www.yChat.org">http://www.yChat.org</a></span></center>
+</body>
+</html>
diff --git a/yhttpd/html/notfound.html b/yhttpd/html/notfound.html
new file mode 100644
index 0000000..a14d44b
--- /dev/null
+++ b/yhttpd/html/notfound.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>
+ %%HTML_TITLE_TAG_CONTENT%%
+</title>
+</head>
+<body>
+ Page not found.
+</body>
+</html>
diff --git a/yhttpd/html/style.css b/yhttpd/html/style.css
new file mode 100644
index 0000000..4b6d9ca
--- /dev/null
+++ b/yhttpd/html/style.css
@@ -0,0 +1,48 @@
+body, div {
+ font-family: Verdana, Helvetica, sans-serif;
+ background-color: #000000;
+ color: #FFFFEF;
+ font-size: 11pt;
+}
+
+input {
+ color: #000000;
+ font-family: Verdana, Helvetica, sans-serif;
+ text-decoration: none;
+ font-size: 9pt;
+ padding: 2px;
+}
+
+input.text {
+ background-color: #FFFFEF;
+}
+
+.fancy {
+ font-family: Verdana, Helvetica, sans-serif;
+ font-size: 9pt;
+ color: #FFFFEF;
+ padding: 2px;
+}
+
+a:hover.fancy {
+ text-decoration: none;
+ color: #FFFFEF;
+ background-color: #000000;
+}
+
+h1 {
+ background-color: #ffa500;
+ border: solid #000000 1px;
+ font-size: 20pt;
+ padding: 13px;
+ font-width: bold;
+}
+
+body.stream {
+ background-color: #323232;
+}
+
+.signature {
+ color: #AAAAAA;
+ font-size: 9pt;
+}
diff --git a/yhttpd/html/test.cgi b/yhttpd/html/test.cgi
new file mode 100644
index 0000000..12b7f75
--- /dev/null
+++ b/yhttpd/html/test.cgi
@@ -0,0 +1,9 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+print "<html><body>\n";
+print "Hello World!\n";
+print "</body></html>\n";
+
+
diff --git a/yhttpd/log/.keepme b/yhttpd/log/.keepme
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/yhttpd/log/.keepme
diff --git a/yhttpd/log/access_log b/yhttpd/log/access_log
new file mode 100644
index 0000000..aa9a3e2
--- /dev/null
+++ b/yhttpd/log/access_log
@@ -0,0 +1,41 @@
+127.0.0.1 - - [04/Aug/2005:00:50:17 +0000] "GET / HTTP/1.1" 200 0 "index.html" ""
+127.0.0.1 - - [04/Aug/2005:00:50:17 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:50:21 +0000] "POST /frameset.html HTTP/1.1" 200 0 "frameset.html" "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.10) Gecko/20050722 Epiphany/1.6.4"
+127.0.0.1 - - [04/Aug/2005:00:50:21 +0000] "GET /input.html?event=input&tmpid=0n81ffo3r9a_2.p_f0b81eer8py4idfoxAZ2HCXcvWcjChcXeShR1 HTTP/1.1" 200 0 "input.html" ""
+127.0.0.1 - - [04/Aug/2005:00:50:21 +0000] "GET /online.html?event=online&tmpid=0n81ffo3r9a_2.p_f0b81eer8py4idfoxAZ2HCXcvWcjChcXeShR1 HTTP/1.1" 200 0 "online.html" ""
+127.0.0.1 - - [04/Aug/2005:00:50:21 +0000] "GET /blank.html HTTP/1.1" 200 0 "blank.html" ""
+127.0.0.1 - - [04/Aug/2005:00:50:21 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:50:22 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:50:24 +0000] "GET /input.html?message=sdfsdf&scroll=on&event=input&tmpid=0n81ffo3r9a_2.p_f0b81eer8py4idfoxAZ2HCXcvWcjChcXeShR1 HTTP/1.1" 200 0 "input.html" ""
+127.0.0.1 - - [04/Aug/2005:00:50:24 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:50:24 +0000] "GET /input.html?message=fds&scroll=on&event=input&tmpid=0n81ffo3r9a_2.p_f0b81eer8py4idfoxAZ2HCXcvWcjChcXeShR1 HTTP/1.1" 200 0 "input.html" ""
+127.0.0.1 - - [04/Aug/2005:00:50:24 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:50:24 +0000] "GET /input.html?message=sdf&scroll=on&event=input&tmpid=0n81ffo3r9a_2.p_f0b81eer8py4idfoxAZ2HCXcvWcjChcXeShR1 HTTP/1.1" 200 0 "input.html" ""
+127.0.0.1 - - [04/Aug/2005:00:50:24 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:50:25 +0000] "GET /input.html?message=fsd&scroll=on&event=input&tmpid=0n81ffo3r9a_2.p_f0b81eer8py4idfoxAZ2HCXcvWcjChcXeShR1 HTTP/1.1" 200 0 "input.html" ""
+127.0.0.1 - - [04/Aug/2005:00:50:25 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:50:30 +0000] "GET /input.html?event=input&tmpid=0n81ffo3r9a_2.p_f0b81eer8py4idfoxAZ2HCXcvWcjChcXeShR1&message=%2Fq HTTP/1.1" 200 0 "input.html" ""
+127.0.0.1 - - [04/Aug/2005:00:50:30 +0000] "GET /stream.html?event=stream&tmpid=0n81ffo3r9a_2.p_f0b81eer8py4idfoxAZ2HCXcvWcjChcXeShR1 HTTP/1.1" 200 0 "stream.html" ""
+127.0.0.1 - - [04/Aug/2005:00:50:30 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:50:30 +0000] "GET /index.html HTTP/1.1" 200 0 "index.html" ""
+127.0.0.1 - - [04/Aug/2005:00:50:30 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:51:02 +0000] "POST /frameset.html HTTP/1.1" 200 0 "frameset.html" "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.10) Gecko/20050722 Epiphany/1.6.4"
+127.0.0.1 - - [04/Aug/2005:00:51:02 +0000] "GET /online.html?event=online&tmpid=wkhkmpvcub33ji_9qz61k8wwho6dtjplrbm4SI.I912ZU/.zHQFd0 HTTP/1.1" 200 0 "online.html" ""
+127.0.0.1 - - [04/Aug/2005:00:51:02 +0000] "GET /input.html?event=input&tmpid=wkhkmpvcub33ji_9qz61k8wwho6dtjplrbm4SI.I912ZU/.zHQFd0 HTTP/1.1" 200 0 "input.html" ""
+127.0.0.1 - - [04/Aug/2005:00:51:02 +0000] "GET /blank.html HTTP/1.1" 200 0 "blank.html" ""
+127.0.0.1 - - [04/Aug/2005:00:51:03 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:51:03 +0000] "GET /online.html?event=online&tmpid=wkhkmpvcub33ji_9qz61k8wwho6dtjplrbm4SI.I912ZU/.zHQFd0 HTTP/1.1" 200 0 "online.html" ""
+127.0.0.1 - - [04/Aug/2005:00:51:03 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:51:03 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:51:03 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:51:03 +0000] "GET /images/guest.png HTTP/1.1" 200 0 "images/guest.png" ""
+127.0.0.1 - - [04/Aug/2005:00:51:59 +0000] "POST /frameset.html HTTP/1.1" 200 0 "frameset.html" "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.10) Gecko/20050722 Epiphany/1.6.4"
+127.0.0.1 - - [04/Aug/2005:00:51:59 +0000] "GET /online.html?event=online&tmpid=zcsiafk16x20ad8_kgk.q2p6qiy0el3723/8msn2stvGQi47h1rW0 HTTP/1.1" 200 0 "online.html" ""
+127.0.0.1 - - [04/Aug/2005:00:51:59 +0000] "GET /input.html?event=input&tmpid=zcsiafk16x20ad8_kgk.q2p6qiy0el3723/8msn2stvGQi47h1rW0 HTTP/1.1" 200 0 "input.html" ""
+127.0.0.1 - - [04/Aug/2005:00:51:59 +0000] "GET /blank.html HTTP/1.1" 200 0 "blank.html" ""
+127.0.0.1 - - [04/Aug/2005:00:51:59 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:52:00 +0000] "GET /online.html?event=online&tmpid=zcsiafk16x20ad8_kgk.q2p6qiy0el3723/8msn2stvGQi47h1rW0 HTTP/1.1" 200 0 "online.html" ""
+127.0.0.1 - - [04/Aug/2005:00:52:00 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:52:00 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:52:00 +0000] "GET /style.css HTTP/1.1" 200 0 "style.css" ""
+127.0.0.1 - - [04/Aug/2005:00:52:01 +0000] "GET /images/guest.png HTTP/1.1" 200 0 "images/guest.png" ""
diff --git a/yhttpd/log/system_log b/yhttpd/log/system_log
new file mode 100644
index 0000000..3a9dffc
--- /dev/null
+++ b/yhttpd/log/system_log
@@ -0,0 +1,114 @@
+[04/Aug/2005:00:42:06 +0000] Sock: Created socket on localhost:2000
+[04/Aug/2005:00:42:06 +0000] Pool: Allocating new threads (10,0)
+[04/Aug/2005:00:42:06 +0000] Reading standard command exec permissions
+[04/Aug/2005:00:42:06 +0000] Chat: Using replacement strings
+[04/Aug/2005:00:42:06 +0000] Timer: Initializing
+[04/Aug/2005:00:42:06 +0000] Timer: Setting offset to 0
+[04/Aug/2005:00:42:07 +0000] Garbage: Initializing collector
+[04/Aug/2005:00:42:07 +0000] Sock: Initializing server socket
+[04/Aug/2005:00:42:07 +0000] Sock: Starting unsecure transport [HTTP]
+[04/Aug/2005:00:42:07 +0000] Sock: Server socket is ready
+[04/Aug/2005:00:42:07 +0000] Timer: Starting timer thread
+[04/Aug/2005:00:49:58 +0000] Sock: Bind error
+[04/Aug/2005:00:49:58 +0000] Sock: Can't create socket, trying next port 2001
+[04/Aug/2005:00:49:58 +0000] Sock: Created socket on localhost:2001
+[04/Aug/2005:00:49:58 +0000] Pool: Allocating new threads (10,0)
+[04/Aug/2005:00:49:58 +0000] Reading standard command exec permissions
+[04/Aug/2005:00:49:58 +0000] Chat: Using replacement strings
+[04/Aug/2005:00:49:58 +0000] Timer: Initializing
+[04/Aug/2005:00:49:58 +0000] Timer: Setting offset to 0
+[04/Aug/2005:00:49:58 +0000] Garbage: Initializing collector
+[04/Aug/2005:00:49:58 +0000] Sock: Initializing server socket
+[04/Aug/2005:00:49:58 +0000] Sock: Starting unsecure transport [HTTP]
+[04/Aug/2005:00:49:58 +0000] Sock: Server socket is ready
+[04/Aug/2005:00:49:58 +0000] Timer: Starting timer thread
+[04/Aug/2005:00:50:07 +0000] Sock: Bind error
+[04/Aug/2005:00:50:07 +0000] Sock: Can't create socket, trying next port 2001
+[04/Aug/2005:00:50:07 +0000] Sock: Created socket on localhost:2001
+[04/Aug/2005:00:50:08 +0000] Pool: Allocating new threads (10,0)
+[04/Aug/2005:00:50:08 +0000] Reading standard command exec permissions
+[04/Aug/2005:00:50:08 +0000] Chat: Using replacement strings
+[04/Aug/2005:00:50:08 +0000] Timer: Initializing
+[04/Aug/2005:00:50:08 +0000] Timer: Setting offset to 0
+[04/Aug/2005:00:50:08 +0000] Garbage: Initializing collector
+[04/Aug/2005:00:50:08 +0000] Sock: Initializing server socket
+[04/Aug/2005:00:50:08 +0000] Sock: Starting unsecure transport [HTTP]
+[04/Aug/2005:00:50:08 +0000] Sock: Server socket is ready
+[04/Aug/2005:00:50:08 +0000] Timer: Starting timer thread
+[04/Aug/2005:00:50:17 +0000] Sock: Caching IP 127.0.0.1
+[04/Aug/2005:00:50:17 +0000] HTML: Caching document html/index.html
+[04/Aug/2005:00:50:17 +0000] HTML: Caching document html/style.css
+[04/Aug/2005:00:50:21 +0000] New tmpid: 0n81ffo3r9a_2.p_f0b81eer8py4idfoxAZ2HCXcvWcjChcXeShR1
+[04/Aug/2005:00:50:21 +0000] Chat: New room Lounge
+[04/Aug/2005:00:50:21 +0000] Chat: New user sdfsdfs
+[04/Aug/2005:00:50:21 +0000] HTML: Caching document html/frameset.html
+[04/Aug/2005:00:50:21 +0000] HTML: Caching document html/stream.html
+[04/Aug/2005:00:50:21 +0000] HTML: Caching document html/input.html
+[04/Aug/2005:00:50:21 +0000] HTML: Caching document html/online.html
+[04/Aug/2005:00:50:21 +0000] HTML: Caching document html/blank.html
+[04/Aug/2005:00:50:30 +0000] Modl: Requesting yc_q.so (sdfsdfs)
+[04/Aug/2005:00:50:30 +0000] Garbage: Added room Lounge
+[04/Aug/2005:00:50:30 +0000] Garbage: Added user sdfsdfs
+[04/Aug/2005:00:50:34 +0000] Garbage collector activated
+[04/Aug/2005:00:50:34 +0000] Garbage: Removing room Lounge
+[04/Aug/2005:00:50:34 +0000] Garbage: Removing user sdfsdfs
+[04/Aug/2005:00:50:59 +0000] Sock: Bind error
+[04/Aug/2005:00:50:59 +0000] Sock: Can't create socket, trying next port 2001
+[04/Aug/2005:00:50:59 +0000] Sock: Created socket on localhost:2001
+[04/Aug/2005:00:50:59 +0000] Pool: Allocating new threads (10,0)
+[04/Aug/2005:00:50:59 +0000] Reading standard command exec permissions
+[04/Aug/2005:00:50:59 +0000] Chat: Using replacement strings
+[04/Aug/2005:00:50:59 +0000] Timer: Initializing
+[04/Aug/2005:00:50:59 +0000] Timer: Setting offset to 0
+[04/Aug/2005:00:50:59 +0000] Garbage: Initializing collector
+[04/Aug/2005:00:50:59 +0000] Sock: Initializing server socket
+[04/Aug/2005:00:50:59 +0000] Sock: Starting unsecure transport [HTTP]
+[04/Aug/2005:00:50:59 +0000] Sock: Server socket is ready
+[04/Aug/2005:00:50:59 +0000] Timer: Starting timer thread
+[04/Aug/2005:00:51:02 +0000] Sock: Caching IP 127.0.0.1
+[04/Aug/2005:00:51:02 +0000] New tmpid: wkhkmpvcub33ji_9qz61k8wwho6dtjplrbm4SI.I912ZU/.zHQFd0
+[04/Aug/2005:00:51:02 +0000] Chat: New room Lounge
+[04/Aug/2005:00:51:02 +0000] Chat: New user sdfsdf
+[04/Aug/2005:00:51:02 +0000] HTML: Caching document html/frameset.html
+[04/Aug/2005:00:51:02 +0000] HTML: Caching document html/online.html
+[04/Aug/2005:00:51:02 +0000] HTML: Caching document html/stream.html
+[04/Aug/2005:00:51:02 +0000] HTML: Caching document html/input.html
+[04/Aug/2005:00:51:02 +0000] HTML: Caching document html/blank.html
+[04/Aug/2005:00:51:03 +0000] HTML: Caching document html/style.css
+[04/Aug/2005:00:51:03 +0000] HTML: Caching document html/images/guest.png
+[04/Aug/2005:00:51:53 +0000] Sock: Bind error
+[04/Aug/2005:00:51:53 +0000] Sock: Can't create socket, trying next port 2001
+[04/Aug/2005:00:51:53 +0000] Sock: Created socket on localhost:2001
+[04/Aug/2005:00:51:54 +0000] Pool: Allocating new threads (10,0)
+[04/Aug/2005:00:51:54 +0000] Reading standard command exec permissions
+[04/Aug/2005:00:51:54 +0000] Chat: Using replacement strings
+[04/Aug/2005:00:51:54 +0000] Timer: Initializing
+[04/Aug/2005:00:51:54 +0000] Timer: Setting offset to 0
+[04/Aug/2005:00:51:54 +0000] Garbage: Initializing collector
+[04/Aug/2005:00:51:54 +0000] Sock: Initializing server socket
+[04/Aug/2005:00:51:54 +0000] Sock: Starting unsecure transport [HTTP]
+[04/Aug/2005:00:51:54 +0000] Sock: Server socket is ready
+[04/Aug/2005:00:51:54 +0000] Timer: Starting timer thread
+[04/Aug/2005:00:51:59 +0000] Sock: Caching IP 127.0.0.1
+[04/Aug/2005:00:51:59 +0000] Chat: New room Lounge
+[04/Aug/2005:00:51:59 +0000] Chat: New user sdfsdf
+[04/Aug/2005:00:51:59 +0000] HTML: Caching document html/frameset.html
+[04/Aug/2005:00:51:59 +0000] HTML: Caching document html/online.html
+[04/Aug/2005:00:51:59 +0000] HTML: Caching document html/stream.html
+[04/Aug/2005:00:51:59 +0000] HTML: Caching document html/input.html
+[04/Aug/2005:00:51:59 +0000] HTML: Caching document html/blank.html
+[04/Aug/2005:00:51:59 +0000] HTML: Caching document html/style.css
+[04/Aug/2005:00:52:01 +0000] HTML: Caching document html/images/guest.png
+[04/Aug/2005:01:08:20 +0000] Sock: Bind error
+[04/Aug/2005:01:08:20 +0000] Sock: Can't create socket, trying next port 2001
+[04/Aug/2005:01:08:20 +0000] Sock: Created socket on localhost:2001
+[04/Aug/2005:01:08:20 +0000] Pool: Allocating new threads (10,0)
+[04/Aug/2005:01:08:20 +0000] Reading standard command exec permissions
+[04/Aug/2005:01:08:20 +0000] Chat: Using replacement strings
+[04/Aug/2005:01:08:20 +0000] Timer: Initializing
+[04/Aug/2005:01:08:20 +0000] Timer: Setting offset to 0
+[04/Aug/2005:01:08:20 +0000] Garbage: Initializing collector
+[04/Aug/2005:01:08:20 +0000] Sock: Initializing server socket
+[04/Aug/2005:01:08:20 +0000] Sock: Starting unsecure transport [HTTP]
+[04/Aug/2005:01:08:20 +0000] Sock: Server socket is ready
+[04/Aug/2005:01:08:21 +0000] Timer: Starting timer thread
diff --git a/yhttpd/scripts/README b/yhttpd/scripts/README
new file mode 100644
index 0000000..4a94391
--- /dev/null
+++ b/yhttpd/scripts/README
@@ -0,0 +1,6 @@
+All scripts should be run from the yhttpd main directory, example:
+
+./scripts/makeyhttpd.pl
+
+
+A ./makeyhttpd.pl WILL NOT work :)
diff --git a/yhttpd/scripts/astyle.sh b/yhttpd/scripts/astyle.sh
new file mode 100755
index 0000000..8f67195
--- /dev/null
+++ b/yhttpd/scripts/astyle.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+# The yhttpd Project (2004)
+#
+# This uses "astyle" to format C++ code into a specific code style!
+
+for f in h cpp tmpl
+do
+ for i in `find . -name "*.$f"`
+ do
+ echo $i
+ astyle --style=ansi -s2 $i
+ rm -f $i.orig
+ done
+done
diff --git a/yhttpd/scripts/buildnr.pl b/yhttpd/scripts/buildnr.pl
new file mode 100755
index 0000000..edfffd6
--- /dev/null
+++ b/yhttpd/scripts/buildnr.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+
+# The yhttpd Project (2003)
+#
+# This script increases the BUILNR of msgs,h each time the yhttpd
+# gets recompiled!
+
+use strict;
+
+open MSGS, "src/msgs.h";
+my @msgs = <MSGS>;
+close MSGS;
+
+foreach (@msgs)
+{
+ if ( /define BUILDNR/ )
+ {
+ s/(BUILDNR )(.+)$/$1.($2+1)/e;
+ print;
+ next;
+ }
+}
+
+open MSGS, ">src/msgs.h";
+print MSGS @msgs;
+close MSGS;
diff --git a/yhttpd/scripts/checkperl.sh b/yhttpd/scripts/checkperl.sh
new file mode 100755
index 0000000..642938b
--- /dev/null
+++ b/yhttpd/scripts/checkperl.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+# The yhttpd Project (2005)
+#
+# This scripts checks for a perl installation
+
+if ! which perl >/dev/null
+then
+ echo You need to have Perl in your PATH!
+ exit 1
+fi
+
+echo Using `which perl`
+exit 0
diff --git a/yhttpd/scripts/config.pl b/yhttpd/scripts/config.pl
new file mode 100755
index 0000000..f82d5ba
--- /dev/null
+++ b/yhttpd/scripts/config.pl
@@ -0,0 +1,133 @@
+#!/usr/bin/perl
+
+# The yhttpd Project (2004, 2005)
+#
+# This script modifues the src/glob.h file.
+
+use strict;
+use scripts::modules::file;
+
+print <<END;
+Welcome to the yhttpd configurator!
+You may also edit the src/glob.h file manually instead of using
+this configurator option. Please also notice that this are only
+before-compile options. All setups which can be made after com-
+iling are placed in the yhttpd configuration file.
+END
+
+my $sep = "================================================================\n";
+my $stdin;
+
+for (;;) {
+ print "$sep Do you want to use the default before-compile options?\n";
+ print " (yes/no) [default is NO] ";
+ $stdin = <STDIN>;
+ chomp $stdin;
+ print "\n";
+
+ if ( $stdin eq "yes") {
+ print " You chose to use all the default before-compile options. Exiti-\n";
+ print " ng the configurator now!\n";
+ print $sep;
+ exit(0);
+ }
+
+ last if $stdin eq "no" or $stdin eq "";
+ print " Wrong input: You need to specify yes or no!\n";
+} # for
+
+`cp src/glob.h src/glob.h.org` unless -f "src/glob.h.org";
+
+my @glob = fopen("src/glob.h.org");
+my $flag = 0;
+
+for (@glob) {
+ if ( $flag == 0 && /- CONFIG -/ ) {
+ print $sep;
+ $flag = 1;
+ next;
+
+ } elsif ( $flag == 1 ) {
+ if ( /\*\// ) {
+ $flag = 2;
+
+ } else {
+ print;
+ }
+
+ next;
+
+ } elsif ( $flag == 2 ) {
+ if ( /#define (.+) (.+)/ ) {
+ my $def = $1;
+ my $val = $2;
+ my $flg = 0;
+
+ $flg = 1 if $val =~ s/"//g;
+
+ print " [Press enter to use default value: $val or q to quit] ";
+ $stdin = <STDIN>;
+ chomp $stdin;
+
+ finish() if $stdin eq "q" or $stdin eq "quit";
+
+ unless ( parse_input_value(\$stdin,\$val) ) {
+ $stdin = "\"$stdin\"" if $flg == 1;
+ $_ = "#define $def $stdin\n";
+ }
+
+ print "\n";
+ $flag = 0;
+ next;
+ }
+
+ elsif ( /#define .+/ ) {
+ my $default = "true";
+ my $stdin;
+
+ for (;;) {
+ $default = "false" if /\/\/#define/;
+
+ print " [Press enter to use default value: $default or q to quit] ";
+ $stdin = <STDIN>;
+ chomp $stdin;
+
+ finish() if $stdin eq "q" or $stdin eq "quit";
+ last if $stdin eq "" || $stdin eq "true" || $stdin eq "false";
+ print " Wrong input: You need to specify true or false!\n";
+ }
+
+ if ( $default eq "true" ) {
+ $_ = "//$_" unless parse_input_value(\$stdin,\$default);
+ }
+
+ else {
+ s/^\/\/// unless parse_input_value(\$stdin,\$default);
+ }
+
+ print "\n";
+ $flag = 0;
+ next;
+ }
+ }
+} // for
+
+finish();
+
+sub finish() {
+ fwrite("src/glob.h", @glob);
+ exit 0;
+}
+
+sub parse_input_value {
+ my $val = shift;
+ my $def = shift;
+
+ if ( $$val eq "" || $$val eq $$def) {
+ print " -> Using default option!\n";
+ return 1;
+ }
+
+ print " -> Using new option $$val!\n";
+ return 0;
+}
diff --git a/yhttpd/scripts/makedist.sh b/yhttpd/scripts/makedist.sh
new file mode 100755
index 0000000..0814611
--- /dev/null
+++ b/yhttpd/scripts/makedist.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+# The yhttpd Project (2005)
+#
+# This script creates a .tar.bz2 ball.
+
+pwd=`pwd` && base=`basename $pwd` && cd .. &&
+version=`grep VERSION $base/src/msgs.h | head -n 1 | cut -d'"' -f2` &&
+prefix="$base-$version"
+package="$prefix.tar.bz2"
+
+echo Copying files... &&
+rm -Rf $prefix 2>/dev/null >/dev/null
+cp -Rp $base $prefix && cd $prefix &&
+
+echo Cleaning... &&
+gmake mrproper 2>/dev/null >/dev/null
+find . -name CVS | xargs rm -Rf
+cd .. &&
+
+echo Compressing... &&
+if test -f $package; then rm -f $package; fi &&
+tar cjf $package $prefix &&
+
+echo Finishing... &&
+rm -Rf $prefix 2>/dev/null >/dev/null
+cd $base &&
+du -h ../$package
diff --git a/yhttpd/scripts/modules/file.pm b/yhttpd/scripts/modules/file.pm
new file mode 100644
index 0000000..b11e2b3
--- /dev/null
+++ b/yhttpd/scripts/modules/file.pm
@@ -0,0 +1,28 @@
+sub dopen
+{
+ my $shift = shift;
+ opendir DIR, $shift or die "$shift: $!\n";
+ my @dir = readdir(DIR);
+ closedir DIR;
+ return @dir;
+}
+
+sub fopen
+{
+ my $shift = shift;
+ open FILE, $shift or die "$shift: $!\n";
+ my @file = <FILE>;
+ close FILE;
+ return @file;
+}
+
+sub fwrite
+{
+ my $shift = shift;
+ my @file = @_;
+ open FILE, ">$shift" or die "$shift: $!\n";
+ print FILE @file;
+ close FILE;
+}
+
+1;
diff --git a/yhttpd/scripts/screen.sh b/yhttpd/scripts/screen.sh
new file mode 100755
index 0000000..5c227fc
--- /dev/null
+++ b/yhttpd/scripts/screen.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+screen -S yhttpd ./bin/yhttpd
diff --git a/yhttpd/scripts/setglobvals.pl b/yhttpd/scripts/setglobvals.pl
new file mode 100755
index 0000000..1ee1de4
--- /dev/null
+++ b/yhttpd/scripts/setglobvals.pl
@@ -0,0 +1,32 @@
+#!/usr/bin/perl
+
+# The yhttpd Project (2003)
+#
+# This script sets up some variables in src/glob.h
+
+use strict;
+
+use scripts::modules::file;
+
+my $file = 'src/glob.h';
+my $gmake = `which gmake`;
+my @glob = fopen($file);
+chomp($gmake);
+
+print "-> Setting values in $file\n";
+
+my $modified = 0;
+foreach (@glob)
+{
+ if (/^(#define GMAKE) "(.*)"/)
+ {
+ if ($2 ne "$gmake \\0")
+ {
+ s/^$1 "$2"/#define GMAKE "$gmake \\0"/;
+ print " -> Set $gmake\n";
+ fwrite($file,@glob);
+ last;
+ }
+ }
+}
+
diff --git a/yhttpd/scripts/stats.pl b/yhttpd/scripts/stats.pl
new file mode 100755
index 0000000..96fbdf1
--- /dev/null
+++ b/yhttpd/scripts/stats.pl
@@ -0,0 +1,95 @@
+#!/usr/bin/perl
+
+# The yhttpd Project (2003 - 2004)
+#
+# This script generates source code and project statistics
+
+use strict;
+
+use scripts::modules::file;
+
+my %stats;
+my $param = shift;
+
+&recursive(".");
+
+$stats{"Lines total"} = $stats{"Lines of source"}
+ + $stats{"Lines of scripts"}
+ + $stats{"Lines of text"}
+ + $stats{"Lines of HTML"};
+
+unless (defined $param) {
+
+ print "$_ = " . $stats{$_} . "\n"
+ for ( sort keys %stats );
+
+} else {
+
+ print $stats{$_} . " "
+ for sort keys %stats;
+
+}
+
+print "\n";
+
+sub recursive
+{
+ my $shift = shift;
+ my @dir = &dopen($shift);
+
+ foreach (@dir)
+ {
+ next if /^\.$/ or /^\.{2}$/;
+
+ if ( -f "$shift/$_" )
+ {
+ $stats{"Number of files total"}++;
+ &filestats("$shift/$_");
+ }
+ elsif ( -d "$shift/$_" )
+ {
+ $stats{"Number of dirs total"}++;
+ &recursive("$shift/$_");
+ }
+ }
+}
+
+sub filestats
+{
+ my $shift = shift;
+ if ( $shift =~ /\.(cpp|h|tmpl)$/ )
+ {
+ $stats{"Number of source files"}++;
+ $stats{"Lines of source"} += countlines($shift);
+ }
+ elsif ( $shift =~ /\.(html|css)$/ )
+ {
+ $stats{"Number of HTML files"}++;
+ $stats{"Lines of HTML"} += countlines($shift);
+ }
+ elsif ( $shift =~ /\.(gif|png|jpg)$/ )
+ {
+ $stats{"Number of gfx files"}++;
+ }
+ elsif ( $shift =~ /(\.pl|\.sh|configure.*|Makefile.*)$/ )
+ {
+ $stats{"Number of script files"}++;
+ $stats{"Lines of scripts"} += countlines($shift);
+ }
+ elsif ( $shift =~ /(\.txt|[A-Z]+)$/ )
+ {
+ $stats{"Number of text files"}++;
+ $stats{"Lines of text"} += countlines($shift);
+ }
+ elsif ( $shift =~ /\.so$/ )
+ {
+ $stats{"Number of compiled module files"}++;
+ }
+}
+
+sub countlines
+{
+ my $shift = shift;
+ my @file = fopen($shift);
+ return $#file;
+}
diff --git a/yhttpd/scripts/version.sh b/yhttpd/scripts/version.sh
new file mode 100755
index 0000000..50c189c
--- /dev/null
+++ b/yhttpd/scripts/version.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# The yhttpd Project (2005)
+#
+# This script shows yhttpd VERSION-BRANCH Build BUILDNUMBER
+
+version=`grep VERSION src/msgs.h | head -n 1 | cut -d'"' -f2`
+branch=`grep BRANCH src/msgs.h | head -n 1 | cut -d'"' -f2`
+build=`grep BUILD src/msgs.h | tail -n 1 | cut -d' ' -f3`
+echo "yhttpd $version-$branch Build $build"
+
+
diff --git a/yhttpd/src/Makefile.in b/yhttpd/src/Makefile.in
new file mode 100644
index 0000000..262f3a6
--- /dev/null
+++ b/yhttpd/src/Makefile.in
@@ -0,0 +1,21 @@
+SRCS=WILLBEADDEDBYCONFIGURE
+OBJS=$(addprefix ../obj/,$(SRCS:.cpp=.o))
+CC=WILLBEADDEDBYCONFIGURE
+LIBADD=`cat libs.add`
+LDFLAGS=$(LIBADD) -lstdc++
+LDADD=-pthread -D_THREAD_SAFE -export-dynamic -ldl
+INCLUDES=`cat includes.add`
+CFLAGS=-fno-inline -fno-default-inline -frepo
+all: yhttpd
+$(SRCS):
+ $(CC) $(INCLUDES) $(CFLAGS) -c $*.cpp
+infotext:
+ @echo Compiling base
+yhttpd: infotext $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDADD)
+ @mv yhttpd ../bin
+ @echo -n "Size of linked executable: "
+ @du -hc ../bin/yhttpd | tail -n 1
+clean:
+ @echo Cleaning base obj
+ @if test -d ../obj; then rm -Rf ../obj; fi
diff --git a/yhttpd/src/cli/cli.cpp b/yhttpd/src/cli/cli.cpp
new file mode 100644
index 0000000..dbbc729
--- /dev/null
+++ b/yhttpd/src/cli/cli.cpp
@@ -0,0 +1,300 @@
+#ifndef CLI_CPP
+#define CLI_CPP
+
+#include "cli.h"
+
+#ifdef CLI
+using namespace std;
+
+cli::cli( )
+{
+#ifdef NCURSES
+ start();
+#endif
+}
+
+cli::~cli()
+{}
+
+int
+cli::parse_input( string s_input )
+{
+ string s_param = "";
+ unsigned i_pos = s_input.find_first_of(" ");
+
+ if ( i_pos != string::npos )
+ {
+ s_param = s_input.substr(i_pos+1);
+ s_input = s_input.substr(0, i_pos);
+ }
+
+ if ( s_input.compare("help") == 0 || s_input.compare("h") == 0)
+ {
+ cout << CLIPRMO << "COMMAND LINE INTERFACE HELP MENU" << endl
+ << CLIPRMO << " !command - Uses system to run a command" << endl;
+#ifdef DEBUG
+
+ cout << CLIPRMO << " (d)ebug - Starts debug routine (cli.cpp)" << endl;
+#endif
+
+ cout << CLIPRMO << " (du)mp [part] - Prints out a dump of the data structure" << endl;
+ cout << CLIPRMO << " (Run without part to list all possibilities)" << endl;
+ cout << CLIPRMO << " (e)cho VAR - Prints out configuration value of VAR" << endl;
+ cout << CLIPRMO << " Wildcards can be used too, example: echo http*" << endl;
+#ifdef NCURSES
+
+ cout << CLIPRMO << " (ex)it - Quits CLI mode and respawns ncurses mode" << endl;
+#endif
+
+ cout << CLIPRMO << " (h)elp - Prints out this help!" << endl;
+#ifdef EXPERIM
+
+ cout << CLIPRMO << " (re)conf - Reloads configuration (EXPERIMENTAL)" << endl;
+#endif
+
+ cout << CLIPRMO << " (r)usage - Shows current resource usage" << endl
+ << CLIPRMO << " (ru)sageh - Shows resource usage history (yhttpd needs to run > 1 day)" << endl
+ << CLIPRMO << " (set) VAR VAL - Sets configuration value VAR to VAL" << endl
+ << CLIPRMO << " (sh)ell - Runs a system shell" << endl
+ << CLIPRMO << " (s)hutdown - Shuts down the whole server" << endl
+ << CLIPRMO << " (t)ime - Prints out time and uptime" << endl;
+ cout << CLIPRMO << " (u)nset VAR - Deletes configuration value VAR" << endl
+ << CLIPRMO << " (v)ersion - Prints out version" << endl;
+ cout << CLIPRMI;
+ }
+ else if( s_input.at(0) == '!' )
+ {
+ system( s_input.substr(1).c_str() );
+ cout << CLIPRMI;
+ }
+
+#ifdef DEBUG
+ else if ( s_input.compare("d") == 0 || s_input.compare("debug") == 0 )
+ {
+ debug_routine();
+ cout << CLIPRMI;
+ }
+#endif
+ else if ( s_input.compare("du") == 0 || s_input.compare("dump") == 0 )
+ {
+ dump d(vectorize(s_param));
+ cout << CLIPRMI;
+ }
+ else if( s_input.compare("echo") == 0 || s_input.compare("e") == 0 )
+ {
+ string s_val;
+
+ // Check wildcards
+ unsigned i_pos = s_param.find("*");
+ if ( i_pos != string::npos )
+ {
+ s_param = s_param.substr( 0, i_pos );
+ vector<string>* p_vec = wrap::CONF->get_key_vector();
+ sort(p_vec->begin(), p_vec->end());
+ vector<string>::iterator iter;
+
+ for ( iter = p_vec->begin(); iter != p_vec->end(); iter++ )
+ if ( iter->find(s_param) == 0 )
+ s_val.append( *iter + " := " + wrap::CONF->get_elem(*iter) + "\n" + CLIPRMO );
+ delete p_vec;
+ }
+ else
+ {
+ s_val = wrap::CONF->get_elem(s_param);
+ }
+
+ if( s_val.empty() )
+ s_val = "Value not set";
+
+ cout << CLIPRMO << s_val << endl;
+ cout << CLIPRMI;
+ }
+
+
+#ifdef NCURSES
+ else if( s_input.compare("exit") == 0 || s_input.compare("ex") == 0 )
+ {
+ return 0;
+ }
+#endif
+
+
+#ifdef EXPERIM
+ else if( s_input.compare("reconf") == 0 || s_input.compare("re") == 0 )
+ {
+ wrap::HTTPD->reconf();
+ cout << CLIPRMI;
+ }
+#endif
+
+ else if( s_input.compare("rusage") == 0 || s_input.compare("r") == 0 )
+ {
+ print_rusage();
+ cout << CLIPRMI;
+ }
+ else if( s_input.compare("ru") == 0 || s_input.compare("rusageh") == 0 )
+ {
+ cout << wrap::STAT->get_rusage_history( "ru_maxrss", string(CLIPRMO) + " " );
+ cout << CLIPRMI;
+ }
+ else if( s_input.compare("set") == 0 )
+ {
+ string s_varname = "";
+ i_pos = s_param.find_first_of(" ");
+
+ if ( i_pos != string::npos )
+ {
+ s_varname = s_param.substr(0, i_pos);
+
+ if ( s_param.length() > i_pos+1 )
+ s_param = s_param.substr(i_pos+1);
+
+ else
+ s_param = "";
+ }
+
+ string s_old_val = wrap::CONF->get_elem(s_varname);
+
+ if ( !s_old_val.empty() )
+ {
+ cout << CLIPRMO << "Old value: " << s_old_val << endl;
+ wrap::CONF->del_elem(s_varname);
+ }
+
+ wrap::CONF->add_elem(s_param, s_varname);
+ cout << CLIPRMO << "New value: " << s_param << endl;
+ cout << CLIPRMI;
+ }
+ else if( s_input.compare("shell") == 0 || s_input.compare("sh") == 0 )
+ {
+ cout << CLIPRMO << CLISHEL << endl;
+ system(wrap::CONF->get_elem("httpd.system.shell").c_str());
+ cout << CLIPRMO << CLIWELC << endl;
+ cout << CLIPRMI;
+ }
+ else if( s_input.compare("shutdown") == 0 || s_input.compare("s") == 0 )
+ {
+ exit(0);
+ }
+ else if( s_input.compare("t") == 0 || s_input.compare("time") == 0 )
+ {
+ cout << CLIPRMO << "Time: " << wrap::TIMR->get_time() << endl
+ << CLIPRMO << "Uptime: " << wrap::TIMR->get_uptime() << endl;
+ cout << CLIPRMI;
+ }
+
+
+ else if( s_input.compare("u") == 0 || s_input.compare("unset") == 0 )
+ {
+ if (!s_param.empty())
+ {
+ string s_old_val = wrap::CONF->get_elem(s_param);
+ if ( !s_old_val.empty() )
+ {
+ cout << CLIPRMO << "Deleted variable " << s_param << " with value: " << s_old_val << endl;
+ wrap::CONF->del_elem(s_param);
+ }
+ else
+ {
+ cout << CLIPRMO << "Variable " << s_param << " was not set" << endl;
+ }
+ cout << CLIPRMI;
+ }
+ }
+ else if( s_input.compare("v") == 0 || s_input.compare("version") == 0 )
+ {
+ cout << CLIPRMO << tool::yhttpd_version() << " " << UNAME << endl;
+ cout << CLIPRMI;
+ }
+ else
+ {
+ cout << CLIPRMO << CLIHELP << "\"" << s_input << "\"" << endl;
+ cout << CLIPRMI;
+ }
+
+ return 1;
+}
+
+void
+#ifndef NCURSES
+cli::start(void* p_void)
+#else
+cli::start()
+#endif
+{
+ cout << CLIPRMO << CLIWELC << endl;
+
+ string s_input;
+ cout << CLIPRMI;
+
+ do
+ {
+ getline(cin, s_input);
+ }
+ while( parse_input(s_input) );
+}
+
+void
+cli::print_rusage()
+{
+ rusage* p_rusage = new rusage;
+ getrusage( RUSAGE_SELF, p_rusage );
+
+ cout << CLIPRMO << "ru_maxrss: " << p_rusage->ru_maxrss << "\t(max resident set size)" << endl
+ << CLIPRMO << "ru_ixrss: " << p_rusage->ru_ixrss << "\t(integral shared text memory size)" << endl
+ << CLIPRMO << "ru_idrss: " << p_rusage->ru_idrss << "\t(integral unshared data size)" << endl
+ << CLIPRMO << "ru_isrss: " << p_rusage->ru_isrss << "\t(integral unshared stack size)" << endl
+ << CLIPRMO << "ru_minflt: " << p_rusage->ru_minflt << "\t(page reclaims)" << endl
+ << CLIPRMO << "ru_majflt: " << p_rusage->ru_majflt << "\t(page faults)" << endl
+ << CLIPRMO << "ru_nswap: " << p_rusage->ru_nswap << "\t(swaps)" << endl
+ << CLIPRMO << "ru_inblock: " << p_rusage->ru_inblock << "\t(block input operations)" << endl
+ << CLIPRMO << "ru_oublock: " << p_rusage->ru_oublock << "\t(block output operations)" << endl
+ << CLIPRMO << "ru_msgsnd: " << p_rusage->ru_msgsnd << "\t(messages sent)" << endl
+ << CLIPRMO << "ru_msgrcv: " << p_rusage->ru_msgrcv << "\t(messages received)" << endl
+ << CLIPRMO << "ru_nsignals: " << p_rusage->ru_nsignals << "\t(signals received)" << endl
+ << CLIPRMO << "ru_nvcsw: " << p_rusage->ru_nvcsw << "\t(voluntary context switches)" << endl
+ << CLIPRMO << "ru_nivcsw: " << p_rusage->ru_nivcsw << "\t(involuntary context switches)" << endl;
+
+ delete p_rusage;
+}
+
+vector<string>
+cli::vectorize(string s_param)
+{
+ vector<string> vec_ret;
+ unsigned i_pos;
+
+ for (i_pos = s_param.find(" ");
+ i_pos != string::npos;
+ i_pos = s_param.find(" "))
+ {
+ vec_ret.push_back(s_param.substr(0, i_pos));
+ s_param = s_param.substr(i_pos+1);
+ }
+
+ if (!s_param.empty())
+ vec_ret.push_back(s_param);
+
+ return vec_ret;
+}
+
+#ifdef DEBUG
+void
+cli::debug_routine()
+{
+ rusage* p_rusage = new rusage;
+ for(;;)
+ {
+ /*
+ ossl *p_tmp = new ossl;
+ getrusage( RUSAGE_SELF, p_rusage );
+ cout << CLIPRMO << "ru_maxrss: " << p_rusage->ru_maxrss << "\t(max resident set size)" << endl;
+ delete p_tmp;
+ */
+ }
+ delete p_rusage;
+}
+#endif
+
+#endif
+#endif
diff --git a/yhttpd/src/cli/cli.h b/yhttpd/src/cli/cli.h
new file mode 100644
index 0000000..8ec75cb
--- /dev/null
+++ b/yhttpd/src/cli/cli.h
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <iostream>
+#include <vector>
+
+#ifndef RUSAGE_SELF
+#define RUSAGE_SELF 0
+#endif
+#ifndef RUSAGE_CHILDREN
+#define RUSAGE_CHILDREN -1
+#endif
+
+#include "../incl.h"
+
+#ifndef CLI_H
+#define CLI_H
+#ifdef CLI
+
+#ifndef NCURSES
+#include "../thrd/thro.h"
+#endif
+
+#include "../monitor/dump.h"
+
+using namespace std;
+
+#ifndef NCURSES
+class cli : public thro
+{
+#else
+class cli
+{
+#endif
+private:
+ int parse_input(string s_input);
+ vector<string> vectorize(string s_param);
+
+public:
+ cli( );
+ ~cli( );
+
+#ifdef DEBUG
+
+ void debug_routine();
+#endif
+
+ void print_rusage();
+
+#ifndef NCURSES
+
+ void start(void* p_void);
+#else
+
+ void start();
+#endif
+};
+
+#endif
+#endif
diff --git a/yhttpd/src/conf/conf.cpp b/yhttpd/src/conf/conf.cpp
new file mode 100644
index 0000000..25884ca
--- /dev/null
+++ b/yhttpd/src/conf/conf.cpp
@@ -0,0 +1,186 @@
+#ifndef CONF_CPP
+#define CONF_CPP
+
+#include <fstream>
+#include "conf.h"
+
+using namespace std;
+
+conf::conf( string s_conf, map<string,string>* p_main_loop_params ) : name::name( s_conf )
+{
+ string s_check[] = {
+ get_name(),
+ string(getenv("HOME"))+string("/.yhttpd/") + get_name(),
+ string("./etc/") + get_name(),
+ string("/etc/") + get_name(),
+ string(PREFIX+string("etc/")+get_name()) };
+
+ string s_config;
+
+ for ( int i = 0; i < 4; ++i )
+ {
+ cout << "Checking for " << s_check[i];
+ ifstream if_check( s_check[i].c_str() );
+ if( if_check )
+ {
+ s_config = s_check[i];
+ if_check.close();
+ cout << "... ok!" << endl;
+ break;
+ }
+ cout << "... not ok!" << endl;
+ }
+
+ if ( s_config.empty() )
+ {
+ cout << CFILEFA << endl;
+ exit(1);
+ }
+
+ else
+ {
+ cout << CFILEOK << "..." << endl;
+ }
+
+ p_xml = new TiXmlDocument(s_config.c_str());
+ TiXmlBase::SetCondenseWhiteSpace( false );
+
+ if ( !p_xml->LoadFile() )
+ {
+ cout << XMLER1 << endl;
+ exit(1);
+ }
+
+ vector<string> vec_string;
+ parse_xml(p_xml, &vec_string);
+
+ shashmap<string>::add_elem_insecure(tool::yhttpd_version(), "yhttpd.version");
+
+ // Overrides yhttpd.conf values with command line options (yhttpd -o key1 value1 -o key2 value2 ...)
+ map<string,string>::iterator iter;
+ for ( iter = p_main_loop_params->begin(); iter != p_main_loop_params->end(); iter++ )
+ {
+ shashmap<string>::del_elem_insecure(iter->first);
+ shashmap<string>::add_elem_insecure(iter->second, iter->first);
+ }
+
+ delete p_xml;
+}
+
+void
+conf::parse_xml(TiXmlNode* p_node, vector<string>* p_vec)
+{
+ if ( p_node->NoChildren() )
+ return;
+
+ for ( TiXmlNode* p_child = p_node->FirstChild(); p_child; p_child = p_child->NextSibling() )
+ {
+ //cout << p_vec->size() << ": (Value:" << p_child->Value() << ") (Type:" << p_child->Type() << ")" << endl;
+
+ if ( strcmp(p_child->Value(),"config") == 0 )
+ {
+ parse_xml(p_child, p_vec);
+ }
+
+ else if ( strcmp(p_child->Value(),"category") == 0 )
+ {
+ p_vec->push_back(p_child->ToElement()->Attribute("name"));
+ parse_xml(p_child, p_vec);
+ p_vec->pop_back();
+ }
+
+ else if ( strcmp(p_child->Value(),"option") == 0 )
+ {
+ string s_option_name = "";
+
+ for ( vector<string>::iterator iter = p_vec->
+ begin();
+ iter != p_vec->end();
+ ++iter )
+ s_option_name.append(*iter + ".");
+
+ TiXmlElement* p_element = p_child->ToElement();
+ exit_if_xml_error();
+
+ s_option_name.append(p_element->Attribute("name"));
+
+#ifdef VERBOSE
+ cout << XMLREAD << s_option_name;
+#endif
+
+ TiXmlNode *p_node_value = p_element->FirstChild("value");
+ TiXmlNode *p_node_descr = p_element->FirstChild("descr");
+
+ TiXmlText* p_text_value = NULL;
+ TiXmlText* p_text_descr = NULL;
+
+ if ( p_node_value && p_node_value->FirstChild()
+ )
+ p_text_value = p_node_value->FirstChild()->ToText();
+
+ if ( p_node_descr && p_node_descr->FirstChild()
+ )
+ p_text_descr = p_node_descr->FirstChild()->ToText();
+
+ if ( !p_text_value )
+ continue;
+
+#ifdef VERBOSE
+ cout << " := " << p_text_value->Value() << endl;
+#endif
+
+ shashmap<string>::add_elem_insecure(p_text_value->Value(), s_option_name);
+
+ if ( !p_text_descr )
+ continue;
+
+ s_option_name.append(".descr");
+#ifdef VERBOSE
+ cout << XMLREAD << s_option_name << endl;
+#endif
+ shashmap<string>::add_elem_insecure(p_text_descr->Value(), s_option_name);
+ }
+ }
+
+ exit_if_xml_error()
+ ;
+}
+
+conf::~conf()
+{
+ delete p_xml;
+}
+
+void
+conf::exit_if_xml_error() const
+{
+ if ( p_xml->Error() )
+ {
+ cout << XMLERR << p_xml->ErrorDesc() << endl;
+ exit(1);
+ }
+}
+
+
+int
+conf::get_int(string s_key)
+{
+ return tool::string2int(get_elem(s_key));
+}
+
+vector<string>
+conf::get_vector(string s_key)
+{
+ vector<string> vec_ret;
+ string s_val = get_elem(s_key);
+
+ for (unsigned i_pos = s_val.find(" "); i_pos != string::npos; i_pos = s_val.find(" "))
+ {
+ vec_ret.push_back(s_val.substr(0, i_pos));
+ s_val = s_val.substr(i_pos+1);
+ }
+
+ vec_ret.push_back(s_val);
+ return vec_ret;
+}
+#endif
diff --git a/yhttpd/src/conf/conf.h b/yhttpd/src/conf/conf.h
new file mode 100644
index 0000000..b083d8c
--- /dev/null
+++ b/yhttpd/src/conf/conf.h
@@ -0,0 +1,29 @@
+#ifndef CONF_H
+#define CONF_H
+
+class conf; // Predefine for nmap.tmpl
+
+#include <map>
+#include "../incl.h"
+#include "../maps/shashmap.h"
+#include "../name.h"
+#include "../contrib/xml/tinyxml.h"
+
+using namespace std;
+
+class conf : public shashmap<string>, name
+{
+private:
+ TiXmlDocument* p_xml;
+ void exit_if_xml_error() const;
+ void parse_xml( TiXmlNode* p_node, vector<string>* p_vec);
+
+public:
+ conf(string s_conf, map<string,string>* p_main_loop_params);
+ ~conf();
+
+ int get_int(string s_key);
+ vector<string> get_vector(string s_key);
+};
+
+#endif
diff --git a/yhttpd/src/configure b/yhttpd/src/configure
new file mode 100755
index 0000000..54cf650
--- /dev/null
+++ b/yhttpd/src/configure
@@ -0,0 +1,350 @@
+#!/bin/sh
+
+#
+# The yhttpd Project (2003 - 2005)
+#
+
+if ! ../scripts/checkperl.sh
+then
+ exit 1
+fi
+
+if ! test -f ../g++.version
+then
+ echo You need to run ./configure of the top level source dir first
+ exit 1
+fi
+
+perl -e '
+ use strict;
+ $|=1;
+
+ my %libadd;
+ my %incadd;
+ my $deepness = 500;
+
+ my @headers = (
+ "dlfcn.h",
+ "pthread.h",
+ "netinet/in.h",
+ "time.h",
+ "ncurses.h",
+ "openssl/ssl.h",
+ "::test::ext/hash_map"
+ );
+
+ my @libs = (
+ "libncurses.so",
+ "libssl.so",
+ "libcrypto.so"
+ );
+
+ my @headerpaths = (
+ $ENV{HOME}."/include",
+ $ENV{HOME}."/usr/include",
+ "/include",
+ "/usr/include",
+ "/usr/local/include",
+ "/usr/lib/",
+ "/usr/pkg/include",
+ "/opt/include",
+ "/opt/local/include"
+ );
+
+ my @libpaths = (
+ $ENV{HOME}."/lib",
+ $ENV{HOME}."/usr/lib",
+ "/lib",
+ "/usr/lib",
+ "/usr/local/lib",
+ "/usr/pkg/lib",
+ "/opt/lib",
+ "/opt/local/lib"
+ );
+
+ my %dependfiles = (
+ database => ["data"],
+ ycurses => ["curses", "ycui.cpp", "ycui.h"],
+ logging => ["logd.cpp", "logd.h"],
+ cli => ["cli"],
+ opnssl => ["sock/sslsock.cpp", "sock/sslsock.h"]
+ );
+
+ open FILE, "glob.h" or die "glob.h: $!\n";
+ while(<FILE>) {
+ if ( /\/\/#define DATABASE/ ) {
+ remove_from_array("mysql/mysql.h",\@headers);
+ remove_from_array("libmysqlclient.so",\@libs);
+ mkdir "../backuped" unless -d "../backuped";
+ `mv $_ ../backuped` for @{$dependfiles{database}};
+ }
+
+ elsif ( /^#define DATABASE/ && !-d "data") {
+ `mv ../backuped/$_ .` for @{$dependfiles{database}};
+ }
+
+ if ( /\/\/#define LOGGING/ ) {
+ mkdir "../backuped" unless -d "../backuped";
+ `mv $_ ../backuped` for @{$dependfiles{logging}};
+ }
+
+ elsif ( /^#define LOGGING/ && !-f "logd.cpp") {
+ `mv ../backuped/$_ .` for @{$dependfiles{logging}};
+ }
+
+ if ( /\/\/#define CLI/ ) {
+ mkdir "../backuped" unless -d "../backuped";
+ `mv $_ ../backuped` for @{$dependfiles{cli}};
+ }
+
+ elsif ( /^#define CLI/ && !-d "cli") {
+ `mv ../backuped/$_ .` for @{$dependfiles{cli}};
+ }
+
+ if ( /\/\/#define YCURSES/ ) {
+ for ("ncurses", "menu", "panel") {
+ remove_from_array("$_.h",\@headers);
+ remove_from_array("lib$_.so",\@libs);
+ }
+
+ mkdir "../backuped" unless -d "../backuped";
+ `mv $_ ../backuped` for @{$dependfiles{ycurses}};
+ }
+
+ elsif ( /^#define YCURSES/ && !-d "curses") {
+ `mv ../backuped/$_ .` for @{$dependfiles{ycurses}};
+ }
+
+ if ( /\/\/#define OPENSSL/ ) {
+ remove_from_array("openssl/ssl.h",\@headers);
+ remove_from_array("lib$_.so",\@libs) for ("ssl", "crypto");
+ }
+ }
+ close FILE;
+
+ if ( defined $ENV{YHTTPDHEADERPATHS} ) {
+ map { print "Adding $_...\n"; unshift @headerpaths, $_ }
+ split /:/, $ENV{YHTTPDHEADERPATHS};
+ }
+
+ if ( defined $ENV{YHTTPDLIBPATHS} ) {
+ map { print "Adding $_...\n"; unshift @libpaths, $_ }
+ split /:/, $ENV{YHTTPDLIBPATHS};
+ }
+
+ print "Headers:\n";
+
+ my $testit = 0;
+ map { $incadd{&check($deepness, $_, @headerpaths)}++ }
+ @headers;
+
+ $testit = 0;
+ print "Libraries:\n";
+ map { $libadd{&check($deepness, $_, @libpaths)}++ }
+ @libs;
+
+ my $incadd = &make_add("-I", \%incadd);
+ my $libadd = &make_add("-L", \%libadd);
+
+ for ( @libs ) { $libadd .= "-l$_ " if s/^lib// and s/\.so$//; }
+
+ print "Incadd: $incadd\n";
+ print "Libadd: $libadd\n";
+
+ `echo $incadd > includes.add`;
+ `echo $libadd > libs.add`;
+
+ print "Creating new base Makefile...\n";
+ unlink("Makefile") if -f "Makefile";
+ unlink("../err") if -f "../err";
+ open Fin, "Makefile.in" or die "Makefile.in: $!\n";
+ open Fout, ">Makefile" or die "Makefile: $!\n";
+
+ my $cpp = `echo *.cpp */*.cpp contrib/*/*.cpp | sort`;
+ my $compiler = `tail -n 1 ../g++.version`;
+ my $version = `tail -n 2 ../g++.version | head -n 1`;
+ my $uname = `uname -srm`;
+ my $compopt = join "; ", split /\n/, `cat ../g++.version`;
+
+ chomp $uname;
+ chomp $compopt;
+
+ print "Configuring for $uname...\n";
+ chomp $cpp;
+ chomp $version;
+
+ while (<Fin>) {
+ s/^(CC=).*\n/$1$compiler/;
+ s/^(SRCS=).*/$1$cpp/;
+ s/ -frepo//; # unless $version =~ /3\.4/;
+ if ( $uname !~ /Linux/i ) {
+ print "Disabling -ldl flag...\n" if s/ -ldl//;
+ }
+ print Fout;
+ }
+ close Fin;
+
+ my $args = join(" -",@ARGV);
+ $args = "-".$args unless $args eq "";
+
+ for my $cppfile (split / /, $cpp) {
+ my $ofile = $cppfile;
+ $ofile =~ s/\.cpp/\.o/;
+ print Fout "../obj/$ofile: $cppfile\n";
+ print Fout "\t\@if ! test -d `dirname ../obj/$ofile`; then mkdir -p `dirname ../obj/$ofile`; fi\n";
+ my $class = $ofile;
+ $class =~ s/\.o//;
+
+ my $text;
+ if ( $class =~ /contrib\/.+/ ) {
+ my $dirname = `dirname $class`;
+ $text = "\t\@echo -n \"Contributed class $class \"\n";
+ }
+
+ else {
+ $text = "\t\@echo -n \"Base class $class \"\n";
+ }
+
+ print Fout "\t\@\$(CC) \$(CFLAGS) \$(INCLUDES) $args -c -o ../obj/$ofile $cppfile\n";
+ print Fout $text."\t\@du -hc ../obj/$ofile | tail -n 1 | sed s/total// | sed \"s/ //g\"\n";
+ }
+
+ close Fout;
+
+ open F, "msgs.h" or die "msgs.h: $!\n";
+ my @msgs = <F>;
+ close F;
+ unlink("msgs.h");
+ open F, ">msgs.h" or die "msgs.h: $!\n";
+
+ for (@msgs) {
+ s/(UNAME)(.+)$/UNAME "$uname"/;
+ s/(COMPOPT)(.+)$/COMPOPT "$compopt"/;
+ print F;
+ }
+ close F;
+
+ if ( -d "mods" ) {
+ chdir("mods");
+ my $cflags = "-fno-inline -fno-default-inline";
+
+ $cflags .= " -nostdlib" if $uname =~ /FreeBSD/i && `uname -r` =~ /^4\./;
+
+ system("echo $cflags > cflags.add");
+ system("./configure");
+ chdir("..");
+ }
+
+ sub remove_from_array {
+ my $elem = shift;
+ my $array = shift;
+
+ for ( my $i = 0; $i <= $#$array; ++$i ) {
+ if ( $$array[$i] eq $elem ) {
+ splice(@$array,$i,1);
+ last;
+ }
+ } # for
+ }
+
+ sub check {
+ my $deep = shift;
+
+ if ($deep == 0) {
+ print "Looking too deep! ($deepness)\n";
+ exit(1);
+ }
+
+ my $check = shift;
+ $testit = 1 if $check =~ s/::test:://;
+
+ my $print = 1;
+ if ( $_[-1] eq "subsearch" ) {
+ $print = 0;
+ pop(@_);
+ }
+
+ if ($print) {
+ print "Checking for $check...";
+ print "\n" if $testit;
+ }
+
+ for (@_) {
+ if ( -f "$_/$check" ) {
+ if ($testit) {
+ return $_ if test_include($_, $check);
+ return "";
+
+ } else {
+ print "OK\n";
+ return "" if $_ eq "/usr/lib" or $_ eq "/usr/include";
+ return $_;
+ }
+ }
+ }
+
+ for (@_) {
+ next unless -d $_;
+ opendir D, $_ or warn "$_: $!\n";
+ my @dir = readdir(D);
+ closedir D;
+
+ for my $dir ( @dir ) {
+ next if $dir =~ /^\.+$/ or !-d "$_/$dir";
+ my $path = &check($deep-1, $check, "$_/$dir", "subsearch");
+ return $path if $path ne "";
+ }
+ }
+
+ if ($print) {
+ print "NOT OK\n";
+ print "Please make sure that you have the needed software installed!\n";
+ print "If you have a special path for your includes then edit src/configure!\n";
+ print "Or set the environment variables YHTTPDHEADERPATHS and YHTTPDLIBPATHS.\n";
+ print " Example: setenv YHTTPDHEADERPATHS \"/your/header/includes:/a/includes\"\n";
+ print "(The environment variables have to be seperated by an :)\n";
+ print "PS: You may use the locate and/or find command to search for files.\n";
+ exit(1);
+ }
+
+ `touch ../err`;
+ return "";
+ }
+
+ sub make_add {
+ my $flag = shift;
+ my $add = shift;
+ my $ret = "";
+
+ for (reverse keys %$add) {
+ next unless /.+/;
+ $ret .= "$flag$_ ";
+ }
+ return $ret;
+ }
+
+ sub test_include {
+ my $shift = shift;
+ my $check = shift;
+ my $return = 0;
+ print "Testing $shift/$check...";
+
+ `echo "\#include \\"maps/hashmap.h\\"" > __test.cpp`;
+ `echo "int main(void){return 0;}" >> __test.cpp`;
+ my $cmd = "`tail -n 1 ../g++.version` -I$shift __test.cpp -o /dev/null 2>/dev/null";
+ system $cmd;
+
+ unless ($?) {
+ print "OK\n";
+ $return = 1;
+
+ } else {
+ print "Not OK\n";
+ }
+
+ unlink "__test.cpp" if -f "__test.cpp";
+ return $return;
+ }
+
+ exit(0);
+' `echo "$*" | sed "s/-//g"`
diff --git a/yhttpd/src/contrib/README b/yhttpd/src/contrib/README
new file mode 100644
index 0000000..105f25d
--- /dev/null
+++ b/yhttpd/src/contrib/README
@@ -0,0 +1,5 @@
+This directory includes source code which has been included directly into yhttpd but is not
+programmed by the yhttpd project explicitly which means the source code here is from extern.
+
+Used versions:
+tinyxml 2.3.2
diff --git a/yhttpd/src/contrib/xml/README b/yhttpd/src/contrib/xml/README
new file mode 100644
index 0000000..7da9dfd
--- /dev/null
+++ b/yhttpd/src/contrib/xml/README
@@ -0,0 +1,504 @@
+ATTENTION:
+
+This version of TinyXML has ben very little modified by
+Paul C. Buetow in 2004 to fit the yhttpd project.
+
+To get the original source go to
+http://www.sourceforge.net/projects/tinyxml
+
+/** @mainpage
+
+<h1> TinyXml </h1>
+
+TinyXml is a simple, small, C++ XML parser that can be easily
+integrating into other programs.
+
+
+<h2> What it does. </h2>
+
+In brief, TinyXml parses an XML document, and builds from that a
+Document Object Model (DOM) that can be read, modified, and saved.
+
+XML stands for "eXtensible Markup Language." It allows you to create
+your own document markups. Where HTML does a very good job of marking
+documents for browsers, XML allows you to define any kind of document
+markup, for example a document that describes a "to do" list for an
+organizer application. XML is a very structured and convenient format.
+All those random file formats created to store application data can
+all be replaced with XML. One parser for everything.
+
+The best place for the complete, correct, and quite frankly hard to
+read spec is at <a href="http://www.w3.org/TR/2004/REC-xml-20040204/">
+http://www.w3.org/TR/2004/REC-xml-20040204/</a>. An intro to XML
+(that I really like) can be found at
+<a href="http://skew.org/xml/tutorial/">http://skew.org/xml/tutorial</a>.
+
+There are different ways to access and interact with XML data.
+TinyXml uses a Document Object Model (DOM), meaning the XML data is parsed
+into a C++ objects that can be browsed and manipulated, and then
+written to disk or another output stream. You can also construct an XML document from
+scratch with C++ objects and write this to disk or another output
+stream.
+
+TinyXml is designed to be easy and fast to learn. It is two headers
+and four cpp files. Simply add these to your project and off you go.
+There is an example file - xmltest.cpp - to get you started.
+
+TinyXml is released under the ZLib license,
+so you can use it in open source or commercial code. The details
+of the license are at the top of every source file.
+
+TinyXml attempts to be a flexible parser, but with truly correct and
+compliant XML output. TinyXml should compile on any reasonably C++
+compliant system. It does not rely on exceptions or RTTI. It can be
+compiled with or without STL support. TinyXml fully supports
+the UTF-8 encoding, and the first 64k character entities.
+
+
+<h2> What it doesn't do. </h2>
+
+It doesnt parse or use DTDs (Document Type Definitions) or XSLs
+(eXtensible Stylesheet Language.) There are other parsers out there
+(check out www.sourceforge.org, search for XML) that are much more fully
+featured. But they are also much bigger, take longer to set up in
+your project, have a higher learning curve, and often have a more
+restrictive license. If you are working with browsers or have more
+complete XML needs, TinyXml is not the parser for you.
+
+The following DTD syntax will not parse at this time in TinyXml:
+
+@verbatim
+ <!DOCTYPE Archiv [
+ <!ELEMENT Comment (#PCDATA)>
+ ]>
+@endverbatim
+
+because TinyXml sees this as a !DOCTYPE node with an illegally
+embedded !ELEMENT node. This may be addressed in the future.
+
+<h2> Code Status. </h2>
+
+TinyXml is mature, tested code. It is very stable. If you find
+bugs, please file a bug report is on the sourceforge web site
+(www.sourceforge.net/projects/tinyxml).
+We'll get them straightened out as soon as possible.
+
+There are some areas of improvement; please check sourceforge if you are
+interested in working on TinyXml.
+
+
+<h2> Features </h2>
+
+<h3> Using STL </h3>
+
+TinyXml can be compiled to use or not use STL. When using STL, TinyXml
+uses the std::string class, and fully supports std::istream, std::ostream,
+operator<<, and operator>>. Many API methods have both 'const char*' and
+'const std::string&' forms.
+
+When STL support is compiled out, no STL files are included whatsover. All
+the string classes are implemented by TinyXml itself. API methods
+all use the 'const char*' form for input.
+
+Use the compile time #define:
+
+ TIXML_USE_STL
+
+to compile one version or the other. This can be passed by the compiler,
+or set as the first line of "tinyxml.h".
+
+Note: If compiling the test code in Linux, setting the environment
+variable TINYXML_USE_STL=YES/NO will control STL compilation. In the
+Windows project file, STL and non STL targets are provided. In your project,
+its probably easiest to add the line "#define TIXML_USE_STL" as the first
+line of tinyxml.h.
+
+<h3> UTF-8 </h3>
+
+TinyXml supports UTF-8 allowing to manipulate XML files in any language. TinyXml
+also supports "legacy mode" - the encoding used before UTF-8 support and
+probably best described as "extended ascii".
+
+Normally, TinyXml will try to detect the correct encoding and use it. However,
+by setting the value of TIXML_DEFAULT_ENCODING in the header file, TinyXml
+can be forced to always use one encoding.
+
+TinyXml will assume Legacy Mode until one of the following occurs:
+<ol>
+ <li> If the non-standard but common "UTF-8 lead bytes" (0xef 0xbb 0xbf)
+ begin the file or data stream, TinyXml will read it as UTF-8. </li>
+ <li> If the declaration tag is read, and it has an encoding="UTF-8", then
+ TinyXml will read it as UTF-8. </li>
+ <li> If the declaration tag is read, and it has no encoding specified, then
+ TinyXml will read it as UTF-8. </li>
+ <li> If the declaration tag is read, and it has an encoding="something else", then
+ TinyXml will read it as Legacy Mode. In legacy mode, TinyXml will
+ work as it did before. It's not clear what that mode does exactly, but
+ old content should keep working.</li>
+ <li> Until one of the above criteria is met, TinyXml runs in Legacy Mode.</li>
+</ol>
+
+What happens if the encoding is incorrectly set or detected? TinyXml will try
+to read and pass through text seen as improperly encoded. You may get some strange
+results or mangled characters. You may want to force TinyXml to the correct mode.
+
+<b> You may force TinyXml to Legacy Mode by using LoadFile( TIXML_ENCODING_LEGACY ) or
+LoadFile( filename, TIXML_ENCODING_LEGACY ). You may force it to use legacy mode all
+the time by setting TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY. Likewise, you may
+force it to TIXML_ENCODING_UTF8 with the same technique.</b>
+
+For English users, using English XML, UTF-8 is the same as low-ASCII. You
+don't need to be aware of UTF-8 or change your code in any way. You can think
+of UTF-8 as a "superset" of ASCII.
+
+UTF-8 is not a double byte format - but it is a standard encoding of Unicode!
+TinyXml does not use or directly support wchar, TCHAR, or Microsofts _UNICODE at this time.
+It is common to see the term "Unicode" improperly refer to UTF-16, a wide byte encoding
+of unicode. This is a source of confusion.
+
+For "high-ascii" languages - everything not English, pretty much - TinyXml can
+handle all languages, at the same time, as long as the XML is encoded
+in UTF-8. That can be a little tricky, older programs and operating systems
+tend to use the "default" or "traditional" code page. Many apps (and almost all
+modern ones) can output UTF-8, but older or stubborn (or just broken) ones
+still output text in the default code page.
+
+For example, Japanese systems traditionally use SHIFT-JIS encoding.
+Text encoded as SHIFT-JIS can not be read by tinyxml.
+A good text editor can import SHIFT-JIS and then save as UTF-8.
+
+The <a href="http://skew.org/xml/tutorial/">Skew.org link</a> does a great
+job covering the encoding issue.
+
+The test file "utf8test.xml" is an XML containing English, Spanish, Russian,
+and Simplified Chinese. (Hopefully they are translated correctly). The file
+"utf8test.gif" is a screen capture of the XML file, rendered in IE. Note that
+if you don't have the correct fonts (Simplified Chinese or Russian) on your
+system, you won't see output that matches the GIF file even if you can parse
+it correctly. Also note that (at least on my Windows machine) console output
+is in a Western code page, so that Print() or printf() cannot correctly display
+the file. This is not a bug in TinyXml - just an OS issue. No data is lost or
+destroyed by TinyXml. The console just doesn't render UTF-8.
+
+
+<h3> Entities </h3>
+TinyXml recognizes the pre-defined "character entities", meaning special
+characters. Namely:
+
+@verbatim
+ &amp; &
+ &lt; <
+ &gt; >
+ &quot; "
+ &apos; '
+@endverbatim
+
+These are recognized when the XML document is read, and translated to there
+UTF-8 equivalents. For instance, text with the XML of:
+
+@verbatim
+ Far &amp; Away
+@endverbatim
+
+will have the Value() of "Far & Away" when queried from the TiXmlText object,
+and will be written back to the XML stream/file as an ampersand. Older versions
+of TinyXml "preserved" character entities, but the newer versions will translate
+them into characters.
+
+Additionally, any character can be specified by its Unicode code point:
+The syntax "&#xA0;" or "&#160;" are both to the non-breaking space characher.
+
+
+<h3> Streams </h3>
+With TIXML_USE_STL on,
+TiXml has been modified to support both C (FILE) and C++ (operator <<,>>)
+streams. There are some differences that you may need to be aware of.
+
+C style output:
+ - based on FILE*
+ - the Print() and SaveFile() methods
+
+ Generates formatted output, with plenty of white space, intended to be as
+ human-readable as possible. They are very fast, and tolerant of ill formed
+ XML documents. For example, an XML document that contains 2 root elements
+ and 2 declarations, will still print.
+
+C style input:
+ - based on FILE*
+ - the Parse() and LoadFile() methods
+
+ A fast, tolerant read. Use whenever you don't need the C++ streams.
+
+C++ style ouput:
+ - based on std::ostream
+ - operator<<
+
+ Generates condensed output, intended for network transmission rather than
+ readability. Depending on your system's implementation of the ostream class,
+ these may be somewhat slower. (Or may not.) Not tolerant of ill formed XML:
+ a document should contain the correct one root element. Additional root level
+ elements will not be streamed out.
+
+C++ style input:
+ - based on std::istream
+ - operator>>
+
+ Reads XML from a stream, making it useful for network transmission. The tricky
+ part is knowing when the XML document is complete, since there will almost
+ certainly be other data in the stream. TinyXml will assume the XML data is
+ complete after it reads the root element. Put another way, documents that
+ are ill-constructed with more than one root element will not read correctly.
+ Also note that operator>> is somewhat slower than Parse, due to both
+ implementation of the STL and limitations of TinyXml.
+
+<h3> White space </h3>
+The world simply does not agree on whether white space should be kept, or condensed.
+For example, pretend the '_' is a space, and look at "Hello____world". HTML, and
+at least some XML parsers, will interpret this as "Hello_world". They condense white
+space. Some XML parsers do not, and will leave it as "Hello____world". (Remember
+to keep pretending the _ is a space.) Others suggest that __Hello___world__ should become
+Hello___world.
+
+It's an issue that hasn't been resolved to my satisfaction. TinyXml supports the
+first 2 approaches. Call TiXmlBase::SetCondenseWhiteSpace( bool ) to set the desired behavior.
+The default is to condense white space.
+
+If you change the default, you should call TiXmlBase::SetCondenseWhiteSpace( bool )
+before making any calls to Parse XML data, and I don't recommend changing it after
+it has been set.
+
+
+<h3> Handles </h3>
+
+Where browsing an XML document in a robust way, it is important to check
+for null returns from method calls. An error safe implementation can
+generate a lot of code like:
+
+@verbatim
+TiXmlElement* root = document.FirstChildElement( "Document" );
+if ( root )
+{
+ TiXmlElement* element = root->FirstChildElement( "Element" );
+ if ( element )
+ {
+ TiXmlElement* child = element->FirstChildElement( "Child" );
+ if ( child )
+ {
+ TiXmlElement* child2 = child->NextSiblingElement( "Child" );
+ if ( child2 )
+ {
+ // Finally do something useful.
+@endverbatim
+
+Handles have been introduced to clean this up. Using the TiXmlHandle class,
+the previous code reduces to:
+
+@verbatim
+TiXmlHandle docHandle( &document );
+TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).Element();
+if ( child2 )
+{
+ // do something useful
+@endverbatim
+
+Which is much easier to deal with. See TiXmlHandle for more information.
+
+
+<h3> Row and Column tracking </h3>
+Being able to track nodes and attributes back to their origin location
+in source files can be very important for some applications. Additionally,
+knowing where parsing errors occured in the original source can be very
+time saving.
+
+TinyXml can tracks the row and column origin of all nodes and attributes
+in a text file. The TiXmlBase::Row() and TiXmlBase::Column() methods return
+the origin of the node in the source text. The correct tabs can be
+configured in TiXmlDocument::SetTabSize().
+
+
+<h2> Using and Installing </h2>
+
+To Compile and Run xmltest:
+
+A Linux Makefile and a Windows Visual C++ .dsw file is provided.
+Simply compile and run. It will write the file demotest.xml to your
+disk and generate output on the screen. It also tests walking the
+DOM by printing out the number of nodes found using different
+techniques.
+
+The Linux makefile is very generic and will
+probably run on other systems, but is only tested on Linux. You no
+longer need to run 'make depend'. The dependecies have been
+hard coded.
+
+<h3>Windows project file for VC6</h3>
+<ul>
+<li>tinyxml: tinyxml library, non-STL </li>
+<li>tinyxmlSTL: tinyxml library, STL </li>
+<li>tinyXmlTest: test app, non-STL </li>
+<li>tinyXmlTestSTL: test app, STL </li>
+</ul>
+
+<h3>Linux Make file</h3>
+At the top of the makefile you can set:
+
+PROFILE, DEBUG, and TINYXML_USE_STL. Details (such that they are) are in
+the makefile.
+
+In the tinyxml directory, type "make clean" then "make". The executable
+file 'xmltest' will be created.
+
+
+
+<h3>To Use in an Application:</h3>
+
+Add tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, tinyxmlparser.cpp, and tinystr.cpp to your
+project or make file. That's it! It should compile on any reasonably
+compliant C++ system. You do not need to enable exceptions or
+RTTI for TinyXml.
+
+
+<h2> How TinyXml works. </h2>
+
+An example is probably the best way to go. Take:
+@verbatim
+ <?xml version="1.0" standalone=no>
+ <!-- Our to do list data -->
+ <ToDo>
+ <Item priority="1"> Go to the <bold>Toy store!</bold></Item>
+ <Item priority="2"> Do bills</Item>
+ </ToDo>
+@endverbatim
+
+Its not much of a To Do list, but it will do. To read this file
+(say "demo.xml") you would create a document, and parse it in:
+@verbatim
+ TiXmlDocument doc( "demo.xml" );
+ doc.LoadFile();
+@endverbatim
+
+And its ready to go. Now lets look at some lines and how they
+relate to the DOM.
+
+@verbatim
+<?xml version="1.0" standalone=no>
+@endverbatim
+
+ The first line is a declaration, and gets turned into the
+ TiXmlDeclaration class. It will be the first child of the
+ document node.
+
+ This is the only directive/special tag parsed by by TinyXml.
+ Generally directive targs are stored in TiXmlUnknown so the
+ commands wont be lost when it is saved back to disk.
+
+@verbatim
+<!-- Our to do list data -->
+@endverbatim
+
+ A comment. Will become a TiXmlComment object.
+
+@verbatim
+<ToDo>
+@endverbatim
+
+ The "ToDo" tag defines a TiXmlElement object. This one does not have
+ any attributes, but does contain 2 other elements.
+
+@verbatim
+<Item priority="1">
+@endverbatim
+
+ Creates another TiXmlElement which is a child of the "ToDo" element.
+ This element has 1 attribute, with the name "priority" and the value
+ "1".
+
+Go to the
+
+ A TiXmlText. This is a leaf node and cannot contain other nodes.
+ It is a child of the "Item" TiXmlElement.
+
+@verbatim
+<bold>
+@endverbatim
+
+
+ Another TiXmlElement, this one a child of the "Item" element.
+
+Etc.
+
+Looking at the entire object tree, you end up with:
+@verbatim
+TiXmlDocument "demo.xml"
+ TiXmlDeclaration "version='1.0'" "standalone=no"
+ TiXmlComment " Our to do list data"
+ TiXmlElement "ToDo"
+ TiXmlElement "Item" Attribtutes: priority = 1
+ TiXmlText "Go to the "
+ TiXmlElement "bold"
+ TiXmlText "Toy store!"
+ TiXmlElement "Item" Attributes: priority=2
+ TiXmlText "bills"
+@endverbatim
+
+<h2> Documentation </h2>
+
+The documentation is build with Doxygen, using the 'dox'
+configuration file.
+
+<h2> License </h2>
+
+TinyXml is released under the zlib license:
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+
+<h2> References </h2>
+
+The World Wide Web Consortium is the definitive standard body for
+XML, and there web pages contain huge amounts of information.
+
+The definitive spec: <a href="http://www.w3.org/TR/2004/REC-xml-20040204/">
+http://www.w3.org/TR/2004/REC-xml-20040204/</a>
+
+I also recommend "XML Pocket Reference" by Robert Eckstein and published by
+OReilly...the book that got the whole thing started.
+
+<h2> Contributors, Contacts, and a Brief History </h2>
+
+Thanks very much to everyone who sends suggestions, bugs, ideas, and
+encouragement. It all helps, and makes this project fun. A special thanks
+to the contributors on the web pages that keep it lively.
+
+So many people have sent in bugs and ideas, that rather than list here
+we try to give credit due in the "changes.txt" file.
+
+TinyXml was originally written be Lee Thomason. (Often the "I" still
+in the documenation.) Lee reviews changes and releases new versions,
+with the help of Yves Berquin and the tinyXml community.
+
+We appreciate your suggestions, and would love to know if you
+use TinyXml. Hopefully you will enjoy it and find it useful.
+Please post questions, comments, file bugs, or contact us at:
+
+www.sourceforge.net/projects/tinyxml
+
+Lee Thomason,
+Yves Berquin
+*/
diff --git a/yhttpd/src/contrib/xml/tinyxml.cpp b/yhttpd/src/contrib/xml/tinyxml.cpp
new file mode 100644
index 0000000..73e57c2
--- /dev/null
+++ b/yhttpd/src/contrib/xml/tinyxml.cpp
@@ -0,0 +1,1428 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include <ctype.h>
+#include "tinyxml.h"
+
+#ifdef TIXML_USE_STL
+#include <sstream>
+#endif
+
+
+bool TiXmlBase::condenseWhiteSpace = true;
+
+void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream )
+{
+ TIXML_STRING buffer;
+ PutString( str, &buffer );
+ (*stream) << buffer;
+}
+
+void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString )
+{
+ int i=0;
+
+ while( i<(int)str.length() )
+ {
+ unsigned char c = (unsigned char) str[i];
+
+ if ( c == '&'
+ && i < ( (int)str.length() - 2 )
+ && str[i+1] == '#'
+ && str[i+2] == 'x' )
+ {
+ // Hexadecimal character reference.
+ // Pass through unchanged.
+ // &#xA9; -- copyright symbol, for example.
+ //
+ // The -1 is a bug fix from Rob Laveaux. It keeps
+ // an overflow from happening if there is no ';'.
+ // There are actually 2 ways to exit this loop -
+ // while fails (error case) and break (semicolon found).
+ // However, there is no mechanism (currently) for
+ // this function to return an error.
+ while ( i<(int)str.length()-1 )
+ {
+ outString->append( str.c_str() + i, 1 );
+ ++i;
+ if ( str[i] == ';' )
+ break;
+ }
+ }
+ else if ( c == '&' )
+ {
+ outString->append( entity[0].str, entity[0].strLength );
+ ++i;
+ }
+ else if ( c == '<' )
+ {
+ outString->append( entity[1].str, entity[1].strLength );
+ ++i;
+ }
+ else if ( c == '>' )
+ {
+ outString->append( entity[2].str, entity[2].strLength );
+ ++i;
+ }
+ else if ( c == '\"' )
+ {
+ outString->append( entity[3].str, entity[3].strLength );
+ ++i;
+ }
+ else if ( c == '\'' )
+ {
+ outString->append( entity[4].str, entity[4].strLength );
+ ++i;
+ }
+ else if ( c < 32 )
+ {
+ // Easy pass at non-alpha/numeric/symbol
+ // Below 32 is symbolic.
+ char buf[ 32 ];
+ sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
+ outString->append( buf, strlen( buf ) );
+ ++i;
+ }
+ else
+ {
+ //char realc = (char) c;
+ //outString->append( &realc, 1 );
+ *outString += (char) c; // somewhat more efficient function call.
+ ++i;
+ }
+ }
+}
+
+
+// <-- Strange class for a bug fix. Search for STL_STRING_BUG
+TiXmlBase::StringToBuffer::StringToBuffer( const TIXML_STRING& str )
+{
+ buffer = new char[ str.length()+1 ];
+ if ( buffer )
+ {
+ strcpy( buffer, str.c_str() );
+ }
+}
+
+
+TiXmlBase::StringToBuffer::~StringToBuffer()
+{
+ delete [] buffer;
+}
+// End strange bug fix. -->
+
+
+TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
+{
+ parent = 0;
+ type = _type;
+ firstChild = 0;
+ lastChild = 0;
+ prev = 0;
+ next = 0;
+}
+
+
+TiXmlNode::~TiXmlNode()
+{
+ TiXmlNode* node = firstChild;
+ TiXmlNode* temp = 0;
+
+ while ( node )
+ {
+ temp = node;
+ node = node->next;
+ delete temp;
+ }
+}
+
+
+void TiXmlNode::CopyTo( TiXmlNode* target ) const
+{
+ target->SetValue (value.c_str() );
+ target->userData = userData;
+}
+
+
+void TiXmlNode::Clear()
+{
+ TiXmlNode* node = firstChild;
+ TiXmlNode* temp = 0;
+
+ while ( node )
+ {
+ temp = node;
+ node = node->next;
+ delete temp;
+ }
+
+ firstChild = 0;
+ lastChild = 0;
+}
+
+
+TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
+{
+ node->parent = this;
+
+ node->prev = lastChild;
+ node->next = 0;
+
+ if ( lastChild )
+ lastChild->next = node;
+ else
+ firstChild = node; // it was an empty list.
+
+ lastChild = node;
+ return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
+{
+ TiXmlNode* node = addThis.Clone();
+ if ( !node )
+ return 0;
+
+ return LinkEndChild( node );
+}
+
+
+TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
+{
+ if ( !beforeThis || beforeThis->parent != this )
+ return 0;
+
+ TiXmlNode* node = addThis.Clone();
+ if ( !node )
+ return 0;
+ node->parent = this;
+
+ node->next = beforeThis;
+ node->prev = beforeThis->prev;
+ if ( beforeThis->prev )
+ {
+ beforeThis->prev->next = node;
+ }
+ else
+ {
+ assert( firstChild == beforeThis );
+ firstChild = node;
+ }
+ beforeThis->prev = node;
+ return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
+{
+ if ( !afterThis || afterThis->parent != this )
+ return 0;
+
+ TiXmlNode* node = addThis.Clone();
+ if ( !node )
+ return 0;
+ node->parent = this;
+
+ node->prev = afterThis;
+ node->next = afterThis->next;
+ if ( afterThis->next )
+ {
+ afterThis->next->prev = node;
+ }
+ else
+ {
+ assert( lastChild == afterThis );
+ lastChild = node;
+ }
+ afterThis->next = node;
+ return node;
+}
+
+
+TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
+{
+ if ( replaceThis->parent != this )
+ return 0;
+
+ TiXmlNode* node = withThis.Clone();
+ if ( !node )
+ return 0;
+
+ node->next = replaceThis->next;
+ node->prev = replaceThis->prev;
+
+ if ( replaceThis->next )
+ replaceThis->next->prev = node;
+ else
+ lastChild = node;
+
+ if ( replaceThis->prev )
+ replaceThis->prev->next = node;
+ else
+ firstChild = node;
+
+ delete replaceThis;
+ node->parent = this;
+ return node;
+}
+
+
+bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
+{
+ if ( removeThis->parent != this )
+ {
+ assert( 0 );
+ return false;
+ }
+
+ if ( removeThis->next )
+ removeThis->next->prev = removeThis->prev;
+ else
+ lastChild = removeThis->prev;
+
+ if ( removeThis->prev )
+ removeThis->prev->next = removeThis->next;
+ else
+ firstChild = removeThis->next;
+
+ delete removeThis;
+ return true;
+}
+
+TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
+{
+ TiXmlNode* node;
+ for ( node = firstChild; node; node = node->next )
+ {
+ if ( node->SValue() == TIXML_STRING( _value ))
+ return node;
+ }
+ return 0;
+}
+
+TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
+{
+ TiXmlNode* node;
+ for ( node = lastChild; node; node = node->prev )
+ {
+ if ( node->SValue() == TIXML_STRING (_value))
+ return node;
+ }
+ return 0;
+}
+
+TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous ) const
+{
+ if ( !previous )
+ {
+ return FirstChild();
+ }
+ else
+ {
+ assert( previous->parent == this );
+ return previous->NextSibling();
+ }
+}
+
+TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous ) const
+{
+ if ( !previous )
+ {
+ return FirstChild( val );
+ }
+ else
+ {
+ assert( previous->parent == this );
+ return previous->NextSibling( val );
+ }
+}
+
+TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
+{
+ TiXmlNode* node;
+ for ( node = next; node; node = node->next )
+ {
+ if ( node->SValue() == TIXML_STRING (_value))
+ return node;
+ }
+ return 0;
+}
+
+
+TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
+{
+ TiXmlNode* node;
+ for ( node = prev; node; node = node->prev )
+ {
+ if ( node->SValue() == TIXML_STRING (_value))
+ return node;
+ }
+ return 0;
+}
+
+void TiXmlElement::RemoveAttribute( const char * name )
+{
+ TiXmlAttribute* node = attributeSet.Find( name );
+ if ( node )
+ {
+ attributeSet.Remove( node );
+ delete node;
+ }
+}
+
+TiXmlElement* TiXmlNode::FirstChildElement() const
+{
+ TiXmlNode* node;
+
+ for ( node = FirstChild();
+ node;
+ node = node->NextSibling() )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
+{
+ TiXmlNode* node;
+
+ for ( node = FirstChild( _value );
+ node;
+ node = node->NextSibling( _value ) )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+
+TiXmlElement* TiXmlNode::NextSiblingElement() const
+{
+ TiXmlNode* node;
+
+ for ( node = NextSibling();
+ node;
+ node = node->NextSibling() )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
+{
+ TiXmlNode* node;
+
+ for ( node = NextSibling( _value );
+ node;
+ node = node->NextSibling( _value ) )
+ {
+ if ( node->ToElement() )
+ return node->ToElement();
+ }
+ return 0;
+}
+
+
+
+TiXmlDocument* TiXmlNode::GetDocument() const
+{
+ const TiXmlNode* node;
+
+ for( node = this; node; node = node->parent )
+ {
+ if ( node->ToDocument() )
+ return node->ToDocument();
+ }
+ return 0;
+}
+
+
+TiXmlElement::TiXmlElement (const char * _value)
+ : TiXmlNode( TiXmlNode::ELEMENT )
+{
+ firstChild = lastChild = 0;
+ value = _value;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlElement::TiXmlElement( const std::string& _value )
+ : TiXmlNode( TiXmlNode::ELEMENT )
+{
+ firstChild = lastChild = 0;
+ value = _value;
+}
+#endif
+
+
+TiXmlElement::TiXmlElement( const TiXmlElement& copy)
+ : TiXmlNode( TiXmlNode::ELEMENT )
+{
+ firstChild = lastChild = 0;
+ copy.CopyTo( this );
+}
+
+
+void TiXmlElement::operator=( const TiXmlElement& base )
+{
+ ClearThis();
+ base.CopyTo( this );
+}
+
+
+TiXmlElement::~TiXmlElement()
+{
+ ClearThis();
+}
+
+
+void TiXmlElement::ClearThis()
+{
+ Clear();
+ while( attributeSet.First() )
+ {
+ TiXmlAttribute* node = attributeSet.First();
+ attributeSet.Remove( node );
+ delete node;
+ }
+}
+
+
+const char * TiXmlElement::Attribute( const char * name ) const
+{
+ TiXmlAttribute* node = attributeSet.Find( name );
+
+ if ( node )
+ return node->Value();
+
+ return 0;
+}
+
+
+const char * TiXmlElement::Attribute( const char * name, int* i ) const
+{
+ const char * s = Attribute( name );
+ if ( i )
+ {
+ if ( s )
+ *i = atoi( s );
+ else
+ *i = 0;
+ }
+ return s;
+}
+
+
+const char * TiXmlElement::Attribute( const char * name, double* d ) const
+{
+ const char * s = Attribute( name );
+ if ( d )
+ {
+ if ( s )
+ *d = atof( s );
+ else
+ *d = 0;
+ }
+ return s;
+}
+
+
+int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
+{
+ TiXmlAttribute* node = attributeSet.Find( name );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+
+ return node->QueryIntValue( ival );
+}
+
+
+int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
+{
+ TiXmlAttribute* node = attributeSet.Find( name );
+ if ( !node )
+ return TIXML_NO_ATTRIBUTE;
+
+ return node->QueryDoubleValue( dval );
+}
+
+
+void TiXmlElement::SetAttribute( const char * name, int val )
+{
+ char buf[64];
+ sprintf( buf, "%d", val );
+ SetAttribute( name, buf );
+}
+
+
+void TiXmlElement::SetDoubleAttribute( const char * name, double val )
+{
+ char buf[128];
+ sprintf( buf, "%f", val );
+ SetAttribute( name, buf );
+}
+
+
+void TiXmlElement::SetAttribute( const char * name, const char * _value )
+{
+ TiXmlAttribute* node = attributeSet.Find( name );
+ if ( node )
+ {
+ node->SetValue( _value );
+ return;
+ }
+
+ TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
+ if ( attrib )
+ {
+ attributeSet.Add( attrib );
+ }
+ else
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ }
+}
+
+void TiXmlElement::Print( FILE* cfile, int depth ) const
+{
+ int i;
+ for ( i=0; i<depth; i++ )
+ {
+ fprintf( cfile, " " );
+ }
+
+ fprintf( cfile, "<%s", value.c_str() );
+
+ TiXmlAttribute* attrib;
+ for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
+ {
+ fprintf( cfile, " " );
+ attrib->Print( cfile, depth );
+ }
+
+ // There are 3 different formatting approaches:
+ // 1) An element without children is printed as a <foo /> node
+ // 2) An element with only a text child is printed as <foo> text </foo>
+ // 3) An element with children is printed on multiple lines.
+ TiXmlNode* node;
+ if ( !firstChild )
+ {
+ fprintf( cfile, " />" );
+ }
+ else if ( firstChild == lastChild && firstChild->ToText() )
+ {
+ fprintf( cfile, ">" );
+ firstChild->Print( cfile, depth + 1 );
+ fprintf( cfile, "</%s>", value.c_str() );
+ }
+ else
+ {
+ fprintf( cfile, ">" );
+
+ for ( node = firstChild; node; node=node->NextSibling() )
+ {
+ if ( !node->ToText() )
+ {
+ fprintf( cfile, "\n" );
+ }
+ node->Print( cfile, depth+1 );
+ }
+ fprintf( cfile, "\n" );
+ for( i=0; i<depth; ++i )
+ fprintf( cfile, " " );
+ fprintf( cfile, "</%s>", value.c_str() );
+ }
+}
+
+void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const
+{
+ (*stream) << "<" << value;
+
+ TiXmlAttribute* attrib;
+ for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
+ {
+ (*stream) << " ";
+ attrib->StreamOut( stream );
+ }
+
+ // If this node has children, give it a closing tag. Else
+ // make it an empty tag.
+ TiXmlNode* node;
+ if ( firstChild )
+ {
+ (*stream) << ">";
+
+ for ( node = firstChild; node; node=node->NextSibling() )
+ {
+ node->StreamOut( stream );
+ }
+ (*stream) << "</" << value << ">";
+ }
+ else
+ {
+ (*stream) << " />";
+ }
+}
+
+
+void TiXmlElement::CopyTo( TiXmlElement* target ) const
+{
+ // superclass:
+ TiXmlNode::CopyTo( target );
+
+ // Element class:
+ // Clone the attributes, then clone the children.
+ TiXmlAttribute* attribute = 0;
+ for( attribute = attributeSet.First();
+ attribute;
+ attribute = attribute->Next() )
+ {
+ target->SetAttribute( attribute->Name(), attribute->Value() );
+ }
+
+ TiXmlNode* node = 0;
+ for ( node = firstChild; node; node = node->NextSibling() )
+ {
+ target->LinkEndChild( node->Clone() );
+ }
+}
+
+
+TiXmlNode* TiXmlElement::Clone() const
+{
+ TiXmlElement* clone = new TiXmlElement( Value() );
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+ tabsize = 4;
+ ClearError();
+}
+
+TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+ tabsize = 4;
+ value = documentName;
+ ClearError();
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+ tabsize = 4;
+ value = documentName;
+ ClearError();
+}
+#endif
+
+
+TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+ copy.CopyTo( this );
+}
+
+
+void TiXmlDocument::operator=( const TiXmlDocument& copy )
+{
+ Clear();
+ copy.CopyTo( this );
+}
+
+
+bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
+{
+ // See STL_STRING_BUG below.
+ StringToBuffer buf( value );
+
+ if ( buf.buffer && LoadFile( buf.buffer, encoding ) )
+ return true;
+
+ return false;
+}
+
+
+bool TiXmlDocument::SaveFile() const
+{
+ // See STL_STRING_BUG below.
+ StringToBuffer buf( value );
+
+ if ( buf.buffer && SaveFile( buf.buffer ) )
+ return true;
+
+ return false;
+}
+
+bool TiXmlDocument::LoadFile( const char* filename, TiXmlEncoding encoding )
+{
+ // Delete the existing data:
+ Clear();
+ location.Clear();
+
+ // There was a really terrifying little bug here. The code:
+ // value = filename
+ // in the STL case, cause the assignment method of the std::string to
+ // be called. What is strange, is that the std::string had the same
+ // address as it's c_str() method, and so bad things happen. Looks
+ // like a bug in the Microsoft STL implementation.
+ // See STL_STRING_BUG above.
+ // Fixed with the StringToBuffer class.
+ value = filename;
+
+ FILE* file = fopen( value.c_str (), "r" );
+
+ if ( file )
+ {
+ // Get the file size, so we can pre-allocate the string. HUGE speed impact.
+ long length = 0;
+ fseek( file, 0, SEEK_END );
+ length = ftell( file );
+ fseek( file, 0, SEEK_SET );
+
+ // Strange case, but good to handle up front.
+ if ( length == 0 )
+ {
+ fclose( file );
+ return false;
+ }
+
+ // If we have a file, assume it is all one big XML file, and read it in.
+ // The document parser may decide the document ends sooner than the entire file, however.
+ TIXML_STRING data;
+ data.reserve( length );
+
+ const int BUF_SIZE = 2048;
+ char buf[BUF_SIZE];
+
+ while( fgets( buf, BUF_SIZE, file ) )
+ {
+ data += buf;
+ }
+ fclose( file );
+
+ Parse( data.c_str(), 0, encoding );
+
+ if ( Error() )
+ return false;
+ else
+ return true;
+ }
+ SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return false;
+}
+
+bool TiXmlDocument::SaveFile( const char * filename ) const
+{
+ // The old c stuff lives on...
+ FILE* fp = fopen( filename, "w" );
+ if ( fp )
+ {
+ Print( fp, 0 );
+ fclose( fp );
+ return true;
+ }
+ return false;
+}
+
+
+void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
+{
+ TiXmlNode::CopyTo( target );
+
+ target->error = error;
+ target->errorDesc = errorDesc.c_str ();
+
+ TiXmlNode* node = 0;
+ for ( node = firstChild; node; node = node->NextSibling() )
+ {
+ target->LinkEndChild( node->Clone() );
+ }
+}
+
+
+TiXmlNode* TiXmlDocument::Clone() const
+{
+ TiXmlDocument* clone = new TiXmlDocument();
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+void TiXmlDocument::Print( FILE* cfile, int depth ) const
+{
+ TiXmlNode* node;
+ for ( node=FirstChild(); node; node=node->NextSibling() )
+ {
+ node->Print( cfile, depth );
+ fprintf( cfile, "\n" );
+ }
+}
+
+void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const
+{
+ TiXmlNode* node;
+ for ( node=FirstChild(); node; node=node->NextSibling() )
+ {
+ node->StreamOut( out );
+
+ // Special rule for streams: stop after the root element.
+ // The stream in code will only read one element, so don't
+ // write more than one.
+ if ( node->ToElement() )
+ break;
+ }
+}
+
+
+TiXmlAttribute* TiXmlAttribute::Next() const
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( next->value.empty() && next->name.empty() )
+ return 0;
+ return next;
+}
+
+
+TiXmlAttribute* TiXmlAttribute::Previous() const
+{
+ // We are using knowledge of the sentinel. The sentinel
+ // have a value or name.
+ if ( prev->value.empty() && prev->name.empty() )
+ return 0;
+ return prev;
+}
+
+
+void TiXmlAttribute::Print( FILE* cfile, int /*depth*/ ) const
+{
+ TIXML_STRING n, v;
+
+ PutString( name, &n );
+ PutString( value, &v );
+
+ if (value.find ('\"') == TIXML_STRING::npos)
+ fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
+ else
+ fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
+}
+
+
+void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const
+{
+ if (value.find( '\"' ) != TIXML_STRING::npos)
+ {
+ PutString( name, stream );
+ (*stream) << "=" << "'";
+ PutString( value, stream );
+ (*stream) << "'";
+ }
+ else
+ {
+ PutString( name, stream );
+ (*stream) << "=" << "\"";
+ PutString( value, stream );
+ (*stream) << "\"";
+ }
+}
+
+int TiXmlAttribute::QueryIntValue( int* ival ) const
+{
+ if ( sscanf( value.c_str(), "%d", ival ) == 1 )
+ return TIXML_SUCCESS;
+ return TIXML_WRONG_TYPE;
+}
+
+int TiXmlAttribute::QueryDoubleValue( double* dval ) const
+{
+ if ( sscanf( value.c_str(), "%lf", dval ) == 1 )
+ return TIXML_SUCCESS;
+ return TIXML_WRONG_TYPE;
+}
+
+void TiXmlAttribute::SetIntValue( int _value )
+{
+ char buf [64];
+ sprintf (buf, "%d", _value);
+ SetValue (buf);
+}
+
+void TiXmlAttribute::SetDoubleValue( double _value )
+{
+ char buf [64];
+ sprintf (buf, "%lf", _value);
+ SetValue (buf);
+}
+
+const int TiXmlAttribute::IntValue() const
+{
+ return atoi (value.c_str ());
+}
+
+const double TiXmlAttribute::DoubleValue() const
+{
+ return atof (value.c_str ());
+}
+
+
+TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
+{
+ copy.CopyTo( this );
+}
+
+
+void TiXmlComment::operator=( const TiXmlComment& base )
+{
+ Clear();
+ base.CopyTo( this );
+}
+
+
+void TiXmlComment::Print( FILE* cfile, int depth ) const
+{
+ for ( int i=0; i<depth; i++ )
+ {
+ fputs( " ", cfile );
+ }
+ fprintf( cfile, "<!--%s-->", value.c_str() );
+}
+
+void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
+{
+ (*stream) << "<!--";
+ //PutString( value, stream );
+ (*stream) << value;
+ (*stream) << "-->";
+}
+
+
+void TiXmlComment::CopyTo( TiXmlComment* target ) const
+{
+ TiXmlNode::CopyTo( target );
+}
+
+
+TiXmlNode* TiXmlComment::Clone() const
+{
+ TiXmlComment* clone = new TiXmlComment();
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+void TiXmlText::Print( FILE* cfile, int /*depth*/ ) const
+{
+ TIXML_STRING buffer;
+ PutString( value, &buffer );
+ fprintf( cfile, "%s", buffer.c_str() );
+}
+
+
+void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
+{
+ PutString( value, stream );
+}
+
+
+void TiXmlText::CopyTo( TiXmlText* target ) const
+{
+ TiXmlNode::CopyTo( target );
+}
+
+
+TiXmlNode* TiXmlText::Clone() const
+{
+ TiXmlText* clone = 0;
+ clone = new TiXmlText( "" );
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+TiXmlDeclaration::TiXmlDeclaration( const char * _version,
+ const char * _encoding,
+ const char * _standalone )
+ : TiXmlNode( TiXmlNode::DECLARATION )
+{
+ version = _version;
+ encoding = _encoding;
+ standalone = _standalone;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
+ const std::string& _encoding,
+ const std::string& _standalone )
+ : TiXmlNode( TiXmlNode::DECLARATION )
+{
+ version = _version;
+ encoding = _encoding;
+ standalone = _standalone;
+}
+#endif
+
+
+TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
+ : TiXmlNode( TiXmlNode::DECLARATION )
+{
+ copy.CopyTo( this );
+}
+
+
+void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
+{
+ Clear();
+ copy.CopyTo( this );
+}
+
+
+void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/ ) const
+{
+ fprintf (cfile, "<?xml ");
+
+ if ( !version.empty() )
+ fprintf (cfile, "version=\"%s\" ", version.c_str ());
+ if ( !encoding.empty() )
+ fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
+ if ( !standalone.empty() )
+ fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
+ fprintf (cfile, "?>");
+}
+
+void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
+{
+ (*stream) << "<?xml ";
+
+ if ( !version.empty() )
+ {
+ (*stream) << "version=\"";
+ PutString( version, stream );
+ (*stream) << "\" ";
+ }
+ if ( !encoding.empty() )
+ {
+ (*stream) << "encoding=\"";
+ PutString( encoding, stream );
+ (*stream ) << "\" ";
+ }
+ if ( !standalone.empty() )
+ {
+ (*stream) << "standalone=\"";
+ PutString( standalone, stream );
+ (*stream) << "\" ";
+ }
+ (*stream) << "?>";
+}
+
+
+void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
+{
+ TiXmlNode::CopyTo( target );
+
+ target->version = version;
+ target->encoding = encoding;
+ target->standalone = standalone;
+}
+
+
+TiXmlNode* TiXmlDeclaration::Clone() const
+{
+ TiXmlDeclaration* clone = new TiXmlDeclaration();
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+void TiXmlUnknown::Print( FILE* cfile, int depth ) const
+{
+ for ( int i=0; i<depth; i++ )
+ fprintf( cfile, " " );
+ fprintf( cfile, "<%s>", value.c_str() );
+}
+
+
+void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
+{
+ (*stream) << "<" << value << ">"; // Don't use entities here! It is unknown.
+}
+
+
+void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
+{
+ TiXmlNode::CopyTo( target );
+}
+
+
+TiXmlNode* TiXmlUnknown::Clone() const
+{
+ TiXmlUnknown* clone = new TiXmlUnknown();
+
+ if ( !clone )
+ return 0;
+
+ CopyTo( clone );
+ return clone;
+}
+
+
+TiXmlAttributeSet::TiXmlAttributeSet()
+{
+ sentinel.next = &sentinel;
+ sentinel.prev = &sentinel;
+}
+
+
+TiXmlAttributeSet::~TiXmlAttributeSet()
+{
+ assert( sentinel.next == &sentinel );
+ assert( sentinel.prev == &sentinel );
+}
+
+
+void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
+{
+ assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
+
+ addMe->next = &sentinel;
+ addMe->prev = sentinel.prev;
+
+ sentinel.prev->next = addMe;
+ sentinel.prev = addMe;
+}
+
+void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
+{
+ TiXmlAttribute* node;
+
+ for( node = sentinel.next; node != &sentinel; node = node->next )
+ {
+ if ( node == removeMe )
+ {
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+ node->next = 0;
+ node->prev = 0;
+ return;
+ }
+ }
+ assert( 0 ); // we tried to remove a non-linked attribute.
+}
+
+TiXmlAttribute* TiXmlAttributeSet::Find( const char * name ) const
+{
+ TiXmlAttribute* node;
+
+ for( node = sentinel.next; node != &sentinel; node = node->next )
+ {
+ if ( node->name == name )
+ return node;
+ }
+ return 0;
+}
+
+
+#ifdef TIXML_USE_STL
+TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base)
+{
+ TIXML_STRING tag;
+ tag.reserve( 8 * 1000 );
+ base.StreamIn( &in, &tag );
+
+ base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
+ return in;
+}
+#endif
+
+
+TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
+{
+ base.StreamOut (& out);
+ return out;
+}
+
+
+#ifdef TIXML_USE_STL
+std::string & operator<< (std::string& out, const TiXmlNode& base )
+{
+ std::ostringstream os_stream( std::ostringstream::out );
+ base.StreamOut( &os_stream );
+
+ out.append( os_stream.str() );
+ return out;
+}
+#endif
+
+
+TiXmlHandle TiXmlHandle::FirstChild() const
+{
+ if ( node )
+ {
+ TiXmlNode* child = node->FirstChild();
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
+{
+ if ( node )
+ {
+ TiXmlNode* child = node->FirstChild( value );
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChildElement() const
+{
+ if ( node )
+ {
+ TiXmlElement* child = node->FirstChildElement();
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
+{
+ if ( node )
+ {
+ TiXmlElement* child = node->FirstChildElement( value );
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::Child( int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlNode* child = node->FirstChild();
+ for ( i=0;
+ child && i<count;
+ child = child->NextSibling(), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlNode* child = node->FirstChild( value );
+ for ( i=0;
+ child && i<count;
+ child = child->NextSibling( value ), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::ChildElement( int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlElement* child = node->FirstChildElement();
+ for ( i=0;
+ child && i<count;
+ child = child->NextSiblingElement(), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
+{
+ if ( node )
+ {
+ int i;
+ TiXmlElement* child = node->FirstChildElement( value );
+ for ( i=0;
+ child && i<count;
+ child = child->NextSiblingElement( value ), ++i )
+ {
+ // nothing
+ }
+ if ( child )
+ return TiXmlHandle( child );
+ }
+ return TiXmlHandle( 0 );
+}
diff --git a/yhttpd/src/contrib/xml/tinyxml.h b/yhttpd/src/contrib/xml/tinyxml.h
new file mode 100644
index 0000000..a9ece4b
--- /dev/null
+++ b/yhttpd/src/contrib/xml/tinyxml.h
@@ -0,0 +1,1630 @@
+#include "../../incl.h"
+
+
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+
+#ifndef TINYXML_INCLUDED
+#define TINYXML_INCLUDED
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4530 )
+#pragma warning( disable : 4786 )
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+// Help out windows:
+#if defined( _DEBUG ) && !defined( DEBUG )
+#define DEBUG
+#endif
+
+#if defined( DEBUG ) && defined( _MSC_VER )
+#include <windows.h>
+#define TIXML_LOG OutputDebugString
+#else
+#define TIXML_LOG printf
+#endif
+
+#include <string>
+#include <iostream>
+#define TIXML_STRING std::string
+#define TIXML_ISTREAM std::istream
+#define TIXML_OSTREAM std::ostream
+
+class TiXmlDocument;
+class TiXmlElement;
+class TiXmlComment;
+class TiXmlUnknown;
+class TiXmlAttribute;
+class TiXmlText;
+class TiXmlDeclaration;
+class TiXmlParsingData;
+
+const int TIXML_MAJOR_VERSION = 2;
+const int TIXML_MINOR_VERSION = 3;
+const int TIXML_PATCH_VERSION = 2;
+
+/* Internal structure for tracking location of items
+ in the XML file.
+*/
+struct TiXmlCursor
+{
+ TiXmlCursor()
+ {
+ Clear();
+ }
+ void Clear()
+ {
+ row = col = -1;
+ }
+
+ int row; // 0 based.
+ int col; // 0 based.
+};
+
+
+// Only used by Attribute::Query functions
+enum
+{
+ TIXML_SUCCESS,
+ TIXML_NO_ATTRIBUTE,
+ TIXML_WRONG_TYPE
+};
+
+
+// Used by the parsing routines.
+enum TiXmlEncoding
+{
+ TIXML_ENCODING_UNKNOWN,
+ TIXML_ENCODING_UTF8,
+ TIXML_ENCODING_LEGACY
+};
+
+const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN;
+
+/** TiXmlBase is a base class for every class in TinyXml.
+ It does little except to establish that TinyXml classes
+ can be printed and provide some utility functions.
+
+ In XML, the document and elements can contain
+ other elements and other types of nodes.
+
+ @verbatim
+ A Document can contain: Element (container or leaf)
+ Comment (leaf)
+ Unknown (leaf)
+ Declaration( leaf )
+
+ An Element can contain: Element (container or leaf)
+ Text (leaf)
+ Attributes (not on tree)
+ Comment (leaf)
+ Unknown (leaf)
+
+ A Decleration contains: Attributes (not on tree)
+ @endverbatim
+*/
+class TiXmlBase
+{
+ friend class TiXmlNode;
+ friend class TiXmlElement;
+ friend class TiXmlDocument;
+
+public:
+ TiXmlBase() : userData(0)
+ {}
+ virtual ~TiXmlBase()
+ {}
+
+ /** All TinyXml classes can print themselves to a filestream.
+ This is a formatted print, and will insert tabs and newlines.
+
+ (For an unformatted stream, use the << operator.)
+ */
+ virtual void Print( FILE* cfile, int depth ) const = 0;
+
+ /** The world does not agree on whether white space should be kept or
+ not. In order to make everyone happy, these global, static functions
+ are provided to set whether or not TinyXml will condense all white space
+ into a single space or not. The default is to condense. Note changing this
+ values is not thread safe.
+ */
+ static void SetCondenseWhiteSpace( bool condense )
+ {
+ condenseWhiteSpace = condense;
+ }
+
+ /// Return the current white space setting.
+ static bool IsWhiteSpaceCondensed()
+ {
+ return condenseWhiteSpace;
+ }
+
+ /** Return the position, in the original source file, of this node or attribute.
+ The row and column are 1-based. (That is the first row and first column is
+ 1,1). If the returns values are 0 or less, then the parser does not have
+ a row and column value.
+
+ Generally, the row and column value will be set when the TiXmlDocument::Load(),
+ TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set
+ when the DOM was created from operator>>.
+
+ The values reflect the initial load. Once the DOM is modified programmatically
+ (by adding or changing nodes and attributes) the new values will NOT update to
+ reflect changes in the document.
+
+ There is a minor performance cost to computing the row and column. Computation
+ can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value.
+
+ @sa TiXmlDocument::SetTabSize()
+ */
+ int Row() const
+ {
+ return location.row + 1;
+ }
+ int Column() const
+ {
+ return location.col + 1;
+ } ///< See Row()
+
+ void SetUserData( void* user )
+ {
+ userData = user;
+ }
+ void* GetUserData()
+ {
+ return userData;
+ }
+
+ // Table that returs, for a given lead byte, the total number of bytes
+ // in the UTF-8 sequence.
+ static const int utf8ByteTable[256];
+
+ virtual const char* Parse( const char* p,
+ TiXmlParsingData* data,
+ TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0;
+
+protected:
+
+ // See STL_STRING_BUG
+ // Utility class to overcome a bug.
+ class StringToBuffer
+ {
+ public:
+ StringToBuffer( const TIXML_STRING& str );
+ ~StringToBuffer();
+ char* buffer;
+ };
+
+ static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding );
+ inline static bool IsWhiteSpace( char c )
+ {
+ return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' );
+ }
+
+ virtual void StreamOut (TIXML_OSTREAM *) const = 0;
+
+#ifdef TIXML_USE_STL
+
+ static bool StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag );
+ static bool StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag );
+#endif
+
+ /* Reads an XML name into the string provided. Returns
+ a pointer just past the last character of the name,
+ or 0 if the function has an error.
+ */
+ static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding );
+
+ /* Reads text. Returns a pointer past the given end tag.
+ Wickedly complex options, but it keeps the (sensitive) code in one place.
+ */
+ static const char* ReadText( const char* in, // where to start
+ TIXML_STRING* text, // the string read
+ bool ignoreWhiteSpace, // whether to keep the white space
+ const char* endTag, // what ends this text
+ bool ignoreCase, // whether to ignore case in the end tag
+ TiXmlEncoding encoding ); // the current encoding
+
+ // If an entity has been found, transform it into a character.
+ static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding );
+
+ // Get a character, while interpreting entities.
+ // The length can be from 0 to 4 bytes.
+ inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding )
+ {
+ assert( p );
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ *length = utf8ByteTable[ *((unsigned char*)p) ];
+ assert( *length >= 0 && *length < 5 );
+ }
+ else
+ {
+ *length = 1;
+ }
+
+ if ( *length == 1 )
+ {
+ if ( *p == '&' )
+ return GetEntity( p, _value, length, encoding );
+ *_value = *p;
+ return p+1;
+ }
+ else if ( *length )
+ {
+ strncpy( _value, p, *length );
+ return p + (*length);
+ }
+ else
+ {
+ // Not valid text.
+ return 0;
+ }
+ }
+
+ // Puts a string to a stream, expanding entities as it goes.
+ // Note this should not contian the '<', '>', etc, or they will be transformed into entities!
+ static void PutString( const TIXML_STRING& str, TIXML_OSTREAM* out );
+
+ static void PutString( const TIXML_STRING& str, TIXML_STRING* out );
+
+ // Return true if the next characters in the stream are any of the endTag sequences.
+ // Ignore case only works for english, and should only be relied on when comparing
+ // to Engilish words: StringEqual( p, "version", true ) is fine.
+ static bool StringEqual( const char* p,
+ const char* endTag,
+ bool ignoreCase,
+ TiXmlEncoding encoding );
+
+
+ enum
+ {
+ TIXML_NO_ERROR = 0,
+ TIXML_ERROR,
+ TIXML_ERROR_OPENING_FILE,
+ TIXML_ERROR_OUT_OF_MEMORY,
+ TIXML_ERROR_PARSING_ELEMENT,
+ TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
+ TIXML_ERROR_READING_ELEMENT_VALUE,
+ TIXML_ERROR_READING_ATTRIBUTES,
+ TIXML_ERROR_PARSING_EMPTY,
+ TIXML_ERROR_READING_END_TAG,
+ TIXML_ERROR_PARSING_UNKNOWN,
+ TIXML_ERROR_PARSING_COMMENT,
+ TIXML_ERROR_PARSING_DECLARATION,
+ TIXML_ERROR_DOCUMENT_EMPTY,
+ TIXML_ERROR_EMBEDDED_NULL,
+
+ TIXML_ERROR_STRING_COUNT
+ };
+ static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
+
+ TiXmlCursor location;
+
+ /// Field containing a generic user pointer
+ void* userData;
+
+ // None of these methods are reliable for any language except English.
+ // Good for approximation, not great for accuracy.
+ static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding );
+ static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding );
+ inline static int ToLower( int v, TiXmlEncoding encoding )
+ {
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ if ( v < 128 )
+ return tolower( v );
+ return v;
+ }
+ else
+ {
+ return tolower( v );
+ }
+ }
+ static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
+
+private:
+ TiXmlBase( const TiXmlBase& ); // not implemented.
+ void operator=( const TiXmlBase& base ); // not allowed.
+
+ struct Entity
+ {
+ const char* str;
+ unsigned int strLength;
+ char chr;
+ };
+ enum
+ {
+ NUM_ENTITY = 5,
+ MAX_ENTITY_LENGTH = 6
+
+ };
+ static Entity entity[ NUM_ENTITY ];
+ static bool condenseWhiteSpace;
+};
+
+
+/** The parent class for everything in the Document Object Model.
+ (Except for attributes).
+ Nodes have siblings, a parent, and children. A node can be
+ in a document, or stand on its own. The type of a TiXmlNode
+ can be queried, and it can be cast to its more defined type.
+*/
+class TiXmlNode : public TiXmlBase
+{
+ friend class TiXmlDocument;
+ friend class TiXmlElement;
+
+public:
+#ifdef TIXML_USE_STL
+
+ /** An input stream operator, for every class. Tolerant of newlines and
+ formatting, but doesn't expect them.
+ */
+ friend std::istream& operator >> (std::istream& in, TiXmlNode& base);
+
+ /** An output stream operator, for every class. Note that this outputs
+ without any newlines or formatting, as opposed to Print(), which
+ includes tabs and new lines.
+
+ The operator<< and operator>> are not completely symmetric. Writing
+ a node to a stream is very well defined. You'll get a nice stream
+ of output, without any extra whitespace or newlines.
+
+ But reading is not as well defined. (As it always is.) If you create
+ a TiXmlElement (for example) and read that from an input stream,
+ the text needs to define an element or junk will result. This is
+ true of all input streams, but it's worth keeping in mind.
+
+ A TiXmlDocument will read nodes until it reads a root element, and
+ all the children of that root element.
+ */
+ friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base);
+
+ /// Appends the XML node or attribute to a std::string.
+ friend std::string& operator<< (std::string& out, const TiXmlNode& base );
+
+#else
+ // Used internally, not part of the public API.
+ friend TIXML_OSTREAM& operator<< (TIXML_OSTREAM& out, const TiXmlNode& base);
+#endif
+
+ /** The types of XML nodes supported by TinyXml. (All the
+ unsupported types are picked up by UNKNOWN.)
+ */
+ enum NodeType
+ {
+ DOCUMENT,
+ ELEMENT,
+ COMMENT,
+ UNKNOWN,
+ TEXT,
+ DECLARATION,
+ TYPECOUNT
+ };
+
+ virtual ~TiXmlNode();
+
+ /** The meaning of 'value' changes for the specific type of
+ TiXmlNode.
+ @verbatim
+ Document: filename of the xml file
+ Element: name of the element
+ Comment: the comment text
+ Unknown: the tag contents
+ Text: the text string
+ @endverbatim
+
+ The subclasses will wrap this function.
+ */
+ const char * Value() const
+ {
+ return value.c_str ();
+ }
+
+ /** Changes the value of the node. Defined as:
+ @verbatim
+ Document: filename of the xml file
+ Element: name of the element
+ Comment: the comment text
+ Unknown: the tag contents
+ Text: the text string
+ @endverbatim
+ */
+ void SetValue(const char * _value)
+ {
+ value = _value;
+ }
+
+#ifdef TIXML_USE_STL
+ /// STL std::string form.
+ void SetValue( const std::string& _value )
+ {
+ StringToBuffer buf( _value );
+ SetValue( buf.buffer ? buf.buffer : "" );
+ }
+#endif
+
+ /// Delete all the children of this node. Does not affect 'this'.
+ void Clear();
+
+ /// One step up the DOM.
+ TiXmlNode* Parent() const
+ {
+ return parent;
+ }
+
+ TiXmlNode* FirstChild() const
+ {
+ return firstChild;
+ } ///< The first child of this node. Will be null if there are no children.
+ TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found.
+
+ TiXmlNode* LastChild() const
+ {
+ return lastChild;
+ } /// The last child of this node. Will be null if there are no children.
+ TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children.
+
+#ifdef TIXML_USE_STL
+
+ TiXmlNode* FirstChild( const std::string& _value ) const
+ {
+ return FirstChild (_value.c_str ());
+ } ///< STL std::string form.
+ TiXmlNode* LastChild( const std::string& _value ) const
+ {
+ return LastChild (_value.c_str ());
+ } ///< STL std::string form.
+#endif
+
+ /** An alternate way to walk the children of a node.
+ One way to iterate over nodes is:
+ @verbatim
+ for( child = parent->FirstChild(); child; child = child->NextSibling() )
+ @endverbatim
+
+ IterateChildren does the same thing with the syntax:
+ @verbatim
+ child = 0;
+ while( child = parent->IterateChildren( child ) )
+ @endverbatim
+
+ IterateChildren takes the previous child as input and finds
+ the next one. If the previous child is null, it returns the
+ first. IterateChildren will return null when done.
+ */
+ TiXmlNode* IterateChildren( TiXmlNode* previous ) const;
+
+ /// This flavor of IterateChildren searches for children with a particular 'value'
+ TiXmlNode* IterateChildren( const char * value, TiXmlNode* previous ) const;
+
+#ifdef TIXML_USE_STL
+
+ TiXmlNode* IterateChildren( const std::string& _value, TiXmlNode* previous ) const
+ {
+ return IterateChildren (_value.c_str (), previous);
+ } ///< STL std::string form.
+#endif
+
+ /** Add a new node related to this. Adds a child past the LastChild.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
+
+
+ /** Add a new node related to this. Adds a child past the LastChild.
+
+ NOTE: the node to be added is passed by pointer, and will be
+ henceforth owned (and deleted) by tinyXml. This method is efficient
+ and avoids an extra copy, but should be used with care as it
+ uses a different memory model than the other insert functions.
+
+ @sa InsertEndChild
+ */
+ TiXmlNode* LinkEndChild( TiXmlNode* addThis );
+
+ /** Add a new node related to this. Adds a child before the specified child.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
+
+ /** Add a new node related to this. Adds a child after the specified child.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis );
+
+ /** Replace a child of this node.
+ Returns a pointer to the new object or NULL if an error occured.
+ */
+ TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
+
+ /// Delete a child of this node.
+ bool RemoveChild( TiXmlNode* removeThis );
+
+ /// Navigate to a sibling node.
+ TiXmlNode* PreviousSibling() const
+ {
+ return prev;
+ }
+
+ /// Navigate to a sibling node.
+ TiXmlNode* PreviousSibling( const char * ) const;
+
+#ifdef TIXML_USE_STL
+
+ TiXmlNode* PreviousSibling( const std::string& _value ) const
+ {
+ return PreviousSibling (_value.c_str ());
+ } ///< STL std::string form.
+ TiXmlNode* NextSibling( const std::string& _value) const
+ {
+ return NextSibling (_value.c_str ());
+ } ///< STL std::string form.
+#endif
+
+ /// Navigate to a sibling node.
+ TiXmlNode* NextSibling() const
+ {
+ return next;
+ }
+
+ /// Navigate to a sibling node with the given 'value'.
+ TiXmlNode* NextSibling( const char * ) const;
+
+ /** Convenience function to get through elements.
+ Calls NextSibling and ToElement. Will skip all non-Element
+ nodes. Returns 0 if there is not another element.
+ */
+ TiXmlElement* NextSiblingElement() const;
+
+ /** Convenience function to get through elements.
+ Calls NextSibling and ToElement. Will skip all non-Element
+ nodes. Returns 0 if there is not another element.
+ */
+ TiXmlElement* NextSiblingElement( const char * ) const;
+
+#ifdef TIXML_USE_STL
+
+ TiXmlElement* NextSiblingElement( const std::string& _value) const
+ {
+ return NextSiblingElement (_value.c_str ());
+ } ///< STL std::string form.
+#endif
+
+ /// Convenience function to get through elements.
+ TiXmlElement* FirstChildElement() const;
+
+ /// Convenience function to get through elements.
+ TiXmlElement* FirstChildElement( const char * value ) const;
+
+#ifdef TIXML_USE_STL
+
+ TiXmlElement* FirstChildElement( const std::string& _value ) const
+ {
+ return FirstChildElement (_value.c_str ());
+ } ///< STL std::string form.
+#endif
+
+ /** Query the type (as an enumerated value, above) of this node.
+ The possible types are: DOCUMENT, ELEMENT, COMMENT,
+ UNKNOWN, TEXT, and DECLARATION.
+ */
+ virtual int Type() const
+ {
+ return type;
+ }
+
+ /** Return a pointer to the Document this node lives in.
+ Returns null if not in a document.
+ */
+ TiXmlDocument* GetDocument() const;
+
+ /// Returns true if this node has no children.
+ bool NoChildren() const
+ {
+ return !firstChild;
+ }
+
+ TiXmlDocument* ToDocument() const
+ {
+ return ( this && type == DOCUMENT ) ? (TiXmlDocument*) this : 0;
+ } ///< Cast to a more defined type. Will return null not of the requested type.
+ TiXmlElement* ToElement() const
+ {
+ return ( this && type == ELEMENT ) ? (TiXmlElement*) this : 0;
+ } ///< Cast to a more defined type. Will return null not of the requested type.
+ TiXmlComment* ToComment() const
+ {
+ return ( this && type == COMMENT ) ? (TiXmlComment*) this : 0;
+ } ///< Cast to a more defined type. Will return null not of the requested type.
+ TiXmlUnknown* ToUnknown() const
+ {
+ return ( this && type == UNKNOWN ) ? (TiXmlUnknown*) this : 0;
+ } ///< Cast to a more defined type. Will return null not of the requested type.
+ TiXmlText* ToText() const
+ {
+ return ( this && type == TEXT ) ? (TiXmlText*) this : 0;
+ } ///< Cast to a more defined type. Will return null not of the requested type.
+ TiXmlDeclaration* ToDeclaration() const
+ {
+ return ( this && type == DECLARATION ) ? (TiXmlDeclaration*) this : 0;
+ } ///< Cast to a more defined type. Will return null not of the requested type.
+
+ /** Create an exact duplicate of this node and return it. The memory must be deleted
+ by the caller.
+ */
+ virtual TiXmlNode* Clone() const = 0;
+
+protected:
+ TiXmlNode( NodeType _type );
+
+ // Copy to the allocated object. Shared functionality between Clone, Copy constructor,
+ // and the assignment operator.
+ void CopyTo( TiXmlNode* target ) const;
+
+#ifdef TIXML_USE_STL
+ // The real work of the input operator.
+ virtual void StreamIn( TIXML_ISTREAM* in, TIXML_STRING* tag ) = 0;
+#endif
+
+ // Figure out what is at *p, and parse it. Returns null if it is not an xml node.
+ TiXmlNode* Identify( const char* start, TiXmlEncoding encoding );
+
+ // Internal Value function returning a TIXML_STRING
+ const TIXML_STRING& SValue() const
+ {
+ return value ;
+ }
+
+ TiXmlNode* parent;
+ NodeType type;
+
+ TiXmlNode* firstChild;
+ TiXmlNode* lastChild;
+
+ TIXML_STRING value;
+
+ TiXmlNode* prev;
+ TiXmlNode* next;
+
+private:
+ TiXmlNode( const TiXmlNode& ); // not implemented.
+ void operator=( const TiXmlNode& base ); // not allowed.
+};
+
+
+/** An attribute is a name-value pair. Elements have an arbitrary
+ number of attributes, each with a unique name.
+
+ @note The attributes are not TiXmlNodes, since they are not
+ part of the tinyXML document object model. There are other
+ suggested ways to look at this problem.
+*/
+class TiXmlAttribute : public TiXmlBase
+{
+ friend class TiXmlAttributeSet;
+
+public:
+ /// Construct an empty attribute.
+ TiXmlAttribute() : TiXmlBase()
+ {
+ document = 0;
+ prev = next = 0;
+ }
+
+#ifdef TIXML_USE_STL
+ /// std::string constructor.
+ TiXmlAttribute( const std::string& _name, const std::string& _value )
+ {
+ name = _name;
+ value = _value;
+ document = 0;
+ prev = next = 0;
+ }
+#endif
+
+ /// Construct an attribute with a name and value.
+ TiXmlAttribute( const char * _name, const char * _value )
+ {
+ name = _name;
+ value = _value;
+ document = 0;
+ prev = next = 0;
+ }
+
+ const char* Name() const
+ {
+ return name.c_str ();
+ } ///< Return the name of this attribute.
+ const char* Value() const
+ {
+ return value.c_str ();
+ } ///< Return the value of this attribute.
+ const int IntValue() const; ///< Return the value of this attribute, converted to an integer.
+ const double DoubleValue() const; ///< Return the value of this attribute, converted to a double.
+
+ /** QueryIntValue examines the value string. It is an alternative to the
+ IntValue() method with richer error checking.
+ If the value is an integer, it is stored in 'value' and
+ the call returns TIXML_SUCCESS. If it is not
+ an integer, it returns TIXML_WRONG_TYPE.
+
+ A specialized but useful call. Note that for success it returns 0,
+ which is the opposite of almost all other TinyXml calls.
+ */
+ int QueryIntValue( int* value ) const;
+ /// QueryDoubleValue examines the value string. See QueryIntValue().
+ int QueryDoubleValue( double* value ) const;
+
+ void SetName( const char* _name )
+ {
+ name = _name;
+ } ///< Set the name of this attribute.
+ void SetValue( const char* _value )
+ {
+ value = _value;
+ } ///< Set the value.
+
+ void SetIntValue( int value ); ///< Set the value from an integer.
+ void SetDoubleValue( double value ); ///< Set the value from a double.
+
+#ifdef TIXML_USE_STL
+ /// STL std::string form.
+ void SetName( const std::string& _name )
+ {
+ StringToBuffer buf( _name );
+ SetName ( buf.buffer ? buf.buffer : "error" );
+ }
+ /// STL std::string form.
+ void SetValue( const std::string& _value )
+ {
+ StringToBuffer buf( _value );
+ SetValue( buf.buffer ? buf.buffer : "error" );
+ }
+#endif
+
+ /// Get the next sibling attribute in the DOM. Returns null at end.
+ TiXmlAttribute* Next() const;
+ /// Get the previous sibling attribute in the DOM. Returns null at beginning.
+ TiXmlAttribute* Previous() const;
+
+ bool operator==( const TiXmlAttribute& rhs ) const
+ {
+ return rhs.name == name;
+ }
+ bool operator<( const TiXmlAttribute& rhs ) const
+ {
+ return name < rhs.name;
+ }
+ bool operator>( const TiXmlAttribute& rhs ) const
+ {
+ return name > rhs.name;
+ }
+
+ /* Attribute parsing starts: first letter of the name
+ returns: the next char after the value end quote
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+ // Prints this Attribute to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ virtual void StreamOut( TIXML_OSTREAM * out ) const;
+ // [internal use]
+ // Set the document pointer so the attribute can report errors.
+ void SetDocument( TiXmlDocument* doc )
+ {
+ document = doc;
+ }
+
+private:
+ TiXmlAttribute( const TiXmlAttribute& ); // not implemented.
+ void operator=( const TiXmlAttribute& base ); // not allowed.
+
+ TiXmlDocument* document; // A pointer back to a document, for error reporting.
+ TIXML_STRING name;
+ TIXML_STRING value;
+ TiXmlAttribute* prev;
+ TiXmlAttribute* next;
+};
+
+
+/* A class used to manage a group of attributes.
+ It is only used internally, both by the ELEMENT and the DECLARATION.
+
+ The set can be changed transparent to the Element and Declaration
+ classes that use it, but NOT transparent to the Attribute
+ which has to implement a next() and previous() method. Which makes
+ it a bit problematic and prevents the use of STL.
+
+ This version is implemented with circular lists because:
+ - I like circular lists
+ - it demonstrates some independence from the (typical) doubly linked list.
+*/
+class TiXmlAttributeSet
+{
+public:
+ TiXmlAttributeSet();
+ ~TiXmlAttributeSet();
+
+ void Add( TiXmlAttribute* attribute );
+ void Remove( TiXmlAttribute* attribute );
+
+ TiXmlAttribute* First() const
+ {
+ return ( sentinel.next == &sentinel ) ? 0 : sentinel.next;
+ }
+ TiXmlAttribute* Last() const
+ {
+ return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev;
+ }
+ TiXmlAttribute* Find( const char * name ) const;
+
+private:
+ TiXmlAttribute sentinel;
+};
+
+
+/** The element is a container class. It has a value, the element name,
+ and can contain other elements, text, comments, and unknowns.
+ Elements also contain an arbitrary number of attributes.
+*/
+class TiXmlElement : public TiXmlNode
+{
+public:
+ /// Construct an element.
+ TiXmlElement (const char * in_value);
+
+#ifdef TIXML_USE_STL
+ /// std::string constructor.
+ TiXmlElement( const std::string& _value );
+#endif
+
+ TiXmlElement( const TiXmlElement& );
+
+ void operator=( const TiXmlElement& base );
+
+ virtual ~TiXmlElement();
+
+ /** Given an attribute name, Attribute() returns the value
+ for the attribute of that name, or null if none exists.
+ */
+ const char* Attribute( const char* name ) const;
+
+ /** Given an attribute name, Attribute() returns the value
+ for the attribute of that name, or null if none exists.
+ If the attribute exists and can be converted to an integer,
+ the integer value will be put in the return 'i', if 'i'
+ is non-null.
+ */
+ const char* Attribute( const char* name, int* i ) const;
+
+ /** Given an attribute name, Attribute() returns the value
+ for the attribute of that name, or null if none exists.
+ If the attribute exists and can be converted to an double,
+ the double value will be put in the return 'd', if 'd'
+ is non-null.
+ */
+ const char* Attribute( const char* name, double* d ) const;
+
+ /** QueryIntAttribute examines the attribute - it is an alternative to the
+ Attribute() method with richer error checking.
+ If the attribute is an integer, it is stored in 'value' and
+ the call returns TIXML_SUCCESS. If it is not
+ an integer, it returns TIXML_WRONG_TYPE. If the attribute
+ does not exist, then TIXML_NO_ATTRIBUTE is returned.
+ */
+ int QueryIntAttribute( const char* name, int* value ) const;
+ /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
+ int QueryDoubleAttribute( const char* name, double* value ) const;
+
+ /** Sets an attribute of name to a given value. The attribute
+ will be created if it does not exist, or changed if it does.
+ */
+ void SetAttribute( const char* name, const char * value );
+
+#ifdef TIXML_USE_STL
+
+ const char* Attribute( const std::string& name ) const
+ {
+ return Attribute( name.c_str() );
+ }
+ const char* Attribute( const std::string& name, int* i ) const
+ {
+ return Attribute( name.c_str(), i );
+ }
+ const char* Attribute( const std::string& name, double* d ) const
+ {
+ return Attribute( name.c_str(), d );
+ }
+ int QueryIntAttribute( const std::string& name, int* value ) const
+ {
+ return QueryIntAttribute( name.c_str(), value );
+ }
+ int QueryDoubleAttribute( const std::string& name, double* value ) const
+ {
+ return QueryDoubleAttribute( name.c_str(), value );
+ }
+
+ /// STL std::string form.
+ void SetAttribute( const std::string& name, const std::string& _value )
+ {
+ StringToBuffer n( name );
+ StringToBuffer v( _value );
+ if ( n.buffer && v.buffer )
+ SetAttribute (n.buffer, v.buffer );
+ }
+ ///< STL std::string form.
+ void SetAttribute( const std::string& name, int _value )
+ {
+ StringToBuffer n( name );
+ if ( n.buffer )
+ SetAttribute (n.buffer, _value);
+ }
+#endif
+
+ /** Sets an attribute of name to a given value. The attribute
+ will be created if it does not exist, or changed if it does.
+ */
+ void SetAttribute( const char * name, int value );
+
+ /** Sets an attribute of name to a given value. The attribute
+ will be created if it does not exist, or changed if it does.
+ */
+ void SetDoubleAttribute( const char * name, double value );
+
+ /** Deletes an attribute with the given name.
+ */
+ void RemoveAttribute( const char * name );
+#ifdef TIXML_USE_STL
+
+ void RemoveAttribute( const std::string& name )
+ {
+ RemoveAttribute (name.c_str ());
+ } ///< STL std::string form.
+#endif
+
+ TiXmlAttribute* FirstAttribute() const
+ {
+ return attributeSet.First();
+ } ///< Access the first attribute in this element.
+ TiXmlAttribute* LastAttribute() const
+ {
+ return attributeSet.Last();
+ } ///< Access the last attribute in this element.
+
+ /// Creates a new Element and returns it - the returned element is a copy.
+ virtual TiXmlNode* Clone() const;
+ // Print the Element to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ /* Attribtue parsing starts: next char past '<'
+ returns: next char past '>'
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+protected:
+
+ void CopyTo( TiXmlElement* target ) const;
+ void ClearThis(); // like clear, but initializes 'this' object as well
+
+ // Used to be public [internal use]
+#ifdef TIXML_USE_STL
+
+ virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+#endif
+
+ virtual void StreamOut( TIXML_OSTREAM * out ) const;
+
+ /* [internal use]
+ Reads the "value" of the element -- another element, or text.
+ This should terminate with the current end tag.
+ */
+ const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding );
+
+private:
+
+ TiXmlAttributeSet attributeSet;
+};
+
+
+/** An XML comment.
+*/
+class TiXmlComment : public TiXmlNode
+{
+public:
+ /// Constructs an empty comment.
+ TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT )
+ {}
+ TiXmlComment( const TiXmlComment& );
+ void operator=( const TiXmlComment& base );
+
+ virtual ~TiXmlComment()
+ {}
+
+ /// Returns a copy of this Comment.
+ virtual TiXmlNode* Clone() const;
+ /// Write this Comment to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ /* Attribtue parsing starts: at the ! of the !--
+ returns: next char past '>'
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+protected:
+ void CopyTo( TiXmlComment* target ) const;
+
+ // used to be public
+#ifdef TIXML_USE_STL
+
+ virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+#endif
+
+ virtual void StreamOut( TIXML_OSTREAM * out ) const;
+
+private:
+
+};
+
+
+/** XML text. Contained in an element.
+*/
+class TiXmlText : public TiXmlNode
+{
+ friend class TiXmlElement;
+public:
+ /// Constructor.
+ TiXmlText (const char * initValue) : TiXmlNode (TiXmlNode::TEXT)
+ {
+ SetValue( initValue );
+ }
+ virtual ~TiXmlText()
+ {}
+
+#ifdef TIXML_USE_STL
+ /// Constructor.
+ TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
+ {
+ SetValue( initValue );
+ }
+#endif
+
+ TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT )
+ {
+ copy.CopyTo( this );
+ }
+ void operator=( const TiXmlText& base )
+ {
+ base.CopyTo( this );
+ }
+
+ /// Write this text object to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+protected :
+ /// [internal use] Creates a new Element and returns it.
+ virtual TiXmlNode* Clone() const;
+ void CopyTo( TiXmlText* target ) const;
+
+ virtual void StreamOut ( TIXML_OSTREAM * out ) const;
+ bool Blank() const; // returns true if all white space and new lines
+ // [internal use]
+#ifdef TIXML_USE_STL
+
+ virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+#endif
+
+private:
+};
+
+
+/** In correct XML the declaration is the first entry in the file.
+ @verbatim
+ <?xml version="1.0" standalone="yes"?>
+ @endverbatim
+
+ TinyXml will happily read or write files without a declaration,
+ however. There are 3 possible attributes to the declaration:
+ version, encoding, and standalone.
+
+ Note: In this version of the code, the attributes are
+ handled as special cases, not generic attributes, simply
+ because there can only be at most 3 and they are always the same.
+*/
+class TiXmlDeclaration : public TiXmlNode
+{
+public:
+ /// Construct an empty declaration.
+ TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION )
+ {}
+
+#ifdef TIXML_USE_STL
+ /// Constructor.
+ TiXmlDeclaration( const std::string& _version,
+ const std::string& _encoding,
+ const std::string& _standalone );
+#endif
+
+ /// Construct.
+ TiXmlDeclaration( const char* _version,
+ const char* _encoding,
+ const char* _standalone );
+
+ TiXmlDeclaration( const TiXmlDeclaration& copy );
+ void operator=( const TiXmlDeclaration& copy );
+
+ virtual ~TiXmlDeclaration()
+ {}
+
+ /// Version. Will return an empty string if none was found.
+ const char *Version() const
+ {
+ return version.c_str ();
+ }
+ /// Encoding. Will return an empty string if none was found.
+ const char *Encoding() const
+ {
+ return encoding.c_str ();
+ }
+ /// Is this a standalone document?
+ const char *Standalone() const
+ {
+ return standalone.c_str ();
+ }
+
+ /// Creates a copy of this Declaration and returns it.
+ virtual TiXmlNode* Clone() const;
+ /// Print this declaration to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+protected:
+ void CopyTo( TiXmlDeclaration* target ) const;
+ // used to be public
+#ifdef TIXML_USE_STL
+
+ virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+#endif
+
+ virtual void StreamOut ( TIXML_OSTREAM * out) const;
+
+private:
+
+ TIXML_STRING version;
+ TIXML_STRING encoding;
+ TIXML_STRING standalone;
+};
+
+
+/** Any tag that tinyXml doesn't recognize is saved as an
+ unknown. It is a tag of text, but should not be modified.
+ It will be written back to the XML, unchanged, when the file
+ is saved.
+
+ DTD tags get thrown into TiXmlUnknowns.
+*/
+class TiXmlUnknown : public TiXmlNode
+{
+public:
+ TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN )
+ {}
+ virtual ~TiXmlUnknown()
+ {}
+
+ TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN )
+ {
+ copy.CopyTo( this );
+ }
+ void operator=( const TiXmlUnknown& copy )
+ {
+ copy.CopyTo( this );
+ }
+
+ /// Creates a copy of this Unknown and returns it.
+ virtual TiXmlNode* Clone() const;
+ /// Print this Unknown to a FILE stream.
+ virtual void Print( FILE* cfile, int depth ) const;
+
+ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+protected:
+ void CopyTo( TiXmlUnknown* target ) const;
+
+#ifdef TIXML_USE_STL
+
+ virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+#endif
+
+ virtual void StreamOut ( TIXML_OSTREAM * out ) const;
+
+private:
+
+};
+
+
+/** Always the top level node. A document binds together all the
+ XML pieces. It can be saved, loaded, and printed to the screen.
+ The 'value' of a document node is the xml file name.
+*/
+class TiXmlDocument : public TiXmlNode
+{
+public:
+ /// Create an empty document, that has no name.
+ TiXmlDocument();
+ /// Create a document with a name. The name of the document is also the filename of the xml.
+ TiXmlDocument( const char * documentName );
+
+#ifdef TIXML_USE_STL
+ /// Constructor.
+ TiXmlDocument( const std::string& documentName );
+#endif
+
+ TiXmlDocument( const TiXmlDocument& copy );
+ void operator=( const TiXmlDocument& copy );
+
+ virtual ~TiXmlDocument()
+ {}
+
+ /** Load a file using the current document value.
+ Returns true if successful. Will delete any existing
+ document data before loading.
+ */
+ bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+ /// Save a file using the current document value. Returns true if successful.
+ bool SaveFile() const;
+ /// Load a file using the given filename. Returns true if successful.
+ bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+ /// Save a file using the given filename. Returns true if successful.
+ bool SaveFile( const char * filename ) const;
+
+#ifdef TIXML_USE_STL
+
+ bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version.
+ {
+ StringToBuffer f( filename );
+ return ( f.buffer && LoadFile( f.buffer, encoding ));
+ }
+ bool SaveFile( const std::string& filename ) const ///< STL std::string version.
+ {
+ StringToBuffer f( filename );
+ return ( f.buffer && SaveFile( f.buffer ));
+ }
+#endif
+
+ /** Parse the given null terminated block of xml data. Passing in an encoding to this
+ method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml
+ to use that encoding, regardless of what TinyXml might otherwise try to detect.
+ */
+ virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+
+ /** Get the root element -- the only top level element -- of the document.
+ In well formed XML, there should only be one. TinyXml is tolerant of
+ multiple elements at the document level.
+ */
+ TiXmlElement* RootElement() const
+ {
+ return FirstChildElement();
+ }
+
+ /** If an error occurs, Error will be set to true. Also,
+ - The ErrorId() will contain the integer identifier of the error (not generally useful)
+ - The ErrorDesc() method will return the name of the error. (very useful)
+ - The ErrorRow() and ErrorCol() will return the location of the error (if known)
+ */
+ bool Error() const
+ {
+ return error;
+ }
+
+ /// Contains a textual (english) description of the error if one occurs.
+ const char * ErrorDesc() const
+ {
+ return errorDesc.c_str ();
+ }
+
+ /** Generally, you probably want the error string ( ErrorDesc() ). But if you
+ prefer the ErrorId, this function will fetch it.
+ */
+ const int ErrorId() const
+ {
+ return errorId;
+ }
+
+ /** Returns the location (if known) of the error. The first column is column 1,
+ and the first row is row 1. A value of 0 means the row and column wasn't applicable
+ (memory errors, for example, have no row/column) or the parser lost the error. (An
+ error in the error reporting, in that case.)
+
+ @sa SetTabSize, Row, Column
+ */
+ int ErrorRow()
+ {
+ return errorLocation.row+1;
+ }
+ int ErrorCol()
+ {
+ return errorLocation.col+1;
+ } ///< The column where the error occured. See ErrorRow()
+
+ /** By calling this method, with a tab size
+ greater than 0, the row and column of each node and attribute is stored
+ when the file is loaded. Very useful for tracking the DOM back in to
+ the source file.
+
+ The tab size is required for calculating the location of nodes. If not
+ set, the default of 4 is used. The tabsize is set per document. Setting
+ the tabsize to 0 disables row/column tracking.
+
+ Note that row and column tracking is not supported when using operator>>.
+
+ The tab size needs to be enabled before the parse or load. Correct usage:
+ @verbatim
+ TiXmlDocument doc;
+ doc.SetTabSize( 8 );
+ doc.Load( "myfile.xml" );
+ @endverbatim
+
+ @sa Row, Column
+ */
+ void SetTabSize( int _tabsize )
+ {
+ tabsize = _tabsize;
+ }
+
+ int TabSize() const
+ {
+ return tabsize;
+ }
+
+ /** If you have handled the error, it can be reset with this call. The error
+ state is automatically cleared if you Parse a new XML block.
+ */
+ void ClearError()
+ {
+ error = false;
+ errorId = 0;
+ errorDesc = "";
+ errorLocation.row = errorLocation.col = 0;
+ //errorLocation.last = 0;
+ }
+
+ /** Dump the document to standard out. */
+ void Print() const
+ {
+ Print( stdout, 0 );
+ }
+
+ /// Print this Document to a FILE stream.
+ virtual void Print( FILE* cfile, int depth = 0 ) const;
+ // [internal use]
+ void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding );
+
+protected :
+ virtual void StreamOut ( TIXML_OSTREAM * out) const;
+ // [internal use]
+ virtual TiXmlNode* Clone() const;
+#ifdef TIXML_USE_STL
+
+ virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
+#endif
+
+private:
+ void CopyTo( TiXmlDocument* target ) const;
+
+ bool error;
+ int errorId;
+ TIXML_STRING errorDesc;
+ int tabsize;
+ TiXmlCursor errorLocation;
+};
+
+
+/**
+ A TiXmlHandle is a class that wraps a node pointer with null checks; this is
+ an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml
+ DOM structure. It is a separate utility class.
+
+ Take an example:
+ @verbatim
+ <Document>
+ <Element attributeA = "valueA">
+ <Child attributeB = "value1" />
+ <Child attributeB = "value2" />
+ </Element>
+ <Document>
+ @endverbatim
+
+ Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
+ easy to write a *lot* of code that looks like:
+
+ @verbatim
+ TiXmlElement* root = document.FirstChildElement( "Document" );
+ if ( root )
+ {
+ TiXmlElement* element = root->FirstChildElement( "Element" );
+ if ( element )
+ {
+ TiXmlElement* child = element->FirstChildElement( "Child" );
+ if ( child )
+ {
+ TiXmlElement* child2 = child->NextSiblingElement( "Child" );
+ if ( child2 )
+ {
+ // Finally do something useful.
+ @endverbatim
+
+ And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity
+ of such code. A TiXmlHandle checks for null pointers so it is perfectly safe
+ and correct to use:
+
+ @verbatim
+ TiXmlHandle docHandle( &document );
+ TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).Element();
+ if ( child2 )
+ {
+ // do something useful
+ @endverbatim
+
+ Which is MUCH more concise and useful.
+
+ It is also safe to copy handles - internally they are nothing more than node pointers.
+ @verbatim
+ TiXmlHandle handleCopy = handle;
+ @endverbatim
+
+ What they should not be used for is iteration:
+
+ @verbatim
+ int i=0;
+ while ( true )
+ {
+ TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).Element();
+ if ( !child )
+ break;
+ // do something
+ ++i;
+ }
+ @endverbatim
+
+ It seems reasonable, but it is in fact two embedded while loops. The Child method is
+ a linear walk to find the element, so this code would iterate much more than it needs
+ to. Instead, prefer:
+
+ @verbatim
+ TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).Element();
+
+ for( child; child; child=child->NextSiblingElement() )
+ {
+ // do something
+ }
+ @endverbatim
+*/
+class TiXmlHandle
+{
+public:
+ /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
+ TiXmlHandle( TiXmlNode* node )
+ {
+ this->node = node;
+ }
+ /// Copy constructor
+ TiXmlHandle( const TiXmlHandle& ref )
+ {
+ this->node = ref.node;
+ }
+ TiXmlHandle operator=( const TiXmlHandle& ref )
+ {
+ this->node = ref.node;
+ return *this;
+ }
+
+ /// Return a handle to the first child node.
+ TiXmlHandle FirstChild() const;
+ /// Return a handle to the first child node with the given name.
+ TiXmlHandle FirstChild( const char * value ) const;
+ /// Return a handle to the first child element.
+ TiXmlHandle FirstChildElement() const;
+ /// Return a handle to the first child element with the given name.
+ TiXmlHandle FirstChildElement( const char * value ) const;
+
+ /** Return a handle to the "index" child with the given name.
+ The first child is 0, the second 1, etc.
+ */
+ TiXmlHandle Child( const char* value, int index ) const;
+ /** Return a handle to the "index" child.
+ The first child is 0, the second 1, etc.
+ */
+ TiXmlHandle Child( int index ) const;
+ /** Return a handle to the "index" child element with the given name.
+ The first child element is 0, the second 1, etc. Note that only TiXmlElements
+ are indexed: other types are not counted.
+ */
+ TiXmlHandle ChildElement( const char* value, int index ) const;
+ /** Return a handle to the "index" child element.
+ The first child element is 0, the second 1, etc. Note that only TiXmlElements
+ are indexed: other types are not counted.
+ */
+ TiXmlHandle ChildElement( int index ) const;
+
+#ifdef TIXML_USE_STL
+
+ TiXmlHandle FirstChild( const std::string& _value ) const
+ {
+ return FirstChild( _value.c_str() );
+ }
+ TiXmlHandle FirstChildElement( const std::string& _value ) const
+ {
+ return FirstChildElement( _value.c_str() );
+ }
+
+ TiXmlHandle Child( const std::string& _value, int index ) const
+ {
+ return Child( _value.c_str(), index );
+ }
+ TiXmlHandle ChildElement( const std::string& _value, int index ) const
+ {
+ return ChildElement( _value.c_str(), index );
+ }
+#endif
+
+ /// Return the handle as a TiXmlNode. This may return null.
+ TiXmlNode* Node() const
+ {
+ return node;
+ }
+ /// Return the handle as a TiXmlElement. This may return null.
+ TiXmlElement* Element() const
+ {
+ return ( ( node && node->ToElement() ) ? node->ToElement() : 0 );
+ }
+ /// Return the handle as a TiXmlText. This may return null.
+ TiXmlText* Text() const
+ {
+ return ( ( node && node->ToText() ) ? node->ToText() : 0 );
+ }
+ /// Return the handle as a TiXmlUnknown. This may return null;
+ TiXmlUnknown* Unknown() const
+ {
+ return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 );
+ }
+
+private:
+ TiXmlNode* node;
+};
+
+
+#endif
+
diff --git a/yhttpd/src/contrib/xml/tinyxmlerror.cpp b/yhttpd/src/contrib/xml/tinyxmlerror.cpp
new file mode 100644
index 0000000..9243e89
--- /dev/null
+++ b/yhttpd/src/contrib/xml/tinyxmlerror.cpp
@@ -0,0 +1,51 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include "tinyxml.h"
+
+// The goal of the seperate error file is to make the first
+// step towards localization. tinyxml (currently) only supports
+// latin-1, but at least the error messages could now be translated.
+//
+// It also cleans up the code a bit.
+//
+
+const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
+ {
+ "No error",
+ "Error",
+ "Failed to open file",
+ "Memory allocation failed.",
+ "Error parsing Element.",
+ "Failed to read Element name",
+ "Error reading Element value.",
+ "Error reading Attributes.",
+ "Error: empty tag.",
+ "Error reading end tag.",
+ "Error parsing Unknown.",
+ "Error parsing Comment.",
+ "Error parsing Declaration.",
+ "Error document empty.",
+ "Error null (0) or unexpected EOF found in input stream.",
+ };
diff --git a/yhttpd/src/contrib/xml/tinyxmlparser.cpp b/yhttpd/src/contrib/xml/tinyxmlparser.cpp
new file mode 100644
index 0000000..9c696b6
--- /dev/null
+++ b/yhttpd/src/contrib/xml/tinyxmlparser.cpp
@@ -0,0 +1,1553 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include "tinyxml.h"
+#include <ctype.h>
+
+//#define DEBUG_PARSER
+
+// Note tha "PutString" hardcodes the same list. This
+// is less flexible than it appears. Changing the entries
+// or order will break putstring.
+TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] =
+ {
+ { "&amp;", 5, '&' },
+ { "&lt;", 4, '<' },
+ { "&gt;", 4, '>' },
+ { "&quot;", 6, '\"' },
+ { "&apos;", 6, '\'' }
+ };
+
+// Bunch of unicode info at:
+// http://www.unicode.org/faq/utf_bom.html
+// Including the basic of this table, which determines the #bytes in the
+// sequence from the lead byte. 1 placed for invalid sequences --
+// although the result will be junk, pass it through as much as possible.
+// Beware of the non-characters in UTF-8:
+// ef bb bf (Microsoft "lead bytes")
+// ef bf be
+// ef bf bf
+
+
+
+const int TiXmlBase::utf8ByteTable[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0
+ 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte
+ 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
+ };
+
+
+void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
+{
+ const unsigned long BYTE_MASK = 0xBF;
+ const unsigned long BYTE_MARK = 0x80;
+ const unsigned long FIRST_BYTE_MARK[7] =
+ {
+ 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
+ };
+
+ if (input < 0x80)
+ *length = 1;
+ else if ( input < 0x800 )
+ *length = 2;
+ else if ( input < 0x10000 )
+ *length = 3;
+ else if ( input < 0x200000 )
+ *length = 4;
+ else
+ {
+ *length = 0;
+ return;
+ } // This code won't covert this correctly anyway.
+
+ output += *length;
+
+ // Scary scary fall throughs.
+ switch (*length)
+ {
+ case 4:
+ --output;
+ *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+ input >>= 6;
+ case 3:
+ --output;
+ *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+ input >>= 6;
+ case 2:
+ --output;
+ *output = (char)((input | BYTE_MARK) & BYTE_MASK);
+ input >>= 6;
+ case 1:
+ --output;
+ *output = (char)(input | FIRST_BYTE_MARK[*length]);
+ }
+}
+
+
+/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding encoding )
+{
+ // This will only work for low-ascii, everything else is assumed to be a valid
+ // letter. I'm not sure this is the best approach, but it is quite tricky trying
+ // to figure out alhabetical vs. not across encoding. So take a very
+ // conservative approach.
+
+ // if ( encoding == TIXML_ENCODING_UTF8 )
+ // {
+ if ( anyByte < 127 )
+ return isalpha( anyByte );
+ else
+ return 1; // What else to do? The unicode set is huge...get the english ones right.
+ // }
+ // else
+ // {
+ // return isalpha( anyByte );
+ // }
+}
+
+
+/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding )
+{
+ // This will only work for low-ascii, everything else is assumed to be a valid
+ // letter. I'm not sure this is the best approach, but it is quite tricky trying
+ // to figure out alhabetical vs. not across encoding. So take a very
+ // conservative approach.
+
+ // if ( encoding == TIXML_ENCODING_UTF8 )
+ // {
+ if ( anyByte < 127 )
+ return isalnum( anyByte );
+ else
+ return 1; // What else to do? The unicode set is huge...get the english ones right.
+ // }
+ // else
+ // {
+ // return isalnum( anyByte );
+ // }
+}
+
+
+class TiXmlParsingData
+{
+ friend class TiXmlDocument;
+public:
+ void Stamp( const char* now, TiXmlEncoding encoding );
+
+ const TiXmlCursor& Cursor()
+ {
+ return cursor;
+ }
+
+private:
+ // Only used by the document!
+ TiXmlParsingData( const char* start, int _tabsize, int row, int col )
+ {
+ assert( start );
+ stamp = start;
+ tabsize = _tabsize;
+ cursor.row = row;
+ cursor.col = col;
+ }
+
+ TiXmlCursor cursor;
+ const char* stamp;
+ int tabsize;
+};
+
+
+void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding )
+{
+ assert( now );
+
+ // Do nothing if the tabsize is 0.
+ if ( tabsize < 1 )
+ {
+ return;
+ }
+
+ // Get the current row, column.
+ int row = cursor.row;
+ int col = cursor.col;
+ const char* p = stamp;
+ assert( p );
+
+ while ( p < now )
+ {
+ // Code contributed by Fletcher Dunn: (modified by lee)
+ switch (*p)
+ {
+ case 0:
+ // We *should* never get here, but in case we do, don't
+ // advance past the terminating null character, ever
+ return;
+
+ case '\r':
+ // bump down to the next line
+ ++row;
+ col = 0;
+ // Eat the character
+ ++p;
+
+ // Check for \r\n sequence, and treat this as a single character
+ if (*p == '\n')
+ {
+ ++p;
+ }
+ break;
+
+ case '\n':
+ // bump down to the next line
+ ++row;
+ col = 0;
+
+ // Eat the character
+ ++p;
+
+ // Check for \n\r sequence, and treat this as a single
+ // character. (Yes, this bizarre thing does occur still
+ // on some arcane platforms...)
+ if (*p == '\r')
+ {
+ ++p;
+ }
+ break;
+
+ case '\t':
+ // Eat the character
+ ++p;
+
+ // Skip to next tab stop
+ col = (col / tabsize + 1) * tabsize;
+ break;
+
+ case (char)(0xef):
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ if ( *(p+1) && *(p+2) )
+ {
+ // In these cases, don't advance the column. These are
+ // 0-width spaces.
+ if ( *(p+1)==(char)(0xbb) && *(p+2)==(char)(0xbf) )
+ p += 3;
+ else if ( *(p+1)==(char)(0xbf) && *(p+2)==(char)(0xbe) )
+ p += 3;
+ else if ( *(p+1)==(char)(0xbf) && *(p+2)==(char)(0xbf) )
+ p += 3;
+ else
+ {
+ p +=3;
+ ++col;
+ } // A normal character.
+ }
+ }
+ else
+ {
+ ++p;
+ ++col;
+ }
+ break;
+
+ default:
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ // Eat the 1 to 4 byte utf8 character.
+ int step = TiXmlBase::utf8ByteTable[*((unsigned char*)p)];
+ if ( step == 0 )
+ step = 1; // Error case from bad encoding, but handle gracefully.
+ p += step;
+
+ // Just advance one column, of course.
+ ++col;
+ }
+ else
+ {
+ ++p;
+ ++col;
+ }
+ break;
+ }
+ }
+ cursor.row = row;
+ cursor.col = col;
+ assert( cursor.row >= -1 );
+ assert( cursor.col >= -1 );
+ stamp = p;
+ assert( stamp );
+}
+
+
+const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding )
+{
+ if ( !p || !*p )
+ {
+ return 0;
+ }
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ while ( *p )
+ {
+ // Skip the stupid Microsoft UTF-8 Byte order marks
+ if ( *(p+0)==(char) 0xef
+ && *(p+1)==(char) 0xbb
+ && *(p+2)==(char) 0xbf )
+ {
+ p += 3;
+ continue;
+ }
+ else if(*(p+0)==(char) 0xef
+ && *(p+1)==(char) 0xbf
+ && *(p+2)==(char) 0xbe )
+ {
+ p += 3;
+ continue;
+ }
+ else if(*(p+0)==(char) 0xef
+ && *(p+1)==(char) 0xbf
+ && *(p+2)==(char) 0xbf )
+ {
+ p += 3;
+ continue;
+ }
+
+ if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space.
+ ++p;
+ else
+ break;
+ }
+ }
+ else
+ {
+ while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' )
+ ++p;
+ }
+
+ return p;
+}
+
+#ifdef TIXML_USE_STL
+/*static*/ bool TiXmlBase::StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+ for( ;; )
+ {
+ if ( !in->good() )
+ return false;
+
+ int c = in->peek();
+ // At this scope, we can't get to a document. So fail silently.
+ if ( !IsWhiteSpace( c ) || c <= 0 )
+ return true;
+
+ *tag += (char) in->get
+ ();
+ }
+}
+
+/*static*/ bool TiXmlBase::StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag )
+{
+ //assert( character > 0 && character < 128 ); // else it won't work in utf-8
+ while ( in->good() )
+ {
+ int c = in->peek();
+ if ( c == character )
+ return true;
+ if ( c <= 0 ) // Silent failure: can't get document at this scope
+ return false;
+
+ in->get
+ ();
+ *tag += (char) c;
+ }
+ return false;
+}
+#endif
+
+const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding )
+{
+ *name = "";
+ assert( p );
+
+ // Names start with letters or underscores.
+ // Of course, in unicode, tinyxml has no idea what a letter *is*. The
+ // algorithm is generous.
+ //
+ // After that, they can be letters, underscores, numbers,
+ // hyphens, or colons. (Colons are valid ony for namespaces,
+ // but tinyxml can't tell namespaces from names.)
+ if ( p && *p
+ && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) )
+ {
+ while( p && *p
+ && ( IsAlphaNum( (unsigned char ) *p, encoding )
+ || *p == '_'
+ || *p == '-'
+ || *p == '.'
+ || *p == ':' ) )
+ {
+ (*name) += *p;
+ ++p;
+ }
+ return p;
+ }
+ return 0;
+}
+
+const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding )
+{
+ // Presume an entity, and pull it out.
+ TIXML_STRING ent;
+ int i;
+ *length = 0;
+
+ if ( *(p+1) && *(p+1) == '#' && *(p+2) )
+ {
+ unsigned long ucs = 0;
+ unsigned delta = 0;
+ unsigned mult = 1;
+
+ if ( *(p+2) == 'x' )
+ {
+ // Hexadecimal.
+ if ( !*(p+3) )
+ return 0;
+
+ const char* q = p+3;
+ q = strchr( q, ';' );
+
+ if ( !q || !*q )
+ return 0;
+
+ delta = q-p;
+ --q;
+
+ while ( *q != 'x' )
+ {
+ if ( *q >= '0' && *q <= '9' )
+ ucs += mult * (*q - '0');
+ else if ( *q >= 'a' && *q <= 'f' )
+ ucs += mult * (*q - 'a' + 10);
+ else if ( *q >= 'A' && *q <= 'F' )
+ ucs += mult * (*q - 'A' + 10 );
+ else
+ return 0;
+ mult *= 16;
+ --q;
+ }
+ }
+ else
+ {
+ // Decimal.
+ if ( !*(p+2) )
+ return 0;
+
+ const char* q = p+2;
+ q = strchr( q, ';' );
+
+ if ( !q || !*q )
+ return 0;
+
+ delta = q-p;
+ --q;
+
+ while ( *q != '#' )
+ {
+ if ( *q >= '0' && *q <= '9' )
+ ucs += mult * (*q - '0');
+ else
+ return 0;
+ mult *= 10;
+ --q;
+ }
+ }
+ if ( encoding == TIXML_ENCODING_UTF8 )
+ {
+ // convert the UCS to UTF-8
+ ConvertUTF32ToUTF8( ucs, value, length );
+ }
+ else
+ {
+ *value = (char)ucs;
+ *length = 1;
+ }
+ return p + delta + 1;
+ }
+
+ // Now try to match it.
+ for( i=0; i<NUM_ENTITY; ++i )
+ {
+ if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 )
+ {
+ assert( strlen( entity[i].str ) == entity[i].strLength );
+ *value = entity[i].chr;
+ *length = 1;
+ return ( p + entity[i].strLength );
+ }
+ }
+
+ // So it wasn't an entity, its unrecognized, or something like that.
+ *value = *p; // Don't put back the last one, since we return it!
+ return p+1;
+}
+
+
+bool TiXmlBase::StringEqual( const char* p,
+ const char* tag,
+ bool ignoreCase,
+ TiXmlEncoding encoding )
+{
+ assert( p );
+ assert( tag );
+ if ( !p || !*p )
+ {
+ assert( 0 );
+ return false;
+ }
+
+ const char* q = p;
+
+ if ( ignoreCase )
+ {
+ while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) )
+ {
+ ++q;
+ ++tag;
+ }
+
+ if ( *tag == 0 )
+ return true;
+ }
+ else
+ {
+ while ( *q && *tag && *q == *tag )
+ {
+ ++q;
+ ++tag;
+ }
+
+ if ( *tag == 0 ) // Have we found the end of the tag, and everything equal?
+ return true;
+ }
+ return false;
+}
+
+const char* TiXmlBase::ReadText( const char* p,
+ TIXML_STRING * text,
+ bool trimWhiteSpace,
+ const char* endTag,
+ bool caseInsensitive,
+ TiXmlEncoding encoding )
+{
+ *text = "";
+ if ( !trimWhiteSpace // certain tags always keep whitespace
+ || !condenseWhiteSpace ) // if true, whitespace is always kept
+ {
+ // Keep all the white space.
+ while ( p && *p
+ && !StringEqual( p, endTag, caseInsensitive, encoding )
+ )
+ {
+ int len;
+ char cArr[4] = { 0, 0, 0, 0 };
+ p = GetChar( p, cArr, &len, encoding );
+ text->append( cArr, len );
+ }
+ }
+ else
+ {
+ bool whitespace = false;
+
+ // Remove leading white space:
+ p = SkipWhiteSpace( p, encoding );
+ while ( p && *p
+ && !StringEqual( p, endTag, caseInsensitive, encoding ) )
+ {
+ if ( *p == '\r' || *p == '\n' )
+ {
+ whitespace = true;
+ ++p;
+ }
+ else if ( IsWhiteSpace( *p ) )
+ {
+ whitespace = true;
+ ++p;
+ }
+ else
+ {
+ // If we've found whitespace, add it before the
+ // new character. Any whitespace just becomes a space.
+ if ( whitespace )
+ {
+ (*text) += ' ';
+ whitespace = false;
+ }
+ int len;
+ char cArr[4] = { 0, 0, 0, 0 };
+ p = GetChar( p, cArr, &len, encoding );
+ if ( len == 1 )
+ (*text) += cArr[0]; // more efficient
+ else
+ text->append( cArr, len );
+ }
+ }
+ }
+ return p + strlen( endTag );
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlDocument::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+ // The basic issue with a document is that we don't know what we're
+ // streaming. Read something presumed to be a tag (and hope), then
+ // identify it, and call the appropriate stream method on the tag.
+ //
+ // This "pre-streaming" will never read the closing ">" so the
+ // sub-tag can orient itself.
+
+ if ( !StreamTo( in, '<', tag ) )
+ {
+ SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ while ( in->good() )
+ {
+ int tagIndex = (int) tag->length();
+ while ( in->good() && in->peek() != '>' )
+ {
+ int c = in->get
+ ();
+ if ( c <= 0 )
+ {
+ SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ break;
+ }
+ (*tag) += (char) c;
+ }
+
+ if ( in->good() )
+ {
+ // We now have something we presume to be a node of
+ // some sort. Identify it, and call the node to
+ // continue streaming.
+ TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING );
+
+ if ( node )
+ {
+ node->StreamIn( in, tag );
+ bool isElement = node->ToElement() != 0;
+ delete node;
+ node = 0;
+
+ // If this is the root element, we're done. Parsing will be
+ // done by the >> operator.
+ if ( isElement )
+ {
+ return;
+ }
+ }
+ else
+ {
+ SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ }
+ }
+ // We should have returned sooner.
+ SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
+}
+
+#endif
+
+const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding )
+{
+ ClearError();
+
+ // Parse away, at the document level. Since a document
+ // contains nothing but other tags, most of what happens
+ // here is skipping white space.
+ if ( !p || !*p )
+ {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ // Note that, for a document, this needs to come
+ // before the while space skip, so that parsing
+ // starts from the pointer we are given.
+ location.Clear();
+ if ( prevData )
+ {
+ location.row = prevData->cursor.row;
+ location.col = prevData->cursor.col;
+ }
+ else
+ {
+ location.row = 0;
+ location.col = 0;
+ }
+ TiXmlParsingData data( p, TabSize(), location.row, location.col );
+ location = data.Cursor();
+
+ if ( encoding == TIXML_ENCODING_UNKNOWN )
+ {
+ // Check for the Microsoft UTF-8 lead bytes.
+ if ( *(p+0) && *(p+0) == (char)(0xef)
+ && *(p+1) && *(p+1) == (char)(0xbb)
+ && *(p+2) && *(p+2) == (char)(0xbf) )
+ {
+ encoding = TIXML_ENCODING_UTF8;
+ }
+ }
+
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p )
+ {
+ SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return 0;
+ }
+
+ while ( p && *p )
+ {
+ TiXmlNode* node = Identify( p, encoding );
+ if ( node )
+ {
+ p = node->Parse( p, &data, encoding );
+ LinkEndChild( node );
+ }
+ else
+ {
+ break;
+ }
+
+ // Did we get encoding info?
+ if ( encoding == TIXML_ENCODING_UNKNOWN
+ && node->ToDeclaration() )
+ {
+ TiXmlDeclaration* dec = node->ToDeclaration();
+ const char* enc = dec->Encoding();
+ assert( enc );
+
+ if ( *enc == 0 )
+ encoding = TIXML_ENCODING_UTF8;
+ else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) )
+ encoding = TIXML_ENCODING_UTF8;
+ else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) )
+ encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice
+ else
+ encoding = TIXML_ENCODING_LEGACY;
+ }
+
+ p = SkipWhiteSpace( p, encoding );
+ }
+
+ // All is well.
+ return p;
+}
+
+void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ // The first error in a chain is more accurate - don't set again!
+ if ( error )
+ return;
+
+ assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
+ error = true;
+ errorId = err;
+ errorDesc = errorString[ errorId ];
+
+ errorLocation.Clear();
+ if ( pError && data )
+ {
+ //TiXmlParsingData data( pError, prevData );
+ data->Stamp( pError, encoding );
+ errorLocation = data->Cursor();
+ }
+}
+
+
+TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding )
+{
+ TiXmlNode* returnNode = 0;
+
+ p = SkipWhiteSpace( p, encoding );
+ if( !p || !*p || *p != '<' )
+ {
+ return 0;
+ }
+
+ TiXmlDocument* doc = GetDocument();
+ p = SkipWhiteSpace( p, encoding );
+
+ if ( !p || !*p )
+ {
+ return 0;
+ }
+
+ // What is this thing?
+ // - Elements start with a letter or underscore, but xml is reserved.
+ // - Comments: <!--
+ // - Decleration: <?xml
+ // - Everthing else is unknown to tinyxml.
+ //
+
+ const char* xmlHeader =
+ { "<?xml"
+ };
+ const char* commentHeader =
+ { "<!--"
+ };
+ const char* dtdHeader =
+ { "<!"
+ };
+
+ if ( StringEqual( p, xmlHeader, true, encoding ) )
+ {
+#ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Declaration\n" );
+#endif
+
+ returnNode = new TiXmlDeclaration();
+ }
+ else if ( StringEqual( p, commentHeader, false, encoding ) )
+ {
+#ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Comment\n" );
+#endif
+
+ returnNode = new TiXmlComment();
+ }
+ else if ( StringEqual( p, dtdHeader, false, encoding ) )
+ {
+#ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Unknown(1)\n" );
+#endif
+
+ returnNode = new TiXmlUnknown();
+ }
+ else if ( IsAlpha( *(p+1), encoding )
+ || *(p+1) == '_' )
+ {
+#ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Element\n" );
+#endif
+
+ returnNode = new TiXmlElement( "" );
+ }
+ else
+ {
+#ifdef DEBUG_PARSER
+ TIXML_LOG( "XML parsing Unknown(2)\n" );
+#endif
+
+ returnNode = new TiXmlUnknown();
+ }
+
+ if ( returnNode )
+ {
+ // Set the parent, so it can report errors
+ returnNode->parent = this;
+ }
+ else
+ {
+ if ( doc )
+ doc->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+ }
+ return returnNode;
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlElement::StreamIn (TIXML_ISTREAM * in, TIXML_STRING * tag)
+{
+ // We're called with some amount of pre-parsing. That is, some of "this"
+ // element is in "tag". Go ahead and stream to the closing ">"
+ while( in->good() )
+ {
+ int c = in->get
+ ();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ (*tag) += (char) c ;
+
+ if ( c == '>' )
+ break;
+ }
+
+ if ( tag->length() < 3 )
+ return;
+
+ // Okay...if we are a "/>" tag, then we're done. We've read a complete tag.
+ // If not, identify and stream.
+
+ if ( tag->at( tag->length() - 1 ) == '>'
+ && tag->at( tag->length() - 2 ) == '/' )
+ {
+ // All good!
+ return;
+ }
+ else if ( tag->at( tag->length() - 1 ) == '>' )
+ {
+ // There is more. Could be:
+ // text
+ // closing tag
+ // another node.
+ for ( ;; )
+ {
+ StreamWhiteSpace( in, tag );
+
+ // Do we have text?
+ if ( in->good() && in->peek() != '<' )
+ {
+ // Yep, text.
+ TiXmlText text( "" );
+ text.StreamIn( in, tag );
+
+ // What follows text is a closing tag or another node.
+ // Go around again and figure it out.
+ continue;
+ }
+
+ // We now have either a closing tag...or another node.
+ // We should be at a "<", regardless.
+ if ( !in->good() )
+ return;
+ assert( in->peek() == '<' );
+ int tagIndex = tag->length();
+
+ bool closingTag = false;
+ bool firstCharFound = false;
+
+ for( ;; )
+ {
+ if ( !in->good() )
+ return;
+
+ int c = in->peek();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ if ( c == '>' )
+ break;
+
+ *tag += (char) c;
+ in->get
+ ();
+
+ if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) )
+ {
+ firstCharFound = true;
+ if ( c == '/' )
+ closingTag = true;
+ }
+ }
+ // If it was a closing tag, then read in the closing '>' to clean up the input stream.
+ // If it was not, the streaming will be done by the tag.
+ if ( closingTag )
+ {
+ if ( !in->good() )
+ return;
+
+ int c = in->get
+ ();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ assert( c == '>' );
+ *tag += (char) c;
+
+ // We are done, once we've found our closing tag.
+ return;
+ }
+ else
+ {
+ // If not a closing tag, id it, and stream.
+ const char* tagloc = tag->c_str() + tagIndex;
+ TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING );
+ if ( !node )
+ return;
+ node->StreamIn( in, tag );
+ delete node;
+ node = 0;
+
+ // No return: go around from the beginning: text, closing tag, or node.
+ }
+ }
+ }
+}
+#endif
+
+const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ p = SkipWhiteSpace( p, encoding );
+ TiXmlDocument* document = GetDocument();
+
+ if ( !p || !*p )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding );
+ return 0;
+ }
+
+ // TiXmlParsingData data( p, prevData );
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+
+ if ( *p != '<' )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding );
+ return 0;
+ }
+
+ p = SkipWhiteSpace( p+1, encoding );
+
+ // Read the name.
+ const char* pErr = p;
+
+ p = ReadName( p, &value, encoding );
+ if ( !p || !*p )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding );
+ return 0;
+ }
+
+ TIXML_STRING endTag ("</");
+ endTag += value;
+ endTag += ">";
+
+ // Check for and read attributes. Also look for an empty
+ // tag or an end tag.
+ while ( p && *p )
+ {
+ pErr = p;
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
+ return 0;
+ }
+ if ( *p == '/' )
+ {
+ ++p;
+ // Empty tag.
+ if ( *p != '>' )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding );
+ return 0;
+ }
+ return (p+1);
+ }
+ else if ( *p == '>' )
+ {
+ // Done with attributes (if there were any.)
+ // Read the value -- which can include other
+ // elements -- read the end tag, and return.
+ ++p;
+ p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens.
+ if ( !p || !*p )
+ return 0;
+
+ // We should find the end tag now
+ if ( StringEqual( p, endTag.c_str(), false, encoding ) )
+ {
+ p += endTag.length();
+ return p;
+ }
+ else
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
+ return 0;
+ }
+ }
+ else
+ {
+ // Try to read an attribute:
+ TiXmlAttribute* attrib = new TiXmlAttribute();
+ if ( !attrib )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding );
+ return 0;
+ }
+
+ attrib->SetDocument( document );
+ const char* pErr = p;
+ p = attrib->Parse( p, data, encoding );
+
+ if ( !p || !*p )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
+ delete attrib;
+ return 0;
+ }
+
+ // Handle the strange case of double attributes:
+ TiXmlAttribute* node = attributeSet.Find( attrib->Name() );
+ if ( node )
+ {
+ node->SetValue( attrib->Value() );
+ delete attrib;
+ return 0;
+ }
+
+ attributeSet.Add( attrib );
+ }
+ }
+ return p;
+}
+
+
+const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ TiXmlDocument* document = GetDocument();
+
+ const char* pWithWhiteSpace = p;
+ // Read in text and elements in any order.
+ p = SkipWhiteSpace( p, encoding );
+ while ( p && *p )
+ {
+ if ( *p != '<' )
+ {
+ // Take what we have, make a text element.
+ TiXmlText* textNode = new TiXmlText( "" );
+
+ if ( !textNode )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding );
+ return 0;
+ }
+
+ if ( TiXmlBase::IsWhiteSpaceCondensed() )
+ {
+ p = textNode->Parse( p, data, encoding );
+ }
+ else
+ {
+ // Special case: we want to keep the white space
+ // so that leading spaces aren't removed.
+ p = textNode->Parse( pWithWhiteSpace, data, encoding );
+ }
+
+ if ( !textNode->Blank() )
+ LinkEndChild( textNode );
+ else
+ delete textNode;
+ }
+ else
+ {
+ // We hit a '<'
+ // Have we hit a new element or an end tag?
+ if ( StringEqual( p, "</", false, encoding ) )
+ {
+ return p;
+ }
+ else
+ {
+ TiXmlNode* node = Identify( p, encoding );
+ if ( node )
+ {
+ p = node->Parse( p, data, encoding );
+ LinkEndChild( node );
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+ p = SkipWhiteSpace( p, encoding );
+ }
+
+ if ( !p )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding );
+ }
+ return p;
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlUnknown::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->get
+ ();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ (*tag) += (char) c;
+
+ if ( c == '>' )
+ {
+ // All is well.
+ return;
+ }
+ }
+}
+#endif
+
+
+const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ TiXmlDocument* document = GetDocument();
+ p = SkipWhiteSpace( p, encoding );
+
+ // TiXmlParsingData data( p, prevData );
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+ if ( !p || !*p || *p != '<' )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding );
+ return 0;
+ }
+ ++p;
+ value = "";
+
+ while ( p && *p && *p != '>' )
+ {
+ value += *p;
+ ++p;
+ }
+
+ if ( !p )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
+ }
+ if ( *p == '>' )
+ return p+1;
+ return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlComment::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->get
+ ();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ (*tag) += (char) c;
+
+ if ( c == '>'
+ && tag->at( tag->length() - 2 ) == '-'
+ && tag->at( tag->length() - 3 ) == '-' )
+ {
+ // All is well.
+ return;
+ }
+ }
+}
+#endif
+
+
+const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ TiXmlDocument* document = GetDocument();
+ value = "";
+
+ p = SkipWhiteSpace( p, encoding );
+
+ // TiXmlParsingData data( p, prevData );
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+ const char* startTag = "<!--";
+ const char* endTag = "-->";
+
+ if ( !StringEqual( p, startTag, false, encoding ) )
+ {
+ document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding );
+ return 0;
+ }
+ p += strlen( startTag );
+ p = ReadText( p, &value, false, endTag, false, encoding );
+ return p;
+}
+
+
+const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p )
+ return 0;
+
+ int tabsize = 4;
+ if ( document )
+ tabsize = document->TabSize();
+
+ // TiXmlParsingData data( p, prevData );
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+ // Read the name, the '=' and the value.
+ const char* pErr = p;
+ p = ReadName( p, &name, encoding );
+ if ( !p || !*p )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
+ return 0;
+ }
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p || *p != '=' )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+ return 0;
+ }
+
+ ++p; // skip '='
+ p = SkipWhiteSpace( p, encoding );
+ if ( !p || !*p )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+ return 0;
+ }
+
+ const char* end;
+
+ if ( *p == '\'' )
+ {
+ ++p;
+ end = "\'";
+ p = ReadText( p, &value, false, end, false, encoding );
+ }
+ else if ( *p == '"' )
+ {
+ ++p;
+ end = "\"";
+ p = ReadText( p, &value, false, end, false, encoding );
+ }
+ else
+ {
+ // All attribute values should be in single or double quotes.
+ // But this is such a common error that the parser will try
+ // its best, even without them.
+ value = "";
+ while ( p && *p // existence
+ && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace
+ && *p != '/' && *p != '>' ) // tag end
+ {
+ value += *p;
+ ++p;
+ }
+ }
+ return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlText::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->peek();
+ if ( c == '<' )
+ return;
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+
+ (*tag) += (char) c;
+ in->get
+ ();
+ }
+}
+#endif
+
+const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+ value = "";
+ // TiXmlParsingData data( p, prevData );
+ if ( data )
+ {
+ data->Stamp( p, encoding );
+ location = data->Cursor();
+ }
+ bool ignoreWhite = true;
+
+ const char* end = "<";
+ p = ReadText( p, &value, ignoreWhite, end, false, encoding );
+ if ( p )
+ return p-1; // don't truncate the '<'
+ return 0;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlDeclaration::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
+{
+ while ( in->good() )
+ {
+ int c = in->get
+ ();
+ if ( c <= 0 )
+ {
+ TiXmlDocument* document = GetDocument();
+ if ( document )
+ document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+ return;
+ }
+ (*tag) += (char) c;
+
+ if ( c == '>' )
+ {
+ // All is well.
+ return;
+ }
+ }
+}
+#endif
+
+const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding )
+{
+ p = SkipWhiteSpace( p, _encoding );
+ // Find the beginning, find the end, and look for
+ // the stuff in-between.
+ TiXmlDocument* document = GetDocument();
+ if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) )
+ {
+ if ( document )
+ document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding );
+ return 0;
+ }
+ // TiXmlParsingData data( p, prevData );
+ if ( data )
+ {
+ data->Stamp( p, _encoding );
+ location = data->Cursor();
+ }
+ p += 5;
+
+ version = "";
+ encoding = "";
+ standalone = "";
+
+ while ( p && *p )
+ {
+ if ( *p == '>' )
+ {
+ ++p;
+ return p;
+ }
+
+ p = SkipWhiteSpace( p, _encoding );
+ if ( StringEqual( p, "version", true, _encoding ) )
+ {
+ TiXmlAttribute attrib;
+ p = attrib.Parse( p, data, _encoding );
+ version = attrib.Value();
+ }
+ else if ( StringEqual( p, "encoding", true, _encoding ) )
+ {
+ TiXmlAttribute attrib;
+ p = attrib.Parse( p, data, _encoding );
+ encoding = attrib.Value();
+ }
+ else if ( StringEqual( p, "standalone", true, _encoding ) )
+ {
+ TiXmlAttribute attrib;
+ p = attrib.Parse( p, data, _encoding );
+ standalone = attrib.Value();
+ }
+ else
+ {
+ // Read over whatever it is.
+ while( p && *p && *p != '>' && !IsWhiteSpace( *p ) )
+ ++p;
+ }
+ }
+ return 0;
+}
+
+bool TiXmlText::Blank() const
+{
+ for ( unsigned i=0; i<value.length(); i++ )
+ if ( !IsWhiteSpace( value[i] ) )
+ return false;
+ return true;
+}
+
diff --git a/yhttpd/src/glob.h b/yhttpd/src/glob.h
new file mode 100644
index 0000000..a2c1334
--- /dev/null
+++ b/yhttpd/src/glob.h
@@ -0,0 +1,198 @@
+/*
+ Notice:
+
+ All #defines which start with an CONFIG can be edited through
+ gmake config in the main directory!
+*/
+
+#include "maps/hashmap.h"
+
+// global variables.
+#ifndef GLOB_H
+#define GLOB_H
+
+// Definition of boolean values.
+#define true 1
+#define false 0
+
+
+/* - CONFIG -
+ Should yhttpd get compiled with OpenSSL support?
+*/
+//#define OPENSSL
+
+/* - CONFIG -
+ Should yhttpd get compiled with comand line interface support?
+*/
+#define CLI
+
+/* - CONFIG -
+ What should be the name of the config file?
+*/
+#define CONFILE "yhttpd.conf"
+
+/* - DISABLED -
+ Enable debugging options.
+*/
+//#define DEBUG
+
+/* - DISABLED -
+ If you want to enable EXPERIMENTAL features, then set this val-
+ ue to true. Else use false which is recommended! All experimen-
+ al features are marked inside of the running yhttpd!
+*/
+//#define EXPERIM
+
+/* - CONFIG -
+ Should yhttpd get compiled with logging support?
+*/
+#define LOGGING
+
+/* - CONFIG -
+ Please enter the highest networking port which is allowed to be
+ used. If yhttpd is unable to create the server socket on a cert-
+ ain port, it will increment the port number and retries to cre-
+ ate another socket on the incremented port number. This proced-
+ ure will continue until MAXPORT has been reached.
+*/
+#define MAXPORT 65535
+
+/* Specifies the max amount of lines to read from a HTTP request
+ header
+*/
+#define MAXLINES 30
+
+/* Specifies the max length of a lines to read from a HTTP request
+ header
+*/
+#define MAXLENGTH 1024
+
+/* - CONFIG -
+ Should yhttpd get compiled with ncurses support?
+*/
+#define NCURSES
+
+/* - CONFIG -
+ Please specify the maximum length of a HTTP post request.
+*/
+#define POSTBUF 512
+
+/* - CONFIG -
+ Please specify the size of a temporary buffer. (Will be used f-
+ or different tasks)
+*/
+#define READBUF 2048
+
+/* - CONFIG -
+ Please specify the maximum length of a line read from a socket
+ or a file. ( config-file, html-template )
+*/
+#define READSOCK 2048
+
+/* - CONFIG -
+ In which prefix should yhttpd be installed if typing gmake inst-
+ all?
+*/
+#define PREFIX "/usr/local"
+
+/* - CONFIG -
+ DO NOT USE TOGETHER WITH NCURSES! Displays important server mes-
+ ages. This one will print all messages to stdout if no NCURSES
+ is defined. Don't use this until NCURSES is defined! all messag-
+ es will appear in the ncurses interface anyways.
+*/
+//#define SERVMSG
+
+/* - CONFIG -
+ Set to true if you want yhttpd to catch the SIGSEGV signal. yhttpd
+ will print a warning message into the system messages and will
+ not core dump if an error occurs.
+*/
+//#define CTCSEGV
+
+/* - CONFIG -
+ Please chose if you want to use verbose server outputs or not.
+ The verbose messages will appear in the ncurses menu if ncurses
+ is enabled or in the server-window if yhttpd has been compiled
+ without ncurses support. This option shows you all incoming
+ requests with the client IP and port numbers. You probably want
+ this to be turned off if you have heavy server load.
+*/
+//#define VERBOSE
+
+
+
+
+// The following values define the positions of the data stats in the NCURSES interface.
+#ifdef NCURSES
+#define NCUR_SERVER_HEADER_X 21
+#define NCUR_SERVER_HEADER_Y 2
+#define NCUR_PORT_X 22
+#define NCUR_PORT_Y 2
+#define NCUR_HITS_X 23
+#define NCUR_HITS_Y 2
+
+#define NCUR_POOL_HEADER_X 21
+#define NCUR_POOL_HEADER_Y 16
+#define NCUR_POOL_WAIT_X 22
+#define NCUR_POOL_WAIT_Y 16
+#define NCUR_POOL_RUNNING_X 23
+#define NCUR_POOL_RUNNING_Y 16
+
+#define NCUR_DATA_HEADER_X 21
+#define NCUR_DATA_HEADER_Y 35
+#define NCUR_GARBAGE_X 22
+#define NCUR_GARBAGE_Y 35
+#define NCUR_CON_QUEUE_X 23
+#define NCUR_CON_QUEUE_Y 35
+
+#define NCUR_HTTPD_HEADER_X 21
+#define NCUR_HTTPD_HEADER_Y 52
+#define NCUR_NUM_ROOMS_X 22
+#define NCUR_NUM_ROOMS_Y 52
+#define NCUR_SESSION_X 23
+#define NCUR_SESSION_Y 52
+
+#define NCUR_CACHED_HEADER_X 21
+#define NCUR_CACHED_HEADER_Y 68
+#define NCUR_CACHED_DOCS_X 22
+#define NCUR_CACHED_DOCS_Y 68
+#define NCUR_CACHED_MODS_X 23
+#define NCUR_CACHED_MODS_Y 68
+
+#define NCUR_MENU_CHAR_X 0
+#define NCUR_MENU_CHAR_Y 33
+#define NCUR_UPTIME_X 0
+#define NCUR_UPTIME_Y 44
+#define NCUR_TIME_X 0
+#define NCUR_TIME_Y 64
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// DO NOT CHANGE ANYTHING BEHIND THIS LINE!
+//////////////////////////////////////////////////////////////////////////////////////////
+
+using namespace std;
+
+typedef int function( void *v_arg );
+
+struct container
+{
+ void* elem[4];
+};
+
+struct dynmod
+{
+ function *the_func ;
+ void *the_module;
+};
+
+typedef enum method_ {
+ METH_NCURSES,
+ METH_RETSTRING
+} method;
+
+// Define external executables:
+#define GMAKE "/usr/local/bin/gmake \0"
+#endif
diff --git a/yhttpd/src/html.cpp b/yhttpd/src/html.cpp
new file mode 100644
index 0000000..ace041a
--- /dev/null
+++ b/yhttpd/src/html.cpp
@@ -0,0 +1,133 @@
+#ifndef HTML_CPP
+#define HTML_CPP
+
+#include <fstream>
+#include "html.h"
+
+using namespace std;
+
+html::html( )
+{
+ set_name( wrap::CONF->get_elem( "httpd.templatedir" ) );
+}
+
+html::~html( )
+{}
+
+void
+html::clear_cache( )
+{
+ clear();
+ wrap::system_message( CLRHTML );
+
+#ifdef NCURSES
+
+ print_cached( 0 );
+#endif
+}
+
+string
+html::parse( map<string,string> &map_params )
+{
+ string s_file = map_params["request"];
+
+ // check if s_file is in the container.
+ string s_templ;
+
+ // if not, read file.
+ if ( ! shashmap<string>::exists( s_file ) )
+ {
+ string s_path = get_name();
+ ifstream if_templ( s_path.append( s_file ).c_str(), ios::binary );
+
+ if ( ! if_templ )
+ {
+ wrap::system_message( OFFFOUND + s_path );
+ if(map_params["request"] == wrap::CONF->get_elem( "httpd.html.notfound" ))
+ return "";
+
+ map_params["request"] = wrap::CONF->get_elem( "httpd.html.notfound" );
+ return parse( map_params );
+ }
+
+ char c_buf;
+ while( !if_templ.eof() )
+ {
+ if_templ.get( c_buf );
+ s_templ += c_buf;
+ }
+
+ if ( map_params["content-type"].compare(0,5,"text/") == 0 )
+ s_templ.erase(s_templ.end()-1);
+
+ if_templ.close();
+
+ wrap::system_message( TECACHE + s_path );
+
+ // cache file.
+ shashmap<string>::add_elem(s_templ, s_file);
+#ifdef NCURSES
+
+ print_cached( shashmap<string>::size() );
+#endif
+
+ }
+ else
+ {
+ s_templ = shashmap<string>::get_elem( s_file );
+ }
+
+ // find %%KEY%% token and substituate those.
+ unsigned pos[2];
+ pos[0] = pos[1] = 0;
+
+ for(;;)
+ {
+ pos[0] = s_templ.find( "%%", pos[1] );
+
+ if ( pos[0] == string::npos )
+ break;
+
+ pos[0] += 2;
+ pos[1] = s_templ.find( "%%", pos[0] );
+
+ if ( pos[0] == string::npos )
+ break;
+
+ // get key and val.
+ string s_key = s_templ.substr( pos[0], pos[1]-pos[0] );
+ string s_val = wrap::CONF->get_elem( s_key );
+
+ // if s_val is empty use map_params.
+ if ( s_val.empty() )
+ s_val = map_params[ s_key ];
+
+ // substituate key with val.
+ s_templ.replace( pos[0]-2, pos[1]-pos[0]+4, s_val );
+
+ // calculate the string displacement.
+ int i_diff = s_val.length() - ( pos[1] - pos[0] + 4);
+
+ pos[1] += 2 + i_diff;
+
+ };
+
+ return s_templ;
+}
+
+
+#ifdef NCURSES
+void
+html::print_cached( int i_docs )
+{
+ if ( !wrap::NCUR->is_ready() )
+ return;
+
+ mvprintw( NCUR_CACHED_DOCS_X, NCUR_CACHED_DOCS_Y, "Docs: %d ", i_docs);
+ refresh();
+}
+
+#endif
+
+#endif
+
diff --git a/yhttpd/src/html.h b/yhttpd/src/html.h
new file mode 100644
index 0000000..14a7161
--- /dev/null
+++ b/yhttpd/src/html.h
@@ -0,0 +1,38 @@
+// class html declaration. this class manages the html-template files.
+#include "incl.h"
+
+#ifndef HTML_H
+#define HTML_H
+
+#include "maps/shashmap.h"
+#include "name.h"
+
+using namespace std;
+
+class html : public shashmap<string>, name
+{
+public:
+ html( );
+ ~html( );
+
+ // Clears the template cache so that new html templates will be read
+ // from hard disk. This method is needed after changeing s.t. on
+ // the html-template files.
+ void clear_cache( );
+
+ // Returns a parsed html-template. this method will check first if the
+ // required html-template exists inside the classes template cache. if not
+ // then the file will be read from file and added to the cache.
+ // afterwards the html-template will be parsed and returned.
+ // map_params contains the client request parameters which also will be
+ // used for string substituation.
+ string parse( map<string,string> &map_params );
+
+#ifdef NCURSES
+
+ void print_cached( int i_docs );
+#endif
+
+};
+
+#endif
diff --git a/yhttpd/src/incl.h b/yhttpd/src/incl.h
new file mode 100644
index 0000000..31e220c
--- /dev/null
+++ b/yhttpd/src/incl.h
@@ -0,0 +1,13 @@
+#include <pthread.h>
+#include <iostream>
+#include <string>
+#include <map>
+
+#include "glob.h"
+
+#ifdef NCURSES
+#include <ncurses.h>
+#endif
+
+#include "msgs.h"
+#include "wrap.h"
diff --git a/yhttpd/src/logd.cpp b/yhttpd/src/logd.cpp
new file mode 100644
index 0000000..664cd14
--- /dev/null
+++ b/yhttpd/src/logd.cpp
@@ -0,0 +1,175 @@
+
+#ifndef LOGD_CPP
+#define LOGD_CPP
+
+#include "logd.h"
+
+#ifdef LOGGING
+
+#include <fstream>
+
+logd::logd( string s_filename, string s_log_lines )
+{
+ initialize( s_filename, tool::string2int(s_log_lines) );
+}
+
+logd::logd( string s_filename, int i_log_lines )
+{
+ initialize( s_filename, i_log_lines );
+}
+
+logd::~logd()
+{
+ flush_logs();
+ pthread_mutex_destroy( &mut_s_logging );
+}
+
+void
+logd::initialize( string s_filename, int i_log_lines )
+{
+ pthread_mutex_init( &mut_s_logging, NULL );
+
+ if( s_filename.empty() )
+ {
+ wrap::system_message( LOGERR2 );
+ exit(1);
+ }
+
+ //if (wrap::NCUR->is_ready())
+ // wrap::system_message(LOGGINI+s_filename);
+
+ s_logfile = s_filename;
+ i_lines = i_log_lines;
+}
+
+string
+logd::get_time_string()
+{
+ struct tm *t_m;
+ time_t t_cur = time(NULL);
+ t_m = gmtime(&t_cur);
+
+ char c_buf[100];
+ c_buf[99] = '\0';
+ strftime(c_buf, 100, "[%d/%b/%Y:%H:%M:%S %z]", t_m);
+
+ return string(c_buf);
+}
+
+void
+logd::flush()
+{
+ ofstream of_output;
+ of_output.open(s_logfile.c_str(), ios::app);
+
+ if( of_output == NULL )
+ {
+ wrap::system_message( LOGERR1 + s_logfile );
+ exit(1);
+ }
+
+ while( ! s_queue.empty() )
+ {
+ string s_l=s_queue.front();
+ s_queue.pop();
+ of_output.write( s_l.c_str(), s_l.size() );
+ }
+
+ of_output.close();
+}
+
+void
+logd::log_access( map<string,string> &map_request )
+{
+ //static int i_access_lines = wrap::CONF->get_elem("httpd.logging.access_lines");
+
+ string s_time = get_time_string();
+ string s_logstr = map_request["REMOTE_ADDR"] + " - - "+s_time+" \"" + map_request["QUERY_STRING"]+"\" 200 0 \""+map_request["request"]+"\" \""+map_request["User-Agent"]+"\"\n";
+
+ pthread_mutex_lock ( &mut_s_logging );
+ s_queue.push(s_logstr);
+
+ if ( s_queue.size() > i_lines )
+ flush();
+
+ pthread_mutex_unlock( &mut_s_logging );
+}
+
+void
+logd::log_simple_line( string s_line )
+{
+ // Dont log empty lines!
+ if (s_line.empty())
+ return;
+
+ string s_time = get_time_string();
+ string s_logstr = s_time + " " + s_line;
+
+ pthread_mutex_lock ( &mut_s_logging );
+ s_queue.push(s_logstr);
+
+ if ( s_queue.size() > i_lines )
+ flush();
+
+ pthread_mutex_unlock( &mut_s_logging );
+}
+
+void
+logd::set_logfile( string s_path, string s_filename )
+{
+ // Remove "/" from filename!
+ unsigned i_pos = s_filename.find( "/" );
+ while ( i_pos != string::npos )
+ {
+ s_filename.replace( i_pos, 1, "SLASH" );
+ i_pos = s_filename.find( "/" );
+ }
+
+ // Remove "\" from filename (for non unix systems)!
+ i_pos = s_filename.find( "\\" );
+ while ( i_pos != string::npos )
+ {
+ s_filename.replace( i_pos, 1, "BACKSLASH" );
+ i_pos = s_filename.find( "\\" );
+ }
+
+ pthread_mutex_lock ( &mut_s_logging );
+ this->s_logfile = s_path + s_filename;
+ pthread_mutex_unlock( &mut_s_logging );
+}
+
+void
+logd::flush_logs()
+{
+ pthread_mutex_lock ( &mut_s_logging );
+ flush();
+ pthread_mutex_unlock( &mut_s_logging );
+}
+
+string
+logd::remove_html_tags( string s_logs )
+{
+ unsigned pos[2];
+
+ while ( (pos[0] = s_logs.find("<")) != string::npos )
+ {
+ if ( (pos[1] = s_logs.find(">", pos[0])) != string::npos )
+ s_logs.replace( pos[0], pos[1]-pos[0]+1, "");
+ else
+ break;
+ }
+
+ if ( s_logs == "\n" )
+ return "";
+
+ return s_logs;
+}
+
+void
+logd::set_lines( const int i_lines )
+{
+ this->i_lines = i_lines;
+}
+
+#endif
+#endif
diff --git a/yhttpd/src/logd.h b/yhttpd/src/logd.h
new file mode 100644
index 0000000..2d6270b
--- /dev/null
+++ b/yhttpd/src/logd.h
@@ -0,0 +1,37 @@
+#include "incl.h"
+
+#ifdef LOGGING
+#ifndef LOGD_H
+#define LOGD_H
+
+#include <queue>
+#include <time.h>
+
+class logd
+{
+private:
+ string s_logfile;
+ queue<string> s_queue;
+ pthread_mutex_t mut_s_logging;
+ int i_lines;
+
+ void initialize( string s_filename, int i_log_lines );
+ void flush();
+ void set_lines( const int i_lines );
+ string get_time_string();
+
+public:
+ logd( string s_filename, string s_log_lines );
+ logd( string s_filename, int i_log_lines );
+ ~logd();
+
+ void set_logfile( string s_path, string s_filename );
+ void log_access( map<string,string> &map_request );
+ void log_simple_line( string s_line );
+ void flush_logs();
+ static string remove_html_tags( string s_log );
+};
+
+#endif
+#endif
+
diff --git a/yhttpd/src/main.cpp b/yhttpd/src/main.cpp
new file mode 100644
index 0000000..87f1cab
--- /dev/null
+++ b/yhttpd/src/main.cpp
@@ -0,0 +1,101 @@
+/*
+ * yhttpd; Contact: www.yChat.org; Mail@yChat.org
+ * Copyright (C) 2003 Paul C. Buetow, Volker Richter
+ * Copyright (C) 2004 Paul C. Buetow
+ * Copyright (C) 2005 EXA Digital Solutions GbR
+ * -----------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "incl.h"
+#include "sign.h"
+
+
+#include "maps/hashmap.h"
+
+using namespace std;
+
+map<string,string>*
+parse_argc( int argc, char* argv[] )
+{
+ map<string,string>* start_params = new map<string,string>;
+
+ string s_output = "";
+
+ // Set to 1 if a config option key has to be read
+ // ( ./yhttpd -o key1 value1 -o key2 value2 ... );
+ bool b_conf = 0;
+
+ // Will store the key of an additional option value (see also b_conf)
+ string s_key;
+
+ for (int i=1; argv[i] != 0; i++)
+ {
+ if ( !s_key.empty() )
+ {
+ (*start_params)[s_key] = string(argv[i]);
+ s_key.clear();
+ }
+ else if ( b_conf )
+ {
+ s_key = string(argv[i]);
+ b_conf = 0;
+ }
+ else
+ {
+ if ( string(argv[i]).find("v") != string::npos )
+ s_output.append(tool::yhttpd_version()+"\n");
+
+ if ( string(argv[i]).find("h") != string::npos )
+ s_output.append( YCUSAGE );
+
+ if ( string(argv[i]).find("o") != string::npos )
+ b_conf = 1;
+ }
+ }
+
+ if ( !s_output.empty() )
+ {
+ cout << s_output;
+ delete start_params;
+ exit(1);
+ }
+
+ return start_params;
+}
+
+int
+main(int argc, char* argv[])
+{
+ cout << tool::yhttpd_version() << endl
+ << DESCRIP << endl
+ << DESCRI2 << endl
+ << CONTACT << endl
+ << SEPERAT << endl;
+
+ wrap::init_wrapper(parse_argc(argc, argv));
+
+
+ sign::init_signal_handlers();
+
+ // start the socket manager. this one will listen for incoming http requests and will
+ // forward them to the specified routines which will generate a http response.
+ wrap::SOCK->start();
+
+ cout << DOWNMSG << endl;
+ return 0;
+}
diff --git a/yhttpd/src/maps/hashmap.h b/yhttpd/src/maps/hashmap.h
new file mode 100644
index 0000000..b3a3212
--- /dev/null
+++ b/yhttpd/src/maps/hashmap.h
@@ -0,0 +1,53 @@
+#ifndef HASHMAP_H
+#define HASHMAP_H
+
+#include <ext/hash_map>
+
+using namespace std;
+
+template<class key_type_>
+struct compare_allocator
+{
+ inline bool operator()(key_type_ t_key_1, key_type_ t_key_2) const;
+};
+
+template<class key_type_>
+struct equals_allocator
+{
+ inline bool operator()(key_type_ t_key_1, key_type_ t_key_2) const;
+};
+
+template<class key_type_>
+struct size_hash
+{
+ inline int operator()(key_type_ t_key) const;
+};
+
+template<class key_type_>
+struct self_hash
+{
+ inline int operator()(key_type_ t_key) const;
+};
+
+template
+<
+class obj_type,
+class key_type_ = string,
+class hash_type = size_hash<string>,
+class alloc_type = compare_allocator<string>
+>
+struct hashmap : public __gnu_cxx::hash_map<key_type_, obj_type, hash_type, alloc_type>
+{
+ virtual inline void set_elem(obj_type t_obj, key_type_ t_key);
+ virtual inline obj_type get_elem(key_type_ t_key);
+ virtual inline obj_type get_set_elem(obj_type t_obj, key_type_ t_key);
+ virtual inline obj_type get_or_callback_set
+ (obj_type (*func)(void*), void* p_void, key_type_ t_key);
+ virtual inline vector<key_type_>* get_key_vector();
+ virtual inline bool exists(key_type_ t_key);
+ virtual inline void run_func( void (*func)(obj_type) );
+ virtual inline void run_func( void (*func)(obj_type, void*), void* v_arg );
+};
+
+#include "hashmap.tmpl"
+#endif
diff --git a/yhttpd/src/maps/hashmap.tmpl b/yhttpd/src/maps/hashmap.tmpl
new file mode 100644
index 0000000..9ee2f36
--- /dev/null
+++ b/yhttpd/src/maps/hashmap.tmpl
@@ -0,0 +1,126 @@
+template<class key_type_>
+bool
+compare_allocator<key_type_>::operator()(key_type_ t_key_1, key_type_ t_key_2) const
+{
+ return t_key_1.compare(t_key_2) == 0;
+}
+
+template<class key_type_>
+bool
+equals_allocator<key_type_>::operator()(key_type_ t_key_1, key_type_ t_key_2) const
+{
+ return t_key_1 == t_key_2;
+}
+
+template<class key_type_>
+int
+size_hash<key_type_>::operator()(key_type_ t_key) const
+{
+ int i_hash = 0;
+ int i_size = t_key.size();
+
+ for( size_t i = 0; i < i_size; ++i )
+ i_hash = ( i_hash << 5 ) ^ t_key.at(i) ^ i_hash;
+
+ return i_hash;
+}
+
+template<class key_type_>
+int
+self_hash<key_type_>::operator()(key_type_ t_key) const
+{
+ return t_key;
+}
+
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+obj_type
+hashmap<obj_type, key_type_, hash_type, alloc_type>::get_set_elem(obj_type t_obj, key_type_ t_key)
+{
+ typename hashmap<obj_type, key_type_, hash_type, alloc_type>::iterator iter = this->find(t_key);
+
+ if ( iter == this->end() )
+ {
+ set_elem(t_obj, t_key);
+ return obj_type();
+ }
+
+ obj_type t_ret = iter->second;
+ iter->second = t_obj;
+
+ return t_ret;
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+obj_type
+hashmap<obj_type, key_type_, hash_type, alloc_type>::get_or_callback_set
+(obj_type (*func)(void*), void* p_void, key_type_ t_key)
+{
+ typename hashmap<obj_type, key_type_, hash_type, alloc_type>::iterator iter = this->find(t_key);
+
+ if ( iter == this->end() )
+ {
+ obj_type t_obj = (*func) (p_void);
+ set_elem(t_obj, t_key);
+ return t_obj;
+ }
+
+ return iter->second;
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+void
+hashmap<obj_type, key_type_, hash_type, alloc_type>::set_elem(obj_type t_obj, key_type_ t_key)
+{
+ (*this)[t_key] = t_obj;
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+obj_type
+hashmap<obj_type, key_type_, hash_type, alloc_type>::get_elem(key_type_ t_key)
+{
+ typename hashmap<obj_type, key_type_, hash_type, alloc_type>::iterator iter = this->find(t_key);
+
+ if ( iter != this->end() )
+ return iter->second;
+
+ return obj_type();
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+vector<key_type_>*
+hashmap<obj_type, key_type_, hash_type, alloc_type>::get_key_vector()
+{
+ vector<key_type_>* p_vec = new vector<key_type_>;
+ typename hashmap<obj_type, key_type_, hash_type, alloc_type>::iterator iter;
+
+ for ( iter = this->begin(); iter != this->end(); ++iter )
+ p_vec->push_back(iter->first);
+
+ return p_vec;
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+bool
+hashmap<obj_type, key_type_, hash_type, alloc_type>::exists(key_type_ t_key)
+{
+ return this->find(t_key) != this->end();
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+void
+hashmap<obj_type, key_type_, hash_type, alloc_type>::run_func( void (*func)(obj_type) )
+{
+ typename hashmap<obj_type, key_type_, hash_type, alloc_type>::iterator iter;
+ for ( iter = this->begin(); iter != this->end(); ++iter )
+ ( *func ) ( iter->second );
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+void
+hashmap<obj_type, key_type_, hash_type, alloc_type>::run_func( void (*func)(obj_type, void*), void* v_arg )
+{
+ typename hashmap<obj_type, key_type_, hash_type, alloc_type>::iterator iter;
+ for ( iter = this->begin(); iter != this->end(); ++iter )
+ ( *func ) ( iter->second, v_arg );
+}
diff --git a/yhttpd/src/maps/mtools.h b/yhttpd/src/maps/mtools.h
new file mode 100644
index 0000000..4ee45b8
--- /dev/null
+++ b/yhttpd/src/maps/mtools.h
@@ -0,0 +1,11 @@
+#ifndef MTOOLS_H
+#define MTOOLS_H
+
+template <class type_>
+struct mtools
+{
+ static void delete_obj(type_ type_obj);
+};
+
+#include "mtools.tmpl"
+#endif
diff --git a/yhttpd/src/maps/mtools.tmpl b/yhttpd/src/maps/mtools.tmpl
new file mode 100644
index 0000000..6917131
--- /dev/null
+++ b/yhttpd/src/maps/mtools.tmpl
@@ -0,0 +1,12 @@
+#ifndef MTOOLS_TMPL
+#define MTOOLS_TMPL
+
+template <class type_>
+void
+mtools<type_>::delete_obj( type_ type_obj )
+{
+ if ( type_obj )
+ delete type_obj;
+}
+
+#endif
diff --git a/yhttpd/src/maps/nhashmap.h b/yhttpd/src/maps/nhashmap.h
new file mode 100644
index 0000000..f440230
--- /dev/null
+++ b/yhttpd/src/maps/nhashmap.h
@@ -0,0 +1,21 @@
+#ifndef NHASHMAP_H
+#define NHASHMAP_H
+
+#include "shashmap.h"
+
+using namespace std;
+
+template
+<
+class obj_type,
+class key_type_ = string,
+class hash_type = size_hash<string>,
+class alloc_type = compare_allocator<string>
+>
+struct nhashmap : public shashmap<obj_type, key_type_, hash_type, alloc_type>
+{
+ inline obj_type get_elem(key_type_ t_key);
+};
+
+#include "nhashmap.tmpl"
+#endif
diff --git a/yhttpd/src/maps/nhashmap.tmpl b/yhttpd/src/maps/nhashmap.tmpl
new file mode 100644
index 0000000..3ea1934
--- /dev/null
+++ b/yhttpd/src/maps/nhashmap.tmpl
@@ -0,0 +1,11 @@
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+obj_type
+nhashmap<obj_type, key_type_, hash_type, alloc_type>::get_elem(key_type_ t_key)
+{
+ typename hashmap<obj_type, key_type_, hash_type, alloc_type>::iterator iter = this->find(t_key);
+
+ if ( iter != this->end() )
+ return iter->second;
+
+ return NULL;
+}
diff --git a/yhttpd/src/maps/shashmap.h b/yhttpd/src/maps/shashmap.h
new file mode 100644
index 0000000..f692e32
--- /dev/null
+++ b/yhttpd/src/maps/shashmap.h
@@ -0,0 +1,49 @@
+#ifndef SHASHMAP_H
+#define SHASHMAP_H
+
+#include <pthread.h>
+#include "hashmap.h"
+
+#include "../monitor/dump.h"
+
+using namespace std;
+
+template
+<
+class obj_type,
+class key_type_ = string,
+class hash_type = size_hash<string>,
+class alloc_type = compare_allocator<string>
+>
+class shashmap : protected hashmap<obj_type, key_type_, hash_type, alloc_type>,
+ public dumpable
+{
+private:
+ pthread_mutex_t mut_shashmap;
+
+protected:
+ virtual void dumpit();
+
+public:
+ explicit shashmap();
+ ~shashmap();
+ virtual inline void set_elem(obj_type t_obj, key_type_ t_key);
+ virtual inline obj_type get_set_elem(obj_type t_obj, key_type_ t_key);
+ virtual inline obj_type get_or_callback_set
+ (obj_type (*func)(void*), void* p_void, key_type_ t_key);
+ virtual inline void add_elem(obj_type t_obj, key_type_ t_key);
+ virtual inline void add_elem_insecure(obj_type t_obj, key_type_ t_key);
+ virtual inline obj_type get_elem(key_type_ t_key);
+ virtual inline void del_elem(key_type_ t_key);
+ virtual inline void del_elem_insecure(key_type_ t_key);
+ virtual inline void clear();
+ virtual inline int size();
+ virtual inline bool exists(key_type_ t_key);
+ virtual inline vector<key_type_>* get_key_vector();
+ virtual inline void run_func( void (*func)(obj_type) );
+ virtual inline void run_func( void (*func)(obj_type, void*), void* v_arg );
+
+};
+
+#include "shashmap.tmpl"
+#endif
diff --git a/yhttpd/src/maps/shashmap.tmpl b/yhttpd/src/maps/shashmap.tmpl
new file mode 100644
index 0000000..0bd5796
--- /dev/null
+++ b/yhttpd/src/maps/shashmap.tmpl
@@ -0,0 +1,157 @@
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+shashmap<obj_type, key_type_, hash_type, alloc_type>::shashmap()
+{
+ pthread_mutex_init( &mut_shashmap, NULL );
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+shashmap<obj_type, key_type_, hash_type, alloc_type>::~shashmap()
+{
+ pthread_mutex_destroy( &mut_shashmap );
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+void
+shashmap<obj_type, key_type_, hash_type, alloc_type>::add_elem(obj_type t_obj, key_type_ t_key)
+{
+ pthread_mutex_lock( &mut_shashmap );
+ (*this)[t_key] = t_obj;
+ pthread_mutex_unlock( &mut_shashmap );
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+void
+shashmap<obj_type, key_type_, hash_type, alloc_type>::add_elem_insecure(obj_type t_obj, key_type_ t_key)
+{
+ (*this)[t_key] = t_obj;
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+obj_type
+shashmap<obj_type, key_type_, hash_type, alloc_type>::get_set_elem(obj_type t_obj, key_type_ t_key)
+{
+ pthread_mutex_lock( &mut_shashmap );
+ obj_type t_ret = hashmap<obj_type, key_type_, hash_type, alloc_type>::get_set_elem(t_obj, t_key);
+ pthread_mutex_unlock( &mut_shashmap );
+ return t_ret;
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+obj_type
+shashmap<obj_type, key_type_, hash_type, alloc_type>::get_or_callback_set
+(obj_type (*func)(void*), void* p_void, key_type_ t_key)
+{
+ pthread_mutex_lock( &mut_shashmap );
+ obj_type t_ret = hashmap<obj_type, key_type_, hash_type, alloc_type>::get_or_callback_set
+ (func, p_void, t_key);
+ pthread_mutex_unlock( &mut_shashmap );
+ return t_ret;
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+void
+shashmap<obj_type, key_type_, hash_type, alloc_type>::set_elem(obj_type t_obj, key_type_ t_key)
+{
+ pthread_mutex_lock( &mut_shashmap );
+ (*this)[t_key] = t_obj;
+ pthread_mutex_unlock( &mut_shashmap );
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+obj_type
+shashmap<obj_type, key_type_, hash_type, alloc_type>::get_elem(key_type_ t_key)
+{
+ pthread_mutex_lock( &mut_shashmap );
+ obj_type t_ret = hashmap<obj_type, key_type_, hash_type, alloc_type>::get_elem(t_key);
+ pthread_mutex_unlock( &mut_shashmap );
+ return t_ret;
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+void
+shashmap<obj_type, key_type_, hash_type, alloc_type>::del_elem(key_type_ t_key)
+{
+ pthread_mutex_lock( &mut_shashmap );
+ hashmap<obj_type, key_type_, hash_type, alloc_type>::erase(t_key);
+ pthread_mutex_unlock( &mut_shashmap );
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+void
+shashmap<obj_type, key_type_, hash_type, alloc_type>::del_elem_insecure(key_type_ t_key)
+{
+ hashmap<obj_type, key_type_, hash_type, alloc_type>::erase(t_key);
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+vector<key_type_>*
+shashmap<obj_type, key_type_, hash_type, alloc_type>::get_key_vector()
+{
+ pthread_mutex_lock( &mut_shashmap );
+ vector<key_type_>* p_vec = hashmap<obj_type, key_type_, hash_type, alloc_type>::get_key_vector();
+ pthread_mutex_unlock( &mut_shashmap );
+ return p_vec;
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+void
+shashmap<obj_type, key_type_, hash_type, alloc_type>::clear()
+{
+ pthread_mutex_lock( &mut_shashmap );
+ hashmap<obj_type, key_type_, hash_type, alloc_type>::clear();
+ pthread_mutex_unlock( &mut_shashmap );
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+int
+shashmap<obj_type, key_type_, hash_type, alloc_type>::size()
+{
+ pthread_mutex_lock( &mut_shashmap );
+ int i_size = hashmap<obj_type, key_type_, hash_type, alloc_type>::size();
+ pthread_mutex_unlock( &mut_shashmap );
+ return i_size;
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+bool
+shashmap<obj_type, key_type_, hash_type, alloc_type>::exists(key_type_ t_key)
+{
+ pthread_mutex_lock( &mut_shashmap );
+ bool b_ret = hashmap<obj_type, key_type_, hash_type, alloc_type>::exists(t_key);
+ pthread_mutex_unlock( &mut_shashmap );
+ return b_ret;
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+void
+shashmap<obj_type, key_type_, hash_type, alloc_type>::run_func( void (*func)(obj_type) )
+{
+ pthread_mutex_lock( &mut_shashmap );
+ hashmap<obj_type, key_type_, hash_type, alloc_type>::run_func(func);
+ pthread_mutex_unlock( &mut_shashmap );
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+void
+shashmap<obj_type, key_type_, hash_type, alloc_type>::run_func( void (*func)(obj_type, void*), void* v_arg )
+{
+ pthread_mutex_lock( &mut_shashmap );
+ hashmap<obj_type, key_type_, hash_type, alloc_type>::run_func(func, v_arg);
+ pthread_mutex_unlock( &mut_shashmap );
+}
+
+template<class obj_type, class key_type_, class hash_type, class alloc_type>
+void
+shashmap<obj_type, key_type_, hash_type, alloc_type>::dumpit()
+{
+ dumpable::add
+ ("[shashmap]");
+ vector<key_type_>* p_vec = get_key_vector();
+
+ typename vector<key_type_>::iterator iter;
+ for (iter = p_vec->begin(); iter != p_vec->end(); ++iter)
+ dumpable::add
+ (*iter);
+
+ delete p_vec;
+}
diff --git a/yhttpd/src/monitor/dump.cpp b/yhttpd/src/monitor/dump.cpp
new file mode 100644
index 0000000..c5f51d0
--- /dev/null
+++ b/yhttpd/src/monitor/dump.cpp
@@ -0,0 +1,109 @@
+#ifndef DUMP_CPP
+#define DUMP_CPP
+
+#include "dump.h"
+
+using namespace std;
+
+const string dumpable::s_sep = "->";
+const int dumpable::i_max_level = 100;
+
+dumpable::dumpable()
+{
+ initialize(0);
+}
+
+void
+dumpable::initialize(int i_level)
+{
+ this->i_level = i_level;
+ this->i_lined = i_level;
+ this->b_lined = false;
+ this->b_next_no_nl = false;
+ this->s_dump = "";
+}
+
+string
+dumpable::dump()
+{
+ return dump(0);
+}
+
+string
+dumpable::dump(int i_level)
+{
+ initialize(i_level);
+ dumpit();
+ return s_dump;
+}
+
+void
+dumpable::add
+ (string s_line)
+{
+ if ( i_lined > i_max_level )
+ i_lined = i_max_level;
+
+ if (!b_lined)
+ s_dump.append(s_sep);
+
+ else
+ for ( int i = 0; i < i_lined; ++i )
+ s_dump.append(" ");
+
+ s_dump.append(s_line);
+
+ if (b_next_no_nl)
+ b_next_no_nl = false;
+
+ else
+ s_dump.append("\n");
+
+ if (!b_lined)
+ {
+ b_lined = true;
+ i_lined = i_level + s_sep.length();
+ }
+}
+
+int
+dumpable::get_level() const
+{
+ return i_lined;
+}
+
+dump::dump(vector<string> vec_params)
+{
+ if (vec_params.empty())
+ {
+ cout << CLIPRMO << "all conf sock";
+ cout << endl;
+ return;
+ }
+
+ cout << run(vec_params);
+}
+
+string
+dump::run(vector<string> &vec_params)
+{
+ string s_ret("");
+ string s_part;
+
+ vector<string>::iterator iter;
+ for (iter = vec_params.begin(); iter != vec_params.end(); ++iter)
+ {
+ s_part = *iter;
+
+ if (!s_part.compare("conf") || !s_part.compare("all"))
+ s_ret.append(wrap::CONF->dump());
+
+ if (!s_part.compare("sock") || !s_part.compare("all"))
+ s_ret.append(wrap::SOCK->dump());
+
+ }
+
+ return s_ret;
+}
+
+#endif
diff --git a/yhttpd/src/monitor/dump.h b/yhttpd/src/monitor/dump.h
new file mode 100644
index 0000000..ffb3529
--- /dev/null
+++ b/yhttpd/src/monitor/dump.h
@@ -0,0 +1,62 @@
+#include "../incl.h"
+
+#ifndef DUMP_H
+#define DUMP_H
+
+using namespace std;
+
+class dumpable
+{
+private:
+ int i_level;
+ int i_lined;
+ bool b_lined;
+ bool b_next_no_nl;
+ string s_dump;
+
+ static const string s_sep;
+ static const int i_max_level;
+
+ virtual void dumpit() = 0;
+ void initialize(int i_level);
+ void reset();
+
+protected:
+ void add
+ (unsigned i_num)
+ {
+ add
+ ("<unsigned>");
+ }
+
+ void add
+ (int i_num)
+ {
+ add
+ ("<int>");
+ }
+
+ void add
+ (string s_line);
+ dumpable();
+
+ void next_no_newline()
+ {
+ b_next_no_nl = true;
+ }
+
+public:
+ string dump();
+ string dump(int i_level);
+ int get_level() const;
+};
+
+class dump
+{
+private:
+ string run(vector<string> &vec_params);
+public:
+ dump(vector<string> vec_params);
+};
+
+#endif
diff --git a/yhttpd/src/monitor/stats.cpp b/yhttpd/src/monitor/stats.cpp
new file mode 100644
index 0000000..e0aa146
--- /dev/null
+++ b/yhttpd/src/monitor/stats.cpp
@@ -0,0 +1,102 @@
+#ifndef STATS_CPP
+#define STATS_CPP
+
+#include "stats.h"
+
+using namespace std;
+
+stats::stats()
+{
+ i_rusage_vec_size = tool::string2int(
+ wrap::CONF->get_elem("httpd.stats.rusagehistory"));
+
+
+ pthread_mutex_init( &mut_vec_rusage, NULL );
+
+}
+
+stats::~stats()
+{
+ pthread_mutex_destroy( &mut_vec_rusage );
+}
+
+void
+stats::update_rusage_history()
+{
+ wrap::system_message(STATUPR);
+
+ rusage* p_rusage = new rusage;
+ getrusage( RUSAGE_SELF, p_rusage );
+
+ map<string,long> map_rusage;
+
+ map_rusage["ru_maxrss"] = p_rusage->ru_maxrss;
+ map_rusage["ru_ixrss"] = p_rusage->ru_ixrss;
+ map_rusage["ru_idrss"] = p_rusage->ru_idrss;
+ map_rusage["ru_isrss"] = p_rusage->ru_isrss;
+ map_rusage["ru_minflt"] = p_rusage->ru_minflt;
+ map_rusage["ru_majflt"] = p_rusage->ru_majflt;
+ map_rusage["ru_nswap"] = p_rusage->ru_nswap;
+ map_rusage["ru_inblock"] = p_rusage->ru_inblock;
+ map_rusage["ru_oublock"] = p_rusage->ru_oublock;
+ map_rusage["ru_msgsnd"] = p_rusage->ru_msgsnd;
+ map_rusage["ru_msgrcv"] = p_rusage->ru_msgrcv;
+ map_rusage["ru_nsignals"] = p_rusage->ru_nsignals;
+ map_rusage["ru_nvcsw"] = p_rusage->ru_nvcsw;
+ map_rusage["ru_nivcsw"] = p_rusage->ru_nivcsw;
+
+ delete p_rusage;
+
+ pthread_mutex_lock ( &mut_vec_rusage );
+
+ if ( vec_rusage_history.size() >= i_rusage_vec_size )
+ vec_rusage_history.erase( vec_rusage_history.begin() );
+
+ vec_rusage_history.push_back(map_rusage);
+
+ pthread_mutex_unlock( &mut_vec_rusage );
+}
+
+void
+stats::set_rusage_vec_size( int i_rusage_vec_size )
+{
+ pthread_mutex_lock ( &mut_vec_rusage );
+ this->i_rusage_vec_size = i_rusage_vec_size;
+ pthread_mutex_unlock( &mut_vec_rusage );
+}
+
+long
+stats::get_ru_maxrss()
+{
+ rusage* p_rusage = new rusage;
+ getrusage( RUSAGE_SELF, p_rusage );
+
+ long l_ret = p_rusage->ru_maxrss;
+ delete p_rusage;
+
+ return l_ret;
+}
+
+string
+stats::get_rusage_history( string s_type, string s_seperator )
+{
+ string s_ret;
+ int i_count = 0;
+ vector< map<string,long> >::iterator iter;
+
+ pthread_mutex_lock ( &mut_vec_rusage );
+
+ for ( iter = vec_rusage_history.begin();
+ iter != vec_rusage_history.end();
+ iter++, i_count++ )
+ s_ret.append(s_seperator +
+ tool::int2string(i_count) + ". " + iter->find(s_type)->first + " " +
+ tool::int2string( iter->find(s_type)->second) + "\n");
+
+ pthread_mutex_unlock( &mut_vec_rusage );
+
+ return s_ret;
+}
+
+
+#endif
diff --git a/yhttpd/src/monitor/stats.h b/yhttpd/src/monitor/stats.h
new file mode 100644
index 0000000..0478258
--- /dev/null
+++ b/yhttpd/src/monitor/stats.h
@@ -0,0 +1,36 @@
+#include "../incl.h"
+
+#ifndef STATS_H
+#define STATS_H
+
+#include "../tool/tool.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+using namespace std;
+
+class stats
+{
+private:
+ // Specifies the max. amount of elements in vec_rusage_history;
+ int i_rusage_vec_size;
+ // History of the last i_rusage_vec_size rusage values.
+ vector< map<string,long> > vec_rusage_history;
+ pthread_mutex_t mut_vec_rusage;
+
+
+ void set_rusage_vec_size( int i_rusage_vec_size );
+
+public:
+ stats( );
+ ~stats( );
+
+ void update_rusage_history();
+ string get_rusage_history( string s_type, string s_seperator );
+ long get_ru_maxrss();
+};
+
+#endif
diff --git a/yhttpd/src/msgs.h b/yhttpd/src/msgs.h
new file mode 100644
index 0000000..fdfb68c
--- /dev/null
+++ b/yhttpd/src/msgs.h
@@ -0,0 +1,145 @@
+#ifndef MSGS_H
+#define MSGS_H
+
+// alphabetical ordered:
+#define ACCPERR "Sock: Accept error "
+#define BINDERR "Sock: Bind error "
+#define HTTPDREP "Chat: Using replacement strings"
+#define HTTPDDOP "Chat: Default operator login "
+#define HTTPDFLO "Chat: Flooding ("
+#define CFILEOK "Parsing config file"
+#define CFILEFA "Failed opening config file!"
+#define CONTACT "Contact: http://www.yChat.org, Mail@yChat.org, ICQ: 11655527"
+#define CLRHTML "HTML: Cleared the document cache "
+#define CLIWELC "Command Line Interface (type help for a list of all commands)"
+#define CLIPRMO ">> "
+#define CLIPRMI "<< "
+#define CLIHELP "Unknown command (use help)"
+#define CLIMSQL "Spawing system mysql client (enter exit to return)"
+#define CLISHEL "Spawing system shell (enter exit to return)"
+#define DATAADD "Data: Adding used connection into the queue"
+#define DATADIS "Data: Closing all connections"
+#define DATADI2 "Data: Closing idle connection ("
+#define DATAQUE "Data: "
+#define DATAGET "Data: Using database connection queue "
+#define DATAIN0 "Data: Initializing maxcon to "
+#define DATAIN1 "Data: Initializing mincon to "
+#define DATAMAX "Data: Max database connections reached "
+#define DATAMA0 "Data: Max database connections "
+#define DATANEW "Data: Creating new database connection "
+#define DESCRIP "Copyright (C) 2003 Paul C. Buetow, Volker Richter"
+#define DESCRI2 "Copyright (C) 2004, 2005 Paul C. Buetow"
+#define DONEMSG "done"
+#define DOWNMSG "Shutting down "
+#define GARBAGE "Garbage: Initializing collector "
+#define GARBACT "Garbage collector activated "
+#define GAROFFNE "Garbage: No garbage to remove available "
+#define GARROOM "Garbage: Added room "
+#define GARUSER "Garbage: Added user "
+#define GARUSE2 "Garbage: Recycle user "
+#define LISTERR "Sock: Listen error "
+#define LOGGINI "Logging: Init on "
+#define LOGERR1 "Logging: Could not open logfile "
+#define LOGERR2 "Logging: No filename specified "
+#define LOGINER "Chat: Login failed (password), nick: "
+#define LOGINE0 "Chat: Login failed (empty nick)"
+#define LOGINE1 "Chat: Login failed (alpha nick), nick: "
+#define LOGINE2 "Chat: Login failed (nick length), nick: "
+#define LOGINE3 "Chat: Login failed (room length), nick/room: "
+#define LOGINE4 "Chat: Login failed (guests disabled), nick: "
+#define LOGINE5 "Chat: Login failed (not enough threads), nick: "
+#define MODULEC "Modl: Caching "
+#define MODULER "Modl: Requesting "
+#define MODUNLO "Modl: Unloading all modules "
+#define MODRELO "Modl: Reloading all modules "
+
+#ifdef DATABASE
+#define MYSQLQU "MySQL: "
+#define MYSQLQ2 "MySQL: Adding query "
+#define MYSQLE1 "MySQL: Error running mysql_init "
+#endif
+
+#ifdef CTCSEGV
+#define SIGNSEG "Signal: Received SIGSEGV"
+#endif
+
+#define NCURADM "ADMINISTRATOR's MAIN MENU"
+#define NCURMSG "SERVER SYSTEM MESSAGES"
+#define NCURSE0 "HTTP server: "
+#define NCURSE1 "Thread pool: "
+#define NCURSE2 "Data stats: "
+#define NCURSE3 "Chat stats: "
+#define NCURSE4 "Caching: "
+#define NEWREQU "Sock: New request "
+#define NEWROOM "Chat: New room "
+#define NEWUSER "Chat: New user "
+#define OFFFOUND "HTML: File not found "
+#define PERMSTD "Reading standard command exec permissions"
+#define POOLER1 "Pool: Did not allocate all threads ("
+#define POOLER2 "Pool: Max pool size reached ("
+#define POOLFLL "Pool: Allocating new threads ("
+#define READERR "Sock: Read error "
+#define REMROOM "Garbage: Removing room "
+#define REMUSER "Garbage: Removing user "
+#define REQUEST "Reqp: Request string "
+#define SELCERR "Sock: Select error "
+#define SEPERAT "-----------------------"
+#define SESSION "Session: Count "
+#define SESSDMP "Session: Dump of session"
+#define SESSERR "Session: Could not find session "
+#define SESSEXI "Session: New TempID already exists, recalc."
+#define SHELLER "Shell: Could not execute command"
+#define SHELLEX "Shell: Executing the following command:"
+#define SIGSIGV "Signal: SIGV received!"
+#define STATUPR "Stats: Updated rusage history"
+#define STATRSS "Stats: Max resident set size "
+#define REUROOM "Garbage: Reusing room object "
+#define SOCKCLN "Sock: Initializing a client socket at "
+#define SOCKCON "Sock: Connecting to "
+#define SOCKCRT "Sock: Created socket on "
+#define SOCKSRV "Sock: Initializing server socket "
+#define SOCKERR "Sock: Can't create socket, trying next port "
+#define SOCKER1 "Sock: Can't create socket, aborting"
+#define SOCKER2 "Sock: Unknown hostname "
+#define SOCKRDY "Sock: Server socket is ready "
+#define SOCKCAC "Sock: Caching IP "
+#define SOCKCA2 "Sock: Cleaning IP cache ("
+#define SOCKUNS "Sock: Starting unsecure transport [HTTP]"
+#ifdef OPENSSL
+#define SSLERR1 "SSL: Can't create socket"
+#define SSLERR2 "SSL: Private key does not match cert. file"
+#define SSLERR3 "SSL: Can't create new SSL context"
+#define SSLERR4 "SSL: Can't create new SSL socket via accept"
+#define SOCKSEC "SSL: Starting secure transport [HTTPS]"
+#endif
+#define TECACHE "HTML: Caching document "
+#define THRDSTR "Thread: Running"
+#define TIMERAT "Timer: User autoaway timeout "
+#define TIMERIN "Timer: Initializing "
+#define TIMEROF "Timer: Setting offset to "
+#define TIMERTH "Timer: Starting timer thread "
+#define TIMERTO "Timer: User logout timeout "
+#define TIMERUP "Timer: System uptime "
+#define XMLREAD "XML: Reading "
+#define XMLERR "XML Error: "
+#define XMLER1 "XML Error: Unable to load file "
+#define VERSION "0.8"
+#define BRANCH "CURRENT"
+#define BUILDNR 4003
+#define UNAME "FreeBSD 5.4-DEVEL-p3 i386"
+#define COMPOPT "Using built-in specs.; Configured with: FreeBSD/i386 system compiler; Thread model: posix; gcc version 3.4 [FreeBSD] 20040728; 3.4; g++"
+#define YCUSAGE "Usage: ./yhttpd {h|v}|{o confkey confvalue}\n"
+
+#define HEADER1 "HTTP/1.1 200 OK\r\n"
+#define HEADER2 "Server: yhttpd/" VERSION "-" BRANCH "\r\n"
+#define HEADER3 "Cache-Control: no-cache\r\n"
+#define HEADER4 "Pragma: no-cache\r\n"
+#define HEADER5 "Transfer-Encoding: chunked\r\n"
+#define HEADER6 "Connection: keep-alive\r\n"
+#define HEADER7 "Content-Length: ";
+#define HEADER8 "Content-Type: ";
+#define HEADER8b "; charset=ISO-8859-1\r\n";
+#define HEADER9 "Allow: GET\r\n";
+//#define MEMBERE "Memb: No such member "
+
+#endif
diff --git a/yhttpd/src/name.cpp b/yhttpd/src/name.cpp
new file mode 100644
index 0000000..79167f5
--- /dev/null
+++ b/yhttpd/src/name.cpp
@@ -0,0 +1,49 @@
+#ifndef NAME_CPP
+#define NAME_CPP
+
+#include "name.h"
+#include "tool/tool.h"
+
+using namespace std;
+
+name::name()
+{
+ pthread_mutex_init( &mut_s_name, NULL);
+}
+
+name::name( string s_name )
+{
+ pthread_mutex_init( &mut_s_name, NULL);
+ set_name( s_name );
+}
+
+name::~name()
+{
+ pthread_mutex_destroy( &mut_s_name );
+}
+
+string
+name::get_name()
+{
+ string s_ret;
+ pthread_mutex_lock ( &mut_s_name );
+ s_ret = s_name;
+ pthread_mutex_unlock( &mut_s_name );
+ return s_ret;
+}
+
+string
+name::get_lowercase_name()
+{
+ return tool::to_lower( get_name() );
+}
+
+void
+name::set_name( string s_name )
+{
+ pthread_mutex_lock ( &mut_s_name );
+ this->s_name = s_name;
+ pthread_mutex_unlock( &mut_s_name );
+}
+
+#endif
diff --git a/yhttpd/src/name.h b/yhttpd/src/name.h
new file mode 100644
index 0000000..0a62c1f
--- /dev/null
+++ b/yhttpd/src/name.h
@@ -0,0 +1,24 @@
+#include "incl.h"
+
+#ifndef NAME_H
+#define NAME_H
+
+using namespace std;
+
+class name
+{
+protected:
+ string s_name; // object's name.
+ pthread_mutex_t mut_s_name;
+
+public:
+ virtual string get_name ( );
+ virtual string get_lowercase_name ( );
+ virtual void set_name ( string s_name );
+
+ name();
+ name( string s_name ); // a standard constructor.
+ ~name();
+};
+
+#endif
diff --git a/yhttpd/src/ncur/menu.cpp b/yhttpd/src/ncur/menu.cpp
new file mode 100644
index 0000000..dcacc9b
--- /dev/null
+++ b/yhttpd/src/ncur/menu.cpp
@@ -0,0 +1,117 @@
+
+#include "menu.h"
+
+#ifdef NCURSES
+
+#ifndef MENU_CPP
+#define MENU_CPP
+
+using namespace std;
+
+menu::menu( int i_startx, int i_starty, int i_width, int i_height, char *c_header, char **choices, int i_numchoices, const chtype ch )
+{
+ this->i_startx = i_startx;
+ this->i_starty = i_starty;
+ this->i_height = i_height;
+ this->i_width = i_width;
+ this->c_header = c_header;
+ this->choices = choices;
+ this->i_numchoices = i_numchoices;
+
+ initialize( ch );
+}
+
+menu::~menu()
+{
+ /*
+ wborder(win, ' ', ' ', ' ',' ',' ',' ',' ',' ');
+ wrefresh(win);
+ delwin(win);
+ */
+}
+
+void
+menu::initialize( const chtype ch )
+{
+ this->i_highlight = 1;
+ this->i_choice = 0;
+
+ win = newwin( i_height, i_width, i_starty, i_startx );
+ wbkgd(win, ch);
+}
+
+void
+menu::display()
+{
+ int x, y, i;
+
+ x = 2;
+ y = 2;
+
+ box( win, 0, 0 );
+ mvwprintw( win, y++, x, "%s", c_header );
+
+ for( i = 0; i < i_numchoices; i++ )
+ {
+ ++y;
+
+ if( i_highlight == i+1 ) // Highlight the current selection.
+ {
+ wattron( win, A_REVERSE);
+ mvwprintw( win, y, x, "%d. %s", i, choices[i]);
+ wattroff( win, A_REVERSE);
+ } else
+ {
+ mvwprintw( win, y, x, "%d. %s", i, choices[i]);
+ }
+ }
+
+ wrefresh( win );
+}
+
+void
+menu::start( void (*swich_case_menu_action)(int) )
+{
+ refresh();
+ bool b_flag = 1;
+
+ while( b_flag )
+ {
+ keypad(win, 1);
+ display();
+ c = wgetch( win );
+
+ switch(c)
+ {
+ case KEY_UP:
+ if( i_highlight == 1 )
+ i_highlight = i_numchoices;
+ else
+ --i_highlight;
+ break;
+
+ case KEY_DOWN:
+ if( i_highlight == i_numchoices )
+ i_highlight = 1;
+ else
+ ++i_highlight;
+ break;
+
+ case 10:
+ i_choice = i_highlight;
+ break;
+
+ default:
+ mvprintw( NCUR_MENU_CHAR_X, NCUR_MENU_CHAR_Y, "%3d %c ", c, c);
+ refresh();
+ break;
+ }
+
+ // Menu action.
+ ( *swich_case_menu_action ) ( i_choice );
+ i_choice = 0;
+ }
+}
+
+#endif
+#endif
diff --git a/yhttpd/src/ncur/menu.h b/yhttpd/src/ncur/menu.h
new file mode 100644
index 0000000..af7dbe9
--- /dev/null
+++ b/yhttpd/src/ncur/menu.h
@@ -0,0 +1,39 @@
+#include "../incl.h"
+
+#ifdef NCURSES
+
+#ifndef MENU_H
+#define MENU_H
+
+#include <ncurses.h>
+
+using namespace std;
+
+class menu
+{
+private:
+ char **choices;
+ char *c_header;
+
+ int i_startx, i_starty, i_width, i_height, i_highlight, i_choice,
+ i_numchoices, c;
+
+ WINDOW *win;
+
+ void initialize( const chtype ch );
+
+public:
+ explicit menu( int i_startx, int i_starty, int i_width, int i_height, char *c_header, char **choices, int i_numchoices, const chtype ch );
+ ~menu( );
+
+ void display();
+ void start( void (*swich_case_menu_action)(int) );
+
+ void activate_menu_win()
+ {
+ keypad(win, 1);
+ }
+};
+
+#endif
+#endif
diff --git a/yhttpd/src/ncur/ncur.cpp b/yhttpd/src/ncur/ncur.cpp
new file mode 100644
index 0000000..41bfdac
--- /dev/null
+++ b/yhttpd/src/ncur/ncur.cpp
@@ -0,0 +1,259 @@
+#ifndef NCUR_CPP
+#define NCUR_CPP
+
+#include "ncur.h"
+
+#ifdef CLI
+#include "../cli/cli.h"
+#endif
+#include "../sign.h"
+
+using namespace std;
+
+#ifdef NCURSES
+
+const string GMAKE_PARAMS[] =
+ { "clean_base", "clean_modules", "all"
+ };
+const int GMAKE_ELEMENTS = 3;
+
+ncur::ncur( )
+{
+ p_messagelist = new list<char*>;
+ pthread_mutex_init( &mut_messages, NULL );
+ pthread_mutex_init( &mut_is_ready, NULL );
+ i_message_length = 45;
+ b_is_ready = false;
+}
+
+ncur::~ncur()
+{
+ pthread_mutex_destroy( &mut_messages );
+ pthread_mutex_destroy( &mut_is_ready );
+}
+
+void
+ncur::start( void *p_void )
+{
+ ncur::init_ncurses();
+
+ char *choices[] = {
+ " ",
+ " ",
+ "Clear template cache ",
+ " ",
+ "Show max res. set size ",
+ "Compile changed sources ",
+ "Recompile all sources ",
+ "Show source stats ",
+ "Command line interface ",
+ " ",
+ "Shut down server"
+ };
+
+ p_serveroutput = newwin( 19, 49, 1, 31 );
+ wbkgd(p_serveroutput, COLOR_PAIR(1));
+
+ box ( p_serveroutput, 0, 0 );
+ mvwprintw( p_serveroutput, 2, 2, NCURMSG );
+ wrefresh ( p_serveroutput );
+
+ print( string("yhttpd ") + VERSION );
+
+
+ p_menu = new menu( 1, 1, 30, 19, NCURADM, choices, 11, COLOR_PAIR(1));
+
+ mvprintw(NCUR_SERVER_HEADER_X,NCUR_SERVER_HEADER_Y, NCURSE0);
+ mvprintw(NCUR_POOL_HEADER_X,NCUR_POOL_HEADER_Y, NCURSE1);
+ mvprintw(NCUR_CACHED_HEADER_X,NCUR_CACHED_HEADER_Y, NCURSE4);
+
+ wrap::HTML->print_cached(0);
+
+ is_ready(true);
+ wrap::SOCK->print_server_port();
+
+ p_menu->start( &switch_main_menu_ );
+
+ shutdown();
+}
+
+void
+ncur::shutdown()
+{
+ ncur::close_ncurses();
+}
+
+
+void
+ncur::print( string *p_msg )
+{
+ print( *p_msg );
+}
+
+void
+ncur::print( string s_msg )
+{
+ print( (char*)s_msg.c_str() );
+}
+
+void
+ncur::print( char* c_print )
+{
+ // Removing \n
+ if ( strlen(c_print) > i_message_length )
+ {
+ string s_tmp(c_print);
+ print( s_tmp.substr( 0, i_message_length ) );
+ print( s_tmp.substr( i_message_length, s_tmp.length()-i_message_length ) );
+ return;
+ }
+
+ int i;
+ char* c_temp = new char[i_message_length];
+ memcpy( c_temp, c_print, strlen(c_print) );
+
+ for ( i = strlen(c_print); i < i_message_length; ++i )
+ c_temp[i] = ' ';
+
+ c_temp[i] = '\0';
+
+ pthread_mutex_lock( &mut_messages );
+
+ if ( p_messagelist->size() > 12 )
+ {
+ char* c_front = p_messagelist->front();
+ p_messagelist->pop_front();
+ free(c_front);
+ }
+
+ p_messagelist->push_back( c_temp );
+
+
+ if ( is_ready() )
+ {
+ list<char*>::iterator iter;
+ iter = p_messagelist->begin();
+
+ for ( i = 4; i < 18 && iter != p_messagelist->end(); ++i, ++iter )
+ mvwprintw( p_serveroutput, i, 2, *iter );
+
+ wrefresh ( p_serveroutput );
+ }
+
+ pthread_mutex_unlock( &mut_messages );
+}
+
+void
+ncur::switch_main_menu_( int i_choice )
+{
+ int i;
+
+ if( i_choice != 0 )
+ switch ( i_choice )
+ {
+ case 3:
+ wrap::HTML->clear_cache();
+ mvprintw( 20,2, "Cleared the template cache ");
+ refresh();
+ break;
+ case 4:
+ refresh();
+ break;
+ case 5:
+ mvprintw( 20,2, "Showing max resident set size in memory ");
+ wrap::NCUR->print( STATRSS + string("(") + tool::int2string(
+ wrap::STAT->get_ru_maxrss()) + string(")"));
+ break;
+ case 6:
+ tool::shell_command( string(GMAKE), METH_NCURSES);
+ break;
+ case 7:
+ for ( i = 0; i < GMAKE_ELEMENTS; i++ )
+ tool::shell_command( GMAKE + GMAKE_PARAMS[i], METH_NCURSES);
+ break;
+ case 8:
+ tool::shell_command( string(GMAKE) + " stats", METH_NCURSES);
+ break;
+ case 9:
+#ifdef CLI
+
+ wrap::NCUR->is_ready(false);
+ refresh(); /* Print it on to the real screen */
+
+ def_prog_mode(); /* Save the tty modes */
+ endwin(); /* End curses mode temporarily */
+ delete new cli(); /* Start CLI mode */
+ reset_prog_mode(); /* Return to the previous tty mode*/
+ /* stored by def_prog_mode() */
+ refresh(); /* Do refresh() to restore the */
+ /* Screen contents */
+ wrap::NCUR->is_ready(true);
+ wrap::NCUR->activate_menu_win();
+#else
+
+ mvprintw( 20,2, "CLI mode has not been compiled in! ");
+#endif
+
+ break;
+ case 10:
+#ifdef DATABASE
+
+#endif
+
+ break;
+
+ case 11: // Shut down server
+ sign::terminate_received(0);
+ break;
+
+ default:
+ mvprintw( 20,2, "Selection # %d not yet implemented!", i_choice-1);
+ wrap::NCUR->print( "Selection not yet implemented!" );
+ refresh();
+ break;
+ }
+}
+
+void
+ncur::init_ncurses()
+{
+ initscr();
+ start_color();
+ clear();
+ noecho();
+ cbreak(); // Line buffering disabled. pass on everything
+ init_pair(1, COLOR_BLACK, COLOR_CYAN);
+ mvprintw( 0,2, (char*)(tool::yhttpd_version()).c_str());
+ curs_set(0);
+ refresh();
+}
+
+void
+ncur::close_ncurses()
+{
+ refresh();
+ clrtoeol();
+ refresh();
+ endwin();
+}
+
+void
+ncur::is_ready( bool b_is_ready )
+{
+ pthread_mutex_lock( &mut_is_ready );
+ this->b_is_ready = b_is_ready;
+ pthread_mutex_unlock( &mut_is_ready );
+}
+
+bool
+ncur::is_ready()
+{
+ bool b_ret;
+ pthread_mutex_lock( &mut_is_ready );
+ b_ret = b_is_ready;
+ pthread_mutex_unlock( &mut_is_ready );
+ return b_ret;
+}
+
+#endif
+#endif
diff --git a/yhttpd/src/ncur/ncur.h b/yhttpd/src/ncur/ncur.h
new file mode 100644
index 0000000..1830cdf
--- /dev/null
+++ b/yhttpd/src/ncur/ncur.h
@@ -0,0 +1,51 @@
+#include "../incl.h"
+
+#ifdef NCURSES
+
+#ifndef NCUR_H
+#define NCUR_H
+
+#include <ncurses.h>
+#include <list>
+
+#include "menu.h"
+#include "../thrd/thro.h"
+
+using namespace std;
+
+class ncur : public thro
+{
+private:
+ friend class sign;
+ menu* p_menu;
+ WINDOW* p_serveroutput;
+ list<char*>* p_messagelist; // contains the messages for p_serveroutput!
+ int i_message_length; // the maximum length of a system message!
+ bool b_is_ready; // is set to TRUE if the admin interface is initialized.
+ static void init_ncurses();
+ static void close_ncurses();
+
+ pthread_mutex_t mut_messages;
+ pthread_mutex_t mut_is_ready;
+
+public:
+ ncur();
+ ~ncur();
+
+ void start( void *p_void );
+ void print( char* c_print );
+ void print( string s_msg );
+ void print( string* p_msg );
+ void is_ready( bool b_is_ready );
+ bool is_ready();
+ static void switch_main_menu_( int i_choice );
+ void shutdown();
+
+ void activate_menu_win()
+ {
+ p_menu->activate_menu_win();
+ }
+};
+
+#endif
+#endif
diff --git a/yhttpd/src/reqp.cpp b/yhttpd/src/reqp.cpp
new file mode 100644
index 0000000..df9de5d
--- /dev/null
+++ b/yhttpd/src/reqp.cpp
@@ -0,0 +1,285 @@
+#ifndef REQP_CPP
+#define REQP_CPP
+
+#include "reqp.h"
+#include "tool/tool.h"
+
+using namespace std;
+
+#define HEADER HEADER1 HEADER2 HEADER3 HEADER4 HEADER9
+#define STREAM HEADER5 HEADER6
+
+const string reqp::s_http = HEADER;
+const string reqp::s_http_stream = STREAM;
+const string reqp::s_http_colength = HEADER7;
+const string reqp::s_http_cotype = HEADER8;
+const string reqp::s_http_cotype_add = HEADER8b;
+
+reqp::reqp( )
+{}
+
+void
+reqp::get_request_parameters( string s_parameters, map<string,string>& map_params )
+{
+ string s_tmp;
+ unsigned i_pos, i_pos2;
+
+ while( (i_pos = s_parameters.find("&")) != string::npos )
+ {
+ s_tmp = s_parameters.substr(0, i_pos );
+
+ if ( (i_pos2 = s_tmp.find("=")) != string::npos )
+ map_params[ s_tmp.substr(0, i_pos2) ] = tool::replace( s_tmp.substr( i_pos2+1 ), "\\AND", "&");
+
+ s_parameters = s_parameters.substr( i_pos + 1 );
+ }
+
+ // Get the last request parameter, which does not have a "&" on the end!
+ if( (i_pos = s_parameters.find("=")) != string::npos )
+ map_params[ s_parameters.substr(0, i_pos) ] = s_parameters.substr( i_pos+1 );
+
+ //map<string,string>::iterator iter;
+ //for ( iter = map_params.begin(); iter != map_params.end(); ++iter )
+ //cout << ">>>" << iter->first << "=" << iter->second << endl;
+}
+
+string
+reqp::get_url( string s_req, map<string, string> &map_params, int& i_postpayloadoffset )
+{
+ unsigned i_pos, i_pos2;
+ string s_vars( "" );
+ string s_ret;
+ int i_req;
+
+ // GET request
+ if ( s_req.find("GET") != string::npos)
+ {
+ // Be sure that the GET request has minimum length
+ if ( s_req.length() > 5 )
+ {
+ // Get rid of "GET /"
+ if ( (i_pos = s_req.find("\n")) == string::npos )
+ i_pos = s_req.length() - 1;
+
+ s_req = s_req.substr(5, i_pos - 5);
+
+ // Get HTML site to be displayed
+ if ( (i_pos = s_req.find("?")) == string::npos )
+ {
+ if ( (i_pos2 = s_req.find(" HTTP")) != string::npos )
+ s_ret = url_decode( s_req.substr(0, i_pos2));
+ }
+ else
+ {
+ s_ret = url_decode( s_req.substr(0, i_pos) );
+
+ // Get request parameters:
+ if ( (i_pos2 = s_req.find(" HTTP")) != string::npos )
+ {
+ s_req = url_decode( s_req.substr(i_pos + 1, i_pos2 - i_pos - 1) );
+ get_request_parameters( s_req, map_params );
+ }
+ }
+
+ }
+ }
+
+ // POST request
+ else
+ {
+ if ( (i_pos2 = s_req.find("HTTP")) != string::npos )
+ {
+ if (i_pos2 > 13)
+ {
+ s_ret = url_decode( s_req.substr(6,i_pos2-7) );
+
+ //wrap::system_message(s_req);
+ //wrap::system_message(string("data offset=") + tool::int2string(i_postpayloadoffset));
+ i_pos = s_req.find("event=",i_postpayloadoffset );
+ if(i_pos != string::npos)
+ {
+ get_request_parameters( url_decode( s_req.substr(i_pos) ), map_params);
+ }
+ }
+ }
+
+ }
+
+#ifdef VERBOSE
+ wrap::system_message( REQUEST + s_ret );
+#endif
+
+ if ( s_ret.empty() )
+ s_ret = wrap::CONF->get_elem( "httpd.startsite" );
+
+ else
+ s_ret = remove_dots(s_ret);
+
+ map_params["request"] = s_ret;
+
+ return s_ret;
+}
+
+string
+reqp::get_content_type(string &s_file)
+{
+ string s_ext(tool::get_extension( s_file ));
+
+ if( s_ext == "" )
+ s_ext = "default";
+
+ return wrap::CONF->get_elem( "httpd.contenttypes." + s_ext );
+}
+
+void
+reqp::parse_headers( string s_req, map<string,string> &map_params )
+{
+ int pos = s_req.find("\n");
+
+ if (pos != string::npos)
+ {
+ map_params["QUERY_STRING"] = tool::trim(s_req.substr(0,pos-1));
+
+ int pos2;
+ do
+ {
+ string s_line( s_req.substr(0, pos) );
+ pos2 = s_line.find(":");
+
+ if (pos2 != string::npos && s_line.length() > pos2+1)
+ map_params[ tool::trim(s_line.substr(0, pos2)) ] = tool::trim(s_line.substr(pos2+1));
+
+ s_req = s_req.substr( s_line.size() + 1 );
+ pos = s_req.find("\n");
+ }
+ while( pos != string::npos);
+ } // if
+}
+
+int
+reqp::htoi(string *p_str)
+{
+ int value, c;
+ c = p_str->at(0);
+
+ if( isupper(c) )
+ c = tolower(c);
+
+ value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
+
+ c = p_str->at(1);
+
+ if( isupper(c) )
+ c = tolower(c);
+
+ value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
+
+ return value;
+}
+
+string
+reqp::url_decode( string s_url )
+{
+ string s_dest = "";
+ int i_len = s_url.size();
+ int i_prv = i_len - 2;
+
+ char c;
+ for( int i = 0; i < i_len; ++i)
+ {
+ c = s_url.at(i);
+ if( c == '+' )
+ {
+ s_dest += " ";
+ }
+ else if (c == '%' && i < i_prv)
+ {
+ string s_tmp = s_url.substr(i+1, 2);
+ c = (char) htoi(&s_tmp);
+ s_dest += c;
+ i += 2;
+ }
+ else
+ {
+ s_dest += c;
+ }
+ }
+
+ return s_dest;
+}
+
+string
+reqp::get_from_header( string s_req, string s_hdr )
+{
+ unsigned i_pos[2];
+ if ( (i_pos[0] = s_req.find( s_hdr, 0 )) == string::npos )
+ return "";
+
+ if ( (i_pos[1] = s_req.find( "\n", i_pos[0]) ) == string::npos )
+ return "";
+
+ unsigned i_len = s_hdr.length();
+ return s_req.substr( i_pos[0] + i_len, i_pos[1] - i_pos[0] - i_len - 1 );
+}
+
+string
+reqp::parse( socketcontainer *p_sock, string s_req, map<string,string> &map_params, int &i_postpayloadoffset )
+{
+
+ // store all request informations in map_params. store the url in
+ // map_params["request"].
+ get_url( s_req, map_params, i_postpayloadoffset );
+
+ parse_headers( s_req, map_params );
+ string s_event( map_params["event"] );
+
+ map_params["content-type"] = get_content_type( map_params["request"] );
+
+ string s_rep( "" );
+
+
+ if ( wrap::CONF->get_elem("httpd.enablecgi").compare("true") == 0 &&
+ string::npos != map_params["request"].find(".cgi") )
+ {
+ s_rep.append( tool::shell_command(
+ wrap::CONF->get_elem("httpd.templatedir") + map_params["request"],
+ METH_RETSTRING ) );
+ }
+ else
+ {
+ // parse and get the requested html-template and also use
+ // the values stored in map_params for %%KEY%% substituations.
+ s_rep.append( wrap::HTML->parse( map_params ) );
+ }
+
+ // create the http header.
+
+ string s_resp(s_http);
+ if ( s_event.compare("stream") == 0 )
+ s_resp.append( s_http_stream );
+
+ s_resp.append( s_http_colength + tool::int2string(s_rep.size()) + "\r\n" +
+ s_http_cotype + map_params["content-type"] +
+ s_http_cotype_add + "\r\n" );
+
+ s_resp.append(s_rep);
+
+
+ // return the parsed html-template.
+ return s_resp;
+}
+
+
+string
+reqp::remove_dots( string s_ret )
+{
+ // remove ".." from the request.
+ unsigned i_pos;
+
+ if ( (i_pos = s_ret.find( ".." )) != string::npos )
+ return remove_dots(s_ret.substr(0, i_pos));
+
+ return s_ret;
+}
+
+#endif
diff --git a/yhttpd/src/reqp.h b/yhttpd/src/reqp.h
new file mode 100644
index 0000000..93e32e4
--- /dev/null
+++ b/yhttpd/src/reqp.h
@@ -0,0 +1,41 @@
+#include "incl.h"
+#ifndef REQP_H
+#define REQP_H
+
+#include "maps/hashmap.h"
+
+using namespace std;
+
+class reqp
+{
+private:
+ static const string s_http;
+ static const string s_http_stream;
+ static const string s_http_colength;
+ static const string s_http_cotype;
+ static const string s_http_cotype_add;
+
+ // returns the request url from thr client's http request header
+ // until the first "?" and stores all request parameter values
+ // ( behind "?" ) into map_params.
+ string get_url( string s_req, map<string,string> &map_params, int& i_postpayloadoffset );
+ // returns a specific value of the client's http request header.
+ // ( s.t. like the User-Agent, Referer etc... ).
+ string get_from_header( string s_req, string s_hdr );
+
+ int htoi( string *p_str );
+ // Removes double dots ".."
+ string remove_dots( string s_req );
+
+ // Parses "event=bla?blu=bli&sadasda=asddds ..." string and stores them in the map
+ void get_request_parameters( string s_parameters, map<string,string>& map_params );
+
+public:
+ reqp( );
+ string parse( socketcontainer* p_sock, string s_req, map<string,string> &map_params, int &i_postpayloadoffset );
+ string url_decode ( string s_url );
+ string get_content_type( string& s_file );
+ void parse_headers( string s_req, map<string,string> &map_params );
+};
+
+#endif
diff --git a/yhttpd/src/sign.cpp b/yhttpd/src/sign.cpp
new file mode 100644
index 0000000..efb28d7
--- /dev/null
+++ b/yhttpd/src/sign.cpp
@@ -0,0 +1,54 @@
+#ifndef SIGN_CPP
+#define SIGN_CPP
+
+#include "sign.h"
+
+void
+sign::clean_template_cache(int i_param)
+{
+ wrap::HTML->clear_cache();
+}
+
+
+#ifdef CTCSEGV
+void
+sign::sigsev_received(int i_param)
+{
+ wrap::system_message(SIGNSEG);
+}
+#endif
+
+void
+sign::terminate_received(int i_param)
+{
+
+#ifdef NCURSES
+
+ mvprintw( 21,2, "Good bye !");
+ wrap::NCUR->close_ncurses();
+
+#endif
+
+ exit(0);
+}
+
+void
+sign::init_signal_handlers()
+{
+ // Ignore SIGPIPE. otherwise the server will shut down with "Broken pipe" if
+ // a client unexpected disconnects himself from a SOCK_STREAM.
+ signal(SIGPIPE, SIG_IGN);
+
+ signal(SIGUSR1, clean_template_cache);
+#ifdef CTCSEGV
+
+ signal(SIGSEGV, sigsev_received);
+#endif
+
+ signal(SIGHUP, terminate_received);
+ signal(SIGINT, terminate_received);
+ signal(SIGTERM, terminate_received);
+ //signal(SIGWINCH, );
+}
+
+#endif
diff --git a/yhttpd/src/sign.h b/yhttpd/src/sign.h
new file mode 100644
index 0000000..a8ec1e1
--- /dev/null
+++ b/yhttpd/src/sign.h
@@ -0,0 +1,21 @@
+#ifndef SIGN_H
+#define SIGN_H
+
+#include "incl.h"
+#include <signal.h>
+
+class sign
+{
+private:
+ static void clean_template_cache(int i_param);
+#ifdef CTCSEGV
+
+ static void sigsev_received(int i_param);
+#endif
+
+public:
+ static void init_signal_handlers();
+ static void terminate_received(int i_param);
+};
+
+#endif
diff --git a/yhttpd/src/sock/sock.cpp b/yhttpd/src/sock/sock.cpp
new file mode 100644
index 0000000..5ae0be1
--- /dev/null
+++ b/yhttpd/src/sock/sock.cpp
@@ -0,0 +1,473 @@
+#ifndef SOCK_CPP
+#define SOCK_CPP
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "sock.h"
+
+using namespace std;
+
+sock::sock()
+{
+ this->b_run = true;
+ this->i_req = 0;
+ this->req_parser = new reqp();
+#ifdef LOGGING
+
+ this->log_daemon = new logd( wrap::CONF->get_elem( "httpd.logging.accessfile" ),
+
+ wrap::CONF->get_elem( "httpd.logging.access_lines" ) );
+#endif
+}
+
+int
+sock::_send(socketcontainer *p_sock, const char *sz, int len)
+{
+
+ return send( p_sock->i_sock, sz, len, 0 );
+}
+
+int
+sock::_read(socketcontainer *p_sock, char *sz, int len)
+{
+
+ return read( p_sock->i_sock, sz, len );
+}
+
+int
+sock::_close(socketcontainer *p_sock)
+{
+ shutdown( p_sock->i_sock, 2 );
+ close ( p_sock->i_sock );
+ delete p_sock;
+}
+
+
+int
+sock::_make_server_socket( int i_port )
+{
+ size_t i_sock;
+ struct sockaddr_in name;
+
+ // create the server socket.
+ i_sock = socket (PF_INET, SOCK_STREAM, 0);
+ if (i_sock < 0)
+ {
+ wrap::system_message( SOCKERR );
+
+ if ( ++i_port > MAXPORT )
+ exit(1);
+
+ wrap::system_message( SOCKERR );
+
+ return _make_server_socket( i_port );
+ }
+
+ // give the server socket a name.
+ name.sin_family = AF_INET;
+ name.sin_port = htons(i_port);
+ name.sin_addr.s_addr = htonl(INADDR_ANY);
+ int i_optval = 1;
+
+ setsockopt( i_sock, SOL_SOCKET, SO_REUSEADDR, (char*)&i_optval, sizeof(int) );
+
+ if ( bind(i_sock, (struct sockaddr *) &name, sizeof (name)) < 0 )
+ {
+
+ wrap::system_message( BINDERR );
+
+ if ( ++i_port > MAXPORT )
+ exit(1);
+
+ wrap::system_message( string(SOCKERR) + tool::int2string(i_port) );
+
+ // Rerun recursive.
+ return _make_server_socket( i_port );
+ }
+
+ wrap::system_message( SOCKCRT + string("localhost:") + tool::int2string(i_port) );
+
+ i_server_port = i_port;
+ i_server_sock = i_sock;
+
+ return i_sock;
+}
+
+string
+sock::read_http_line(socketcontainer *p_sock)
+{
+ string s_line;
+ int i_total = 0;
+ int i_read = 0;
+ char ch;
+
+ do
+ {
+ i_read = _read(p_sock, &ch, sizeof(ch));
+
+ if(i_read <= 0)
+ return "";
+
+ s_line += ch;
+ i_total++;
+ }
+ while((ch != '\n') && i_total < MAXLENGTH);
+
+ if(ch != '\n')
+ /*
+ ** the games people play
+ */
+ return "";
+
+ return s_line;
+}
+int
+sock::read_http(socketcontainer *p_sock, char *c_zbuf, int i_buflen, int &i_postpayloadoffset)
+{
+ /*
+ ** 1) Read the first line
+ ** 2) If GET, handle as such
+ ** 3) If POST, handle as such
+ */
+ char ch;
+ int i_read;
+ int i_ret = -1;
+ int x,z;
+
+ string s_content_length;
+ string s_cl;
+ string s_post_return;
+ string s_line = read_http_line(p_sock);
+
+ i_postpayloadoffset = 0;
+ if(s_line.length() <= 0)
+ return -1;
+
+ /*
+ ** GET yada\r\n Followed by stuff we don't care about :) heh.
+ ** 01234
+ */
+ /*
+ ** POST yada\r\n
+ ** xxxxx
+ ** Content-Length: NNN\n
+ ** \n
+ */
+ if(s_line.substr(0,3) == "GET")
+ {
+ if(s_line.length() > i_buflen)
+ {
+ /*
+ ** Buffer overflow
+ */
+ return -1;
+ }
+ else
+ {
+ memcpy(c_zbuf,s_line.c_str(),s_line.length());
+ return s_line.length();
+ }
+ }
+
+ else
+ {
+ /*
+ ** POST yada
+ ** 01234
+ */
+ if(s_line.substr(0,4) != "POST")
+ return -1;
+
+ /*
+ ** Get us to the Content-Length:
+ */
+ s_post_return += s_line;
+ i_postpayloadoffset += s_line.length();
+
+ for(x=0 ;x < MAXLINES; x++)
+ {
+ s_line = read_http_line(p_sock);
+ s_post_return += s_line;
+ i_postpayloadoffset += s_line.length();
+
+ if (s_line.compare(0, 15, "Content-Length:"))
+ continue;
+
+ // Match found on Content-Length:... process, and then break out and get us to the promised land
+ s_content_length = s_line.substr( 16 /*strlen("Content-Length: ")*/,
+ s_line.length() - 16 /*strlen("Content-Length: ")*/);
+
+ /*
+ ** Content-Length: 333\n
+ ** 0123456789abcdefghijklmnopqrstuvwxyzAB
+ */
+
+ z = 0;
+
+ do
+ {
+ ch = s_content_length[z];
+ if(isdigit(ch))
+ s_cl += ch;
+
+ z++;
+
+ }
+ while(ch != '\n');
+
+ break;
+ }
+
+ if(s_cl.length() <= 0)
+ return -1;
+
+ z = atoi(s_cl.c_str());
+
+ /*
+ ** If we are going to overflow the buffer just by the payload, leave
+ ** of, if z did not convert correctly. (should have been ok by isdigit)
+ */
+ if(z > i_buflen || z < 0)
+ return -1;
+
+ /*
+ ** We have MAXLINES to get to the blank line separating POST data.
+ */
+ for(x=0 ;x < MAXLINES; x++)
+ {
+ s_line = read_http_line(p_sock);
+ s_post_return += s_line;
+
+ i_postpayloadoffset += s_line.length();
+ if(s_line == "\r\n")
+ break;
+ }
+
+ /*
+ ** funny business
+ */
+ if(x == MAXLINES)
+ return -1;
+
+ for(x=0; x < z; x++)
+ {
+ if(_read(p_sock,&ch,sizeof(ch)) != 1)
+ return -1;
+
+ s_post_return += ch;
+ }
+
+ if(s_post_return.length() > i_buflen)
+ return -1;
+
+ memcpy(c_zbuf,s_post_return.c_str(),s_post_return.length());
+ return s_post_return.length();
+ }
+}
+
+int
+sock::read_write(socketcontainer* p_sock)
+{
+ int i_postpayloadoffset;
+ int i_sock = p_sock->i_sock;
+
+ char c_req[READSOCK];
+
+ memset(c_req,0,sizeof(c_req));
+
+ int i_bytes = read_http(p_sock, c_req, READSOCK-1,i_postpayloadoffset);
+
+ if (i_bytes <= 0)
+ {
+ wrap::system_message( READERR );
+ }
+
+ else
+ {
+ // stores the request params.
+ map<string,string> map_params;
+
+ // get the s_rep ( s_html response which will be send imediatly to the client
+ struct sockaddr_in client;
+ size_t size = sizeof(client);
+
+ getpeername(i_sock, (struct sockaddr *)&client, &size);
+
+ uint32_t &s_addr = client.sin_addr.s_addr;
+ if ( (map_params["REMOTE_ADDR"] = get_elem(s_addr)) == "" )
+ {
+ map_params["REMOTE_ADDR"] = string(inet_ntoa(client.sin_addr));
+ set_elem(map_params["REMOTE_ADDR"], s_addr);
+ wrap::system_message(SOCKCAC+map_params["REMOTE_ADDR"]);
+ }
+
+ string s_rep = req_parser->parse(p_sock, string(c_req), map_params, i_postpayloadoffset);
+
+#ifdef LOGGING
+
+ log_daemon->log_access(map_params);
+#endif
+
+ // send s_rep to the client.
+ _send(p_sock, s_rep.c_str(), s_rep.size());
+
+ // dont need those vals anymore.
+ map_params.clear();
+
+ _close(p_sock);
+ return 0;
+ }
+
+ _close(p_sock);
+ return 1;
+}
+
+void
+sock::_main_loop_init()
+{
+ wrap::system_message(SOCKUNS);
+}
+
+#ifdef OPENSSL
+// This method is virtual, and is overloaded by sslsock!
+bool
+sock::_main_loop_do_ssl_stuff(int &i_new_sock)
+{
+ return 0;
+}
+#endif
+
+socketcontainer*
+sock::_create_container(int &i_sock)
+{
+ socketcontainer* p_sock = new socketcontainer;
+ p_sock->i_sock = i_sock;
+ return p_sock;
+}
+
+int
+sock::start()
+{
+ wrap::system_message( SOCKSRV );
+ pool* p_pool = wrap::POOL;
+ int i_sock = i_server_sock;
+
+#ifdef NCURSES
+
+ print_hits();
+ p_pool->print_pool_size();
+#endif
+
+ int i_port = tool::string2int( wrap::CONF->get_elem( "httpd.serverport" ) );
+ _main_loop_init();
+
+ int i;
+ fd_set active_fd_set, read_fd_set;
+ struct sockaddr_in clientname;
+ size_t size;
+
+ if (listen (i_sock, 1) < 0)
+ {
+ wrap::system_message( LISTERR );
+ exit( EXIT_FAILURE );
+ }
+
+ wrap::system_message( SOCKRDY );
+
+ // initialize the set of active sockets.
+ FD_ZERO (&active_fd_set);
+ FD_SET (i_sock, &active_fd_set);
+
+ while( b_run )
+ {
+ // block until input arrives on one or more active sockets.
+ read_fd_set = active_fd_set;
+ if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0)
+ {
+ wrap::system_message( SELCERR );
+
+ exit( EXIT_FAILURE );
+ }
+
+ // service all the sockets with input pending.
+ for ( i = 0; i < FD_SETSIZE; i++ )
+ if ( FD_ISSET (i, &read_fd_set) )
+ {
+ if ( i == i_sock )
+ {
+ // connection request on original socket.
+ ++i_req;
+
+#ifdef NCURSES
+
+ print_hits();
+#endif
+
+ int i_new_sock;
+ size = sizeof(clientname);
+ i_new_sock = accept (i_sock, (struct sockaddr *) &clientname, &size);
+
+#ifdef OPENSSL
+
+ if (_main_loop_do_ssl_stuff(i_new_sock))
+ continue;
+#endif
+
+#ifdef VERBOSE
+
+ wrap::system_message(NEWREQU
+ + tool::int2string(i_req) + " "
+ + string(inet_ntoa( clientname.sin_addr )) + ":"
+ + tool::int2string(ntohs ( clientname.sin_port ))
+ );
+#endif
+
+ FD_SET (i_new_sock, &active_fd_set);
+
+ }
+ else
+ {
+ socketcontainer *p_sock = _create_container(i);
+ p_pool->run( (void*) p_sock );
+ FD_CLR( i, &active_fd_set );
+ }
+ }
+ }
+}
+
+void
+sock::clean_ipcache()
+{
+ int i_ipcachesize = wrap::CONF->get_int("httpd.ipcachesize");
+ int i_currentsize = size();
+
+ if ( i_currentsize > 0 && (i_ipcachesize == 0 || i_ipcachesize <= i_currentsize) )
+ {
+ wrap::system_message(
+ SOCKCA2+tool::int2string(i_currentsize)+","+tool::int2string(i_ipcachesize)+")");
+ clear();
+ }
+}
+
+#ifdef NCURSES
+void
+sock::print_server_port() {
+ mvprintw( NCUR_PORT_X,NCUR_PORT_Y, "Port: %d ", i_server_port);
+ refresh();
+}
+
+void
+sock::print_hits()
+{
+ if ( wrap::NCUR->is_ready() )
+ {
+ mvprintw( NCUR_HITS_X,NCUR_HITS_Y, "Hits: %d ", i_req);
+ refresh();
+ }
+}
+#endif
+
+#endif
diff --git a/yhttpd/src/sock/sock.h b/yhttpd/src/sock/sock.h
new file mode 100644
index 0000000..72944e2
--- /dev/null
+++ b/yhttpd/src/sock/sock.h
@@ -0,0 +1,91 @@
+#include "../incl.h"
+
+#ifndef SOCK_H
+#define SOCK_H
+
+#include <queue>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "../reqp.h"
+
+#include "../thrd/pool.h"
+#include "../maps/shashmap.h"
+
+#ifdef LOGGING
+#include "../logd.h"
+#endif
+
+using namespace std;
+
+class sock : public shashmap
+ < string, uint32_t, self_hash<uint32_t>, equals_allocator<uint32_t> >
+{
+protected:
+#ifdef LOGGING
+
+ logd *log_daemon; // the log daemon
+#endif
+
+ int i_server_sock;
+ int i_server_port;
+
+ // total number of server requests.
+ unsigned long long i_req;
+ bool b_run; // true while socket manager is running.
+ reqp *req_parser; // parses the http requests from clients.
+ char *c_buffer; // char buffer!
+ pthread_mutex_t mut_hits;
+
+ static string inet_ntoa_callback(void* p_void);
+
+public:
+ // creates a server socket.
+ int read_http(socketcontainer *p_sock, char *c_zbuf, int i_buflen, int &i_payloadoffset);
+ string read_http_line(socketcontainer *p_sock);
+
+ // small inline methods:
+ bool get_server_() const
+ {
+ return b_run;
+ }
+ // small inline methods:
+ bool get_run() const
+ {
+ return b_run;
+ }
+ bool set_run( bool b_run )
+ {
+ this->b_run = b_run;
+ }
+
+ sock();
+
+ int read_write( socketcontainer* p_sock );
+
+ int start();
+ void clean_ipcache();
+
+ // the chat stream there all the chat messages will sent through.
+ virtual int _send(socketcontainer *p_sock, const char *sz, int len);
+ virtual int _read(socketcontainer *p_sock, char *sz, int len);
+ virtual int _close(socketcontainer *p_sock);
+ virtual void _main_loop_init();
+#ifdef OPENSSL
+
+ virtual bool _main_loop_do_ssl_stuff(int& i_new_sock);
+#endif
+
+ virtual socketcontainer* _create_container(int& i_sock);
+ virtual int _make_server_socket(int i_port);
+
+#ifdef NCURSES
+ void print_server_port();
+ void print_hits();
+#endif
+
+};
+#endif
diff --git a/yhttpd/src/sock/sslsock.cpp b/yhttpd/src/sock/sslsock.cpp
new file mode 100644
index 0000000..32efc0f
--- /dev/null
+++ b/yhttpd/src/sock/sslsock.cpp
@@ -0,0 +1,141 @@
+#include "../incl.h"
+
+#ifdef OPENSSL
+#ifndef SSLSOCK_CPP
+#define SSLSOCK_CPP
+
+#include "sslsock.h"
+
+using namespace std;
+
+sslsock::sslsock() : sock()
+{
+ s_certificate_path = wrap::CONF->get_elem( "httpd.ssl.certificatepath" );
+ s_privatekey_path = wrap::CONF->get_elem( "httpd.ssl.privatekeypath" );
+ p_ctx = NULL;
+}
+
+int
+sslsock::_send(socketcontainer *p_sock, const char *sz, int len)
+{
+ return SSL_write((SSL*)p_sock->p_ssl_context,sz, len);
+}
+
+int
+sslsock::_read(socketcontainer *p_sock, char *sz, int len)
+{
+ return SSL_read((SSL*)p_sock->p_ssl_context,sz,len);
+}
+
+int
+sslsock::_close(socketcontainer *p_sock)
+{
+ SSL_free((SSL*)p_sock->p_ssl_context);
+ sock::_close(p_sock);
+}
+
+int
+sslsock::_make_server_socket(int i_port)
+{
+ SSL_METHOD *p_ssl_method;
+ unsigned long e;
+ char sz[1024];
+ string s_error;
+
+ int i_sock = sock::_make_server_socket(i_port);
+
+ if(i_sock <= 0)
+ {
+ wrap::system_message(SSLERR1);
+ return -1;
+ }
+
+ SSL_load_error_strings();
+ SSLeay_add_ssl_algorithms();
+
+ p_ssl_method = SSLv23_server_method();
+ p_ctx = SSL_CTX_new (p_ssl_method);
+ if (!p_ctx)
+ {
+ e = ERR_get_error();
+ ERR_error_string_n(e, sz, sizeof(sz) - 1);
+ s_error = sz;
+ wrap::system_message(SSLERR1);
+ return -1;
+ }
+
+ if (SSL_CTX_use_certificate_file(p_ctx, s_certificate_path.c_str(), SSL_FILETYPE_PEM) <= 0)
+ {
+ e = ERR_get_error();
+ ERR_error_string_n(e, sz, sizeof(sz) - 1);
+ s_error = sz;
+ wrap::system_message(SSLERR1);
+ return -1;
+ }
+
+ if (SSL_CTX_use_PrivateKey_file(p_ctx, s_privatekey_path.c_str(), SSL_FILETYPE_PEM) <= 0)
+ {
+ e = ERR_get_error();
+ ERR_error_string_n(e, sz, sizeof(sz) - 1);
+ s_error = sz;
+ wrap::system_message(SSLERR1);
+ return -1;
+ }
+
+ if (!SSL_CTX_check_private_key(p_ctx))
+ {
+ wrap::system_message(SSLERR2);
+ return -1;
+ }
+
+ return i_sock;
+}
+
+void
+sslsock::_main_loop_init()
+{
+ wrap::system_message(SOCKSEC);
+}
+
+bool
+sslsock::_main_loop_do_ssl_stuff(int& i_new_sock)
+{
+ SSL* p_ssl = SSL_new(p_ctx);
+
+ if( p_ssl == NULL || i_new_sock < 0)
+ {
+ wrap::system_message(SSLERR3);
+
+ close(i_new_sock);
+ if(p_ssl != NULL)
+ SSL_free(p_ssl);
+
+ return 1;
+ }
+
+ else
+ {
+ SSL_set_fd(p_ssl, i_new_sock);
+ if(SSL_accept(p_ssl) == -1)
+ {
+ wrap::system_message(SSLERR4);
+ close(i_new_sock);
+ return 1;
+ }
+
+ map_certs[i_new_sock] = p_ssl;
+ }
+
+ return 0;
+}
+
+socketcontainer*
+sslsock::_create_container(int &i_sock)
+{
+ socketcontainer* p_sock = sock::_create_container(i_sock);
+ p_sock->p_ssl_context = map_certs[i_sock];
+ return p_sock;
+}
+
+#endif
+#endif
diff --git a/yhttpd/src/sock/sslsock.h b/yhttpd/src/sock/sslsock.h
new file mode 100644
index 0000000..f5358cc
--- /dev/null
+++ b/yhttpd/src/sock/sslsock.h
@@ -0,0 +1,41 @@
+#include "../incl.h"
+
+#ifdef OPENSSL
+#ifndef SSLSOCK_H
+#define SSLSOCK_H
+
+#include "sock.h"
+
+#include <openssl/rsa.h>
+#include <openssl/crypto.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+using namespace std;
+
+class sslsock : public sock
+{
+private:
+ SSL_CTX* p_ctx;
+ string s_certificate_path;
+ string s_privatekey_path;
+ map<int,void*> map_certs;
+
+public:
+
+ sslsock( );
+ ~sslsock( );
+
+ int _send(socketcontainer *p_sock, const char *sz, int len);
+ int _read(socketcontainer *p_sock, char *sz, int len);
+ int _close(socketcontainer *p_sock);
+ void _main_loop_init();
+ bool _main_loop_do_ssl_stuff(int &i_new_sock);
+ socketcontainer* _create_container(int& i_sock);
+ int _make_server_socket(int i_port);
+};
+
+#endif
+#endif
diff --git a/yhttpd/src/thrd/pool.cpp b/yhttpd/src/thrd/pool.cpp
new file mode 100644
index 0000000..dd29d6a
--- /dev/null
+++ b/yhttpd/src/thrd/pool.cpp
@@ -0,0 +1,157 @@
+#ifndef POOL_CPP
+#define POOL_CPP
+
+#include "pool.h"
+
+using namespace std;
+
+pool::pool()
+{
+ pthread_mutex_init(&mut_threads, 0);
+ pthread_mutex_init(&mut_queue_tasks, 0);
+ pthread_mutex_init(&mut_num_avail_threads, 0);
+ pthread_cond_init(&cond_new_task, 0);
+
+ i_num_total_threads = 0;
+ i_num_avail_threads = tool::string2int( wrap::CONF->get_elem( "httpd.thread.initpoolsize" ) );
+ increase_pool(i_num_avail_threads);
+}
+
+pool::~pool()
+{
+ pthread_mutex_lock(&mut_queue_tasks);
+ while (!queue_tasks.empty())
+ {
+ delete queue_tasks.front();
+ queue_tasks.pop();
+ }
+ pthread_mutex_unlock(&mut_queue_tasks);
+
+ pthread_mutex_destroy(&mut_threads);
+ pthread_mutex_destroy(&mut_queue_tasks);
+ pthread_mutex_destroy(&mut_num_avail_threads);
+ pthread_cond_destroy(&cond_new_task);
+}
+
+int
+pool::increase_pool(int i_num)
+{
+ wrap::system_message(POOLFLL + tool::int2string(i_num) +","+tool::int2string(i_num_total_threads)+")");
+ int i_max_pool_size = tool::string2int( wrap::CONF->get_elem( "httpd.thread.maxpoolsize" ) );
+
+ for ( int i = 0; i < i_num; ++i )
+ {
+ if ( i_max_pool_size != 0 && i_num_total_threads >= i_max_pool_size )
+ {
+ wrap::system_message(POOLER2+tool::int2string(i_max_pool_size)+")");
+ wrap::system_message(POOLER1+tool::int2string(i)+")");
+ return i;
+ }
+
+ ++i_num_total_threads;
+ pthread_t p_pthread;
+ pthread_create(&p_pthread, 0, wait_for_task, (void*) this );
+ }
+
+ return i_num;
+}
+
+void
+pool::add_task( void(*p_func)(void*), void* p_void )
+{
+ pthread_mutex_lock(&mut_queue_tasks);
+ queue_tasks.push(new task(p_func, p_void));
+ pthread_mutex_unlock(&mut_queue_tasks);
+
+ pthread_cond_signal(&cond_new_task);
+
+}
+
+void*
+pool::wait_for_task( void* p_void )
+{
+ pool* p_pool = static_cast<pool*>(p_void);
+
+ for (;;)
+ {
+
+#ifdef NCURSES
+ p_pool->print_pool_size();
+#endif
+
+ pthread_mutex_lock(&p_pool->mut_threads);
+ pthread_cond_wait(&p_pool->cond_new_task, &p_pool->mut_threads);
+
+ pthread_mutex_lock(&p_pool->mut_num_avail_threads);
+ if ( --p_pool->i_num_avail_threads < 5 )
+ {
+ int i_size = 9 - p_pool->i_num_avail_threads;
+ i_size = p_pool->increase_pool(i_size);
+ p_pool->i_num_avail_threads += i_size;
+ }
+ pthread_mutex_unlock(&p_pool->mut_num_avail_threads);
+
+ pthread_mutex_lock(&p_pool->mut_queue_tasks);
+ task* p_task = p_pool->queue_tasks.front();
+ p_pool->queue_tasks.pop();
+ pthread_mutex_unlock(&p_pool->mut_queue_tasks);
+
+ pthread_mutex_unlock(&p_pool->mut_threads);
+
+ (*(p_task->p_func))(p_task->p_void);
+ delete p_task;
+
+ pthread_mutex_lock(&p_pool->mut_num_avail_threads);
+ p_pool->i_num_avail_threads++;
+ pthread_mutex_unlock(&p_pool->mut_num_avail_threads);
+ }
+
+ return 0;
+}
+
+void
+pool::run(void* p_void)
+{
+ add_task(run_func, p_void);
+}
+
+void
+pool::run_func(void *p_void)
+{
+ socketcontainer* p_sock = static_cast<socketcontainer*>(p_void);
+ wrap::SOCK->read_write(p_sock);
+}
+
+bool
+pool::allow_user_login()
+{
+ pthread_mutex_lock(&mut_num_avail_threads);
+ if ( i_num_avail_threads < 2 )
+ {
+ int i_max_pool_size = tool::string2int( wrap::CONF->get_elem( "httpd.thread.maxpoolsize" ) );
+ if ( i_max_pool_size != 0 && i_max_pool_size == i_num_total_threads )
+ {
+ pthread_mutex_unlock(&mut_num_avail_threads);
+ return false;
+ }
+ }
+ pthread_mutex_unlock(&mut_num_avail_threads);
+
+ return true;
+}
+
+#ifdef NCURSES
+void
+pool::print_pool_size()
+{
+ if ( wrap::NCUR->is_ready() )
+ {
+ pthread_mutex_lock(&mut_num_avail_threads);
+ mvprintw( NCUR_POOL_WAIT_X,NCUR_POOL_WAIT_Y, "Wait/Tot: %d/%d ", i_num_avail_threads, i_num_total_threads);
+ mvprintw( NCUR_POOL_RUNNING_X,NCUR_POOL_RUNNING_Y, "Running: %d ", i_num_total_threads-i_num_avail_threads);
+ pthread_mutex_unlock(&mut_num_avail_threads);
+ refresh();
+ }
+}
+#endif
+#endif
diff --git a/yhttpd/src/thrd/pool.h b/yhttpd/src/thrd/pool.h
new file mode 100644
index 0000000..3a5f7b6
--- /dev/null
+++ b/yhttpd/src/thrd/pool.h
@@ -0,0 +1,55 @@
+#include "../incl.h"
+
+#ifndef POOL_H
+#define POOL_H
+
+#include <queue>
+
+using namespace std;
+
+class pool
+{
+private:
+ friend class thro;
+
+ struct task
+ {
+ void(*p_func)(void*);
+ void *p_void;
+
+ task(void(*p_func)(void*), void *p_void)
+ {
+ this->p_func = p_func;
+ this->p_void = p_void;
+ }
+ };
+
+ pthread_mutex_t mut_threads;
+ pthread_mutex_t mut_queue_tasks;
+ pthread_mutex_t mut_num_avail_threads;
+ pthread_cond_t cond_new_task;
+
+ int i_num_avail_threads;
+ int i_num_total_threads;
+
+ queue<task*> queue_tasks;
+
+ int increase_pool(int i_num);
+ void add_task( void(*p_func)(void*), void* p_void );
+ static void* wait_for_task(void *p_void);
+ static void run_func(void *p_void);
+
+public:
+ pool();
+ ~pool();
+
+ void run(void* p_void);
+ bool allow_user_login();
+
+#ifdef NCURSES
+
+ void print_pool_size();
+#endif
+};
+
+#endif
diff --git a/yhttpd/src/thrd/thro.cpp b/yhttpd/src/thrd/thro.cpp
new file mode 100644
index 0000000..8b3f1ba
--- /dev/null
+++ b/yhttpd/src/thrd/thro.cpp
@@ -0,0 +1,43 @@
+#ifndef THRO_CPP
+#define THRO_CPP
+
+#include "thro.h"
+
+using namespace std;
+
+thro::thro()
+{}
+
+thro::~thro()
+{}
+
+void
+thro::run()
+{
+ void *p_void;
+ run( p_void );
+}
+
+void
+thro::run( void *p_void )
+{
+ elem.p_thro = this;
+ elem.p_void = p_void;
+ //wrap::POOL->add_task(start_, &elem);
+ pthread_create( &pthread, NULL, start_, &elem );
+}
+
+void*
+thro::start_( void *p_void )
+{
+ elements *e = (elements*) p_void;
+ e->p_thro->start( e->p_void );
+}
+
+void
+thro::start( void *p_void )
+{
+ wrap::system_message( THRDSTR );
+}
+
+#endif
diff --git a/yhttpd/src/thrd/thro.h b/yhttpd/src/thrd/thro.h
new file mode 100644
index 0000000..8e7e0cf
--- /dev/null
+++ b/yhttpd/src/thrd/thro.h
@@ -0,0 +1,30 @@
+#include "../incl.h"
+
+#ifndef THRO_H
+#define THRO_H
+
+using namespace std;
+
+class thro
+{
+private:
+ pthread_t pthread;
+
+ struct elements
+ {
+ thro *p_thro;
+ void *p_void;
+ }
+ elem;
+
+ static void *start_( void *p_void );
+
+public:
+ thro( );
+ ~thro( );
+ void run();
+ void run( void *p_void );
+ virtual void start( void *p_void );
+};
+
+#endif
diff --git a/yhttpd/src/time/timo.cpp b/yhttpd/src/time/timo.cpp
new file mode 100644
index 0000000..fd89bdf
--- /dev/null
+++ b/yhttpd/src/time/timo.cpp
@@ -0,0 +1,38 @@
+#ifndef TIMO_CPP
+#define TIMO_CPP
+
+#include "timo.h"
+
+using namespace std;
+
+timo::timo()
+{
+ pthread_mutex_init( &mut_t_time, NULL );
+}
+
+timo::~timo()
+{
+ pthread_mutex_destroy( &mut_t_time );
+}
+
+double
+timo::get_last_activity( )
+{
+ double d_ret;
+
+ pthread_mutex_lock ( &mut_t_time );
+ d_ret = wrap::TIMR->get_time_diff( t_time );
+ pthread_mutex_unlock( &mut_t_time );
+
+ return d_ret;
+}
+
+void
+timo::renew_timeout( )
+{
+ pthread_mutex_lock ( &mut_t_time );
+ time( &t_time );
+ pthread_mutex_unlock( &mut_t_time );
+}
+
+#endif
diff --git a/yhttpd/src/time/timo.h b/yhttpd/src/time/timo.h
new file mode 100644
index 0000000..ea160c1
--- /dev/null
+++ b/yhttpd/src/time/timo.h
@@ -0,0 +1,22 @@
+#include "../incl.h"
+
+#ifndef TIMO_H
+#define TIMO_H
+
+using namespace std;
+
+class timo // timeout class
+{
+protected:
+ time_t t_time; // last activity time.
+ pthread_mutex_t mut_t_time;
+
+public:
+ timo( );
+ ~timo( );
+
+ double get_last_activity();
+ virtual void renew_timeout();
+};
+
+#endif
diff --git a/yhttpd/src/time/timr.cpp b/yhttpd/src/time/timr.cpp
new file mode 100644
index 0000000..c7f80ee
--- /dev/null
+++ b/yhttpd/src/time/timr.cpp
@@ -0,0 +1,177 @@
+#ifndef TIMR_CPP
+#define TIMR_CPP
+
+#include <sys/time.h>
+#include "timr.h"
+
+using namespace std;
+
+timr::timr()
+{
+ wrap::system_message( TIMERIN );
+ b_timer_active = true;
+
+ pthread_mutex_init( &mut_s_time, NULL);
+ pthread_mutex_init( &mut_s_uptime, NULL);
+ pthread_mutex_init( &mut_i_offset, NULL);
+
+ i_time_offset = tool::string2int( wrap::CONF->get_elem("chat.timeoffset") );
+ wrap::system_message( TIMEROF + tool::int2string( i_time_offset ) );
+
+ s_time = "00:00:00";
+ s_uptime = "00:00:00";
+}
+
+timr::~timr()
+{
+ pthread_mutex_destroy( &mut_s_time );
+ pthread_mutex_destroy( &mut_s_uptime );
+ pthread_mutex_destroy( &mut_i_offset );
+}
+
+bool
+timr::get_timer_active() const
+{
+ return b_timer_active;
+}
+
+int
+timr::get_offset()
+{
+ pthread_mutex_lock ( &mut_i_offset );
+ int i_ret_val = i_time_offset;
+ pthread_mutex_unlock( &mut_i_offset );
+ return i_ret_val;
+}
+
+void
+timr::start( void *v_ptr )
+{
+ wrap::system_message( TIMERTH );
+
+#ifdef NCURSES
+
+ print_time( );
+#endif
+
+ time_t clock_start;
+ time_t clock_now;
+
+ time( &clock_start );
+ tm time_start = *localtime( &clock_start );
+ tm time_now;
+
+ while ( get_timer_active() )
+ {
+ // sleep a second!
+ usleep( 1000000 );
+
+ // get the current time!
+ time( &clock_now );
+
+ time_now = *localtime( &clock_now );
+
+ // set the current time && the current yhttpd uptime!
+ set_time( difftime( clock_now, clock_start ),
+ time_now.tm_sec, time_now.tm_min, time_now.tm_hour );
+
+#ifdef NCURSES
+
+ if (wrap::NCUR->is_ready())
+ print_time( );
+#endif
+
+ // run every minute:
+ if ( time_now.tm_sec == 0 )
+ {
+#ifdef SERVMSG
+ cout << TIMERUP << get_uptime() << endl;
+#endif
+ // Run every ten minutes:
+ if ( time_now.tm_min % 10 == 0 )
+ {
+
+ wrap::SOCK->clean_ipcache();
+ // Run every hour
+ if ( time_now.tm_min % 60 == 0 )
+ {
+
+ // Run every day
+ if (time_now.tm_min == 0 || time_now.tm_min == 60 )
+ if (time_now.tm_hour == 0 || time_now.tm_hour == 24)
+ wrap::STAT->update_rusage_history();
+ }
+ }
+ }
+ }
+}
+
+#ifdef NCURSES
+void
+timr::print_time( )
+{
+ if ( !wrap::NCUR->is_ready() )
+ return;
+
+ mvprintw( NCUR_TIME_X, NCUR_TIME_Y, "Time: %s ", get_time().c_str());
+ mvprintw( NCUR_UPTIME_X, NCUR_UPTIME_Y, "Uptime: %s ", get_uptime().c_str());
+ refresh();
+}
+#endif
+
+void
+timr::set_time( double d_uptime, int i_cur_seconds, int i_cur_minutes, int i_cur_hours )
+{
+
+ int i_hours = (int) d_uptime / 3600;
+ int i_minutes = (int) d_uptime / 60;
+
+ while ( i_minutes >= 60 )
+ i_minutes -= 60;
+
+ while ( d_uptime >= 60 )
+ d_uptime -= 60;
+
+ // Calculate offset time
+ i_cur_hours += get_offset();
+
+ for ( int i = 24-i_cur_hours; i < 0; i = 24-i_cur_hours )
+ i_cur_hours =- i;
+
+ if (i_cur_hours == 24)
+ i_cur_hours = 0;
+
+ pthread_mutex_lock ( &mut_s_time );
+ s_time = add_zero_to_front( tool::int2string( i_cur_hours ) ) + ":" +
+ add_zero_to_front( tool::int2string( i_cur_minutes ) ) + ":" +
+ add_zero_to_front( tool::int2string( i_cur_seconds ) );
+ pthread_mutex_unlock( &mut_s_time );
+
+ pthread_mutex_lock ( &mut_s_uptime );
+ s_uptime = add_zero_to_front( tool::int2string( i_hours ) ) + ":" +
+ add_zero_to_front( tool::int2string( i_minutes ) ) + ":" +
+ add_zero_to_front( tool::int2string( (int) d_uptime ) );
+ pthread_mutex_unlock( &mut_s_uptime );
+}
+
+string
+timr::add_zero_to_front( string s_time )
+{
+ if ( s_time.length() == 1 )
+ {
+ string s_new = "0" + s_time;
+ return s_new;
+ }
+
+ return s_time;
+}
+
+double
+timr::get_time_diff( time_t &clock_diff )
+{
+ time_t clock_now;
+ time( &clock_now );
+
+ return difftime(clock_now, clock_diff);
+}
+#endif
diff --git a/yhttpd/src/time/timr.h b/yhttpd/src/time/timr.h
new file mode 100644
index 0000000..12cdd8f
--- /dev/null
+++ b/yhttpd/src/time/timr.h
@@ -0,0 +1,64 @@
+#include "../incl.h"
+
+#ifndef TIMR_H
+#define TIMR_H
+
+#include "../thrd/thro.h"
+
+#include <unistd.h>
+
+using namespace std;
+
+class timr : public thro
+{
+private:
+ bool b_timer_active;
+ int i_time_offset;
+ string s_uptime;
+ string s_time;
+
+ pthread_mutex_t mut_s_time;
+ pthread_mutex_t mut_s_uptime;
+ pthread_mutex_t mut_i_offset;
+
+public:
+ timr();
+ ~timr();
+
+ bool get_timer_active() const;
+ void start( void *v_ptr );
+
+#ifdef NCURSES
+
+ void print_time();
+#endif
+
+ void set_time( double d_uptime, int i_cur_seconds, int i_cur_minutes, int i_cur_hours );
+ string add_zero_to_front( string s_time );
+
+ // inline for dynamic module access!
+ string
+ get_time( )
+ {
+ string s_ret;
+ pthread_mutex_lock ( &mut_s_time );
+ s_ret = this->s_time;
+ pthread_mutex_unlock( &mut_s_time );
+ return s_ret;
+ }
+
+ string
+ get_uptime( )
+ {
+ string s_ret;
+ pthread_mutex_lock ( &mut_s_uptime );
+ s_ret = this->s_uptime;
+ pthread_mutex_unlock( &mut_s_uptime );
+ return s_ret;
+ }
+
+ int get_offset();
+ double get_time_diff( time_t &clock_diff );
+};
+
+#endif
diff --git a/yhttpd/src/tool/dir.cpp b/yhttpd/src/tool/dir.cpp
new file mode 100644
index 0000000..a23cca2
--- /dev/null
+++ b/yhttpd/src/tool/dir.cpp
@@ -0,0 +1,66 @@
+#ifndef DIR_CPP
+#define DIR_CPP
+
+#include "dir.h"
+
+using namespace std;
+
+dir::dir()
+{
+ b_open = false;
+}
+
+dir::~dir()
+{
+ vec_dir.clear();
+ close_dir();
+}
+
+bool
+dir::open_dir( char *c_dir )
+{
+ string s_dir( c_dir );
+ return open_dir( s_dir );
+}
+
+bool
+dir::open_dir( string &s_dir )
+{
+ if ( b_open )
+ return false;
+
+ p_d = opendir( s_dir.c_str() );
+
+ if ( p_d == NULL )
+ return false; // Could not open dir.
+
+ b_open = true;
+
+ return true; // Could open dir with success.
+}
+
+void
+dir::close_dir()
+{
+ if ( b_open && p_d != NULL )
+ {
+ closedir( p_d );
+ b_open = false;
+ }
+}
+
+void
+dir::read_dir()
+{
+ if ( p_d != NULL )
+ while( p_ep = readdir( p_d ) )
+ vec_dir.push_back( string( p_ep->d_name ) );
+}
+
+vector<string>
+dir::get_dir_vec()
+{
+ return vec_dir;
+}
+
+#endif
diff --git a/yhttpd/src/tool/dir.h b/yhttpd/src/tool/dir.h
new file mode 100644
index 0000000..eea78f7
--- /dev/null
+++ b/yhttpd/src/tool/dir.h
@@ -0,0 +1,35 @@
+
+#ifndef DIR_H
+#define DIR_H
+
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include <vector>
+
+#include "../incl.h"
+
+using namespace std;
+
+class dir
+{
+private:
+ bool b_open;
+ DIR *p_d;
+ struct dirent *p_ep;
+ vector<string> vec_dir;
+
+public:
+ dir();
+ ~dir();
+
+ bool open_dir( char *c_dir );
+ bool open_dir( string &s_dir );
+ void close_dir();
+ void read_dir();
+ vector<string> get_dir_vec();
+};
+
+#endif
diff --git a/yhttpd/src/tool/tool.cpp b/yhttpd/src/tool/tool.cpp
new file mode 100644
index 0000000..dbb1f22
--- /dev/null
+++ b/yhttpd/src/tool/tool.cpp
@@ -0,0 +1,240 @@
+#ifndef TOOL_CPP
+#define TOOL_CPP
+
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "tool.h"
+
+bool
+tool::is_alpha_numeric( string &s_digit )
+{
+ const char *p_digit = s_digit.c_str();
+ int i_len = strlen( p_digit );
+
+ for( int i=0; i<i_len; i++ )
+ {
+ if ( ! isalnum( *p_digit ) )
+ return false;
+ p_digit++;
+ }
+
+ return true;
+}
+
+string
+tool::int2string( int i_int )
+{
+ char buf[64];
+ sprintf(buf, "%d", i_int);
+ return buf;
+}
+
+long
+tool::unixtime()
+{
+ time_t clock;
+ return (long) time( &clock );
+}
+
+int
+tool::string2int( string s_digit )
+{
+ const char *p_digit = s_digit.c_str();
+ int i_res = 0;
+
+ // Convert each digit char and add into result.
+ while (*p_digit >= '0' && *p_digit <='9')
+ {
+ i_res = (i_res * 10) + (*p_digit - '0');
+ p_digit++;
+ }
+
+ // Check that there were no non-digits at end.
+ if (*p_digit != 0)
+ {
+ return -1;
+ }
+
+ return i_res;
+}
+
+string
+tool::to_lower( string s_str )
+{
+ string s_tmp("");
+
+ for( int i = 0; i < s_str.size() ;i++ )
+ s_tmp = s_tmp + (char) tolower( s_str.at(i) );
+
+ return s_tmp;
+}
+
+void
+tool::strip_html( string *p_str)
+{
+ int i_pos;
+
+ if( (i_pos=p_str->find("<", 0)) == string::npos )
+ return;
+
+ while(true)
+ {
+ p_str->replace(i_pos, 1, "&lt;");
+
+ if( (i_pos = p_str->find("<", 0)) == string::npos )
+ return;
+ }
+}
+
+string
+tool::yhttpd_version()
+{
+ return "yhttpd " + string(VERSION)
+ + "-" + string(BRANCH)
+ + " Build " + int2string(BUILDNR);
+}
+
+list<string>
+tool::split_string(string s_string, string s_split)
+{
+ list<string> list_ret;
+ unsigned i_pos, i_len = s_split.length();
+
+ while ( (i_pos = s_string.find(s_split)) != string::npos )
+ {
+ list_ret.push_back( s_string.substr(0, i_pos) );
+ s_string = s_string.substr( i_pos + i_len );
+ }
+
+ list_ret.push_back( s_string );
+
+ return list_ret;
+}
+
+string
+tool::trim( string s_str )
+{
+ if( s_str.empty() )
+ return s_str;
+
+ char c_cur = s_str[0];
+ int i_pos = 0;
+
+ // left trim
+ while ( c_cur == ' '|| c_cur == '\n' || c_cur == '\r' )
+ {
+ s_str.erase(i_pos,1);
+ c_cur = s_str[++i_pos];
+ }
+
+ // right trim
+ i_pos = s_str.size();
+ c_cur = s_str[s_str.size()];
+
+ while ( c_cur == ' ' || c_cur == '\n' || c_cur == '\0' || c_cur == '\r' )
+ {
+ s_str.erase(i_pos, 1);
+ c_cur = s_str[--i_pos];
+ }
+
+ return s_str;
+}
+
+char*
+tool::clean_char( char* c_str )
+{
+ // Ralf:
+ for ( char* c_pos = c_str; *c_pos != '\0'; ++c_pos )
+ if ( iscntrl(*c_pos) )
+ *c_pos = ' ';
+
+ return c_str;
+}
+
+string
+tool::replace( string s_string, string s_search, string s_replace )
+{
+ unsigned i_pos[2];
+
+ for ( i_pos[0] = s_string.find( s_search );
+ i_pos[0] != string::npos;
+ i_pos[0] = s_string.find( s_search, i_pos[1] ) )
+ {
+ s_string.replace( i_pos[0], s_search.length(), s_replace );
+ i_pos[1] = i_pos[0] + s_replace.length();
+ }
+
+ return s_string;
+}
+
+string
+tool::get_extension( string s_file )
+{
+ int i_pos = s_file.find_last_of(".");
+
+ if( i_pos != string::npos )
+ {
+ string s_ext = s_file.substr(i_pos+1, s_file.size()-i_pos-1 );
+ for( int i = 0; i < s_ext.size(); ++i )
+ s_ext[i] = tolower(s_ext[i]);
+
+ return to_lower(s_ext);
+ }
+
+ return "";
+}
+
+char*
+tool::int2char( int i_int )
+{
+ char *buf = new char[64];
+ sprintf(buf, "%d", i_int);
+ return buf;
+}
+
+string
+tool::shell_command( string s_command, method m_method )
+{
+ FILE *file;
+ char buf[READBUF];
+ char *c_pos;
+ string s_ret = "";
+
+ wrap::system_message(SHELLEX);
+ wrap::system_message(s_command);
+
+ if( (file=popen(s_command.c_str(), "r")) == NULL )
+ {
+ wrap::system_message( SHELLER );
+ }
+ else
+ {
+ while(true)
+ {
+ if(fgets(buf, READBUF, file) == NULL)
+ break;
+
+ switch (m_method)
+ {
+ case METH_NCURSES:
+ wrap::system_message( clean_char(buf) );
+ break;
+ default:
+ s_ret.append("\n" + string(buf));
+ } // switch
+ }
+
+ pclose(file);
+ }
+
+ return s_ret;
+}
+
+#endif
+
diff --git a/yhttpd/src/tool/tool.h b/yhttpd/src/tool/tool.h
new file mode 100644
index 0000000..7a1958d
--- /dev/null
+++ b/yhttpd/src/tool/tool.h
@@ -0,0 +1,29 @@
+#ifndef TOOL_H
+#define TOOL_H
+
+#include "../incl.h"
+
+#include <list>
+
+using namespace std;
+
+class tool
+{
+public:
+ static list<string> split_string(string s_string, string s_split);
+ static bool is_alpha_numeric( string &s_digit );
+ static char* int2char( int i_int );
+ static char* clean_char( char* c_str);
+ static string trim( string s_str );
+ static string replace( string s_string, string s_search, string s_replace );
+ static string int2string( int i_int );
+ static long unixtime();
+ static int string2int( string s_digit );
+ static string get_extension( string s_file );
+ static string to_lower( string s_str );
+ static void strip_html( string *p_str );
+ static string shell_command( string s_command, method m_method );
+ static string yhttpd_version();
+};
+
+#endif
diff --git a/yhttpd/src/wrap.cpp b/yhttpd/src/wrap.cpp
new file mode 100644
index 0000000..251a575
--- /dev/null
+++ b/yhttpd/src/wrap.cpp
@@ -0,0 +1,121 @@
+#ifndef WRAP_CPP
+#define WRAP_CPP
+
+#include "wrap.h"
+
+using namespace std;
+
+
+conf* wrap::CONF = NULL;
+html* wrap::HTML = NULL;
+#ifdef LOGGING
+logd* wrap::LOGD = NULL;
+#endif
+#ifdef NCURSES
+ncur* wrap::NCUR = NULL;
+#endif
+sock* wrap::SOCK = NULL;
+stats* wrap::STAT = NULL;
+timr* wrap::TIMR = NULL;
+pool* wrap::POOL = NULL;
+dynamic_wrap* wrap::WRAP = NULL;
+
+void
+wrap::system_message( string s_message )
+{
+#ifdef NCURSES
+ if(NCUR)
+ {
+ NCUR->print( s_message );
+ }
+
+ else
+ {
+ cout << s_message << endl;
+ }
+#endif
+
+#ifdef SERVMSG
+ cout << s_message << endl;
+#endif
+
+#ifdef LOGGING
+
+ LOGD->log_simple_line( s_message + "\n" );
+#endif
+}
+
+void
+wrap::init_wrapper(map<string,string>* p_main_loop_params)
+{
+ // Init the dynamic wrapper (is needed to pass all wrapped objects through a single pointer).
+ WRAP = new dynamic_wrap;
+
+ // Init the config manager.
+ WRAP->CONF = CONF = new conf( CONFILE, p_main_loop_params );
+ delete p_main_loop_params,
+
+ // Init the statistic manager.
+ WRAP->STAT = STAT = new stats;
+
+ // Init the html-template manager.
+ WRAP->HTML = HTML = new html;
+
+#ifdef LOGGING
+ // Init the system message logd
+ WRAP->LOGD = LOGD = new logd( CONF->get_elem("httpd.logging.systemfile"),
+ CONF->get_elem("httpd.logging.systemlines") );
+#endif
+
+ // Init the socket manager.
+ int i_port = tool::string2int( wrap::CONF->get_elem( "httpd.serverport" ) );
+
+#ifndef OPENSSL
+
+ WRAP->SOCK = SOCK = new sock;
+#else
+
+ WRAP->SOCK = SOCK = new sslsock;
+#endif
+
+ // create the server socket and set it up to accept connections.
+ if(SOCK->_make_server_socket ( i_port ) <= 0)
+ {
+ system_message(SOCKER1);
+ exit(-1);
+ }
+
+#ifdef NCURSES
+
+ WRAP->NCUR = NCUR = new ncur; // init the ncurses admin interface.
+ NCUR->run(); // run the thread
+
+ // Wait until ncurses interface has been initialized.
+ do
+ {
+ usleep(1000);
+ }
+ while ( ! NCUR->is_ready() );
+
+ HTML->print_cached(0);
+#else
+#ifdef CLI
+
+ cli* p_cli = new cli;
+ p_cli->run();
+#endif
+#endif
+
+ // Init the thread pool
+ WRAP->POOL = POOL = new pool;
+
+
+ // Init the system timer.
+ WRAP->TIMR = TIMR = new timr;
+
+
+ // Run threads
+ TIMR->run();
+}
+
+#endif
diff --git a/yhttpd/src/wrap.h b/yhttpd/src/wrap.h
new file mode 100644
index 0000000..768184a
--- /dev/null
+++ b/yhttpd/src/wrap.h
@@ -0,0 +1,105 @@
+#ifndef WRAP_H
+#define WRAP_H
+
+#include "incl.h"
+
+
+struct socketcontainer
+{
+ int i_sock;
+#ifdef OPENSSL
+ void *p_ssl_context;
+#endif
+
+};
+
+#ifdef DATABASE
+#endif
+#include "conf/conf.h"
+#include "html.h"
+#ifdef LOGGING
+#include "logd.h"
+#endif
+
+#ifdef NCURSES
+#include "ncur/ncur.h"
+#else
+#ifdef CLI
+#include "cli/cli.h"
+#endif
+#endif
+
+
+#ifndef OPENSSL
+#include "sock/sock.h"
+#else
+#include "sock/sslsock.h"
+#endif
+
+#include "monitor/stats.h"
+#include "time/timr.h"
+#include "thrd/pool.h"
+
+
+using namespace std;
+
+
+class dynamic_wrap
+{
+public:
+
+ conf* CONF;
+ html* HTML;
+#ifdef LOGGING
+
+ logd* LOGD;
+#endif
+#ifdef NCURSES
+
+ ncur* NCUR;
+#endif
+
+ sock* SOCK;
+ stats* STAT;
+ timr* TIMR;
+ pool* POOL;
+};
+
+class wrap
+{
+public:
+ static void system_message( char* c_message )
+ {
+ wrap::system_message( string(c_message) );
+ }
+
+ static void system_message( string* p_message )
+ {
+ wrap::system_message( *p_message );
+ }
+
+ static void system_message( string s_message );
+
+ static void init_wrapper(map<string,string>* p_main_loop_params);
+
+
+ static conf* CONF;
+ static html* HTML;
+#ifdef LOGGING
+
+ static logd* LOGD;
+#endif
+#ifdef NCURSES
+
+ static ncur* NCUR;
+#endif
+
+ static sock* SOCK;
+ static stats* STAT;
+ static timr* TIMR;
+ static pool* POOL;
+ static dynamic_wrap* WRAP;
+};
+
+
+#endif