summaryrefslogtreecommitdiff
path: root/yhttpd-0.7.0/src
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2013-04-06 13:14:41 +0200
committerPaul Buetow <paul@buetow.org>2013-04-06 13:14:41 +0200
commit9cd3ccffd5372dfde3af478e3f832f18db4be3f1 (patch)
tree631c295a4a4a16b57502b847626763a279bf6df7 /yhttpd-0.7.0/src
parent13aaf70af703748fe096e0664c305cd202637ad2 (diff)
tagging tags
Diffstat (limited to 'yhttpd-0.7.0/src')
-rwxr-xr-xyhttpd-0.7.0/src/Makefile.in21
-rwxr-xr-xyhttpd-0.7.0/src/cli/cli.cpp265
-rwxr-xr-xyhttpd-0.7.0/src/cli/cli.h54
-rwxr-xr-xyhttpd-0.7.0/src/conf/conf.cpp155
-rwxr-xr-xyhttpd-0.7.0/src/conf/conf.h27
-rwxr-xr-xyhttpd-0.7.0/src/conf/lang.cpp67
-rwxr-xr-xyhttpd-0.7.0/src/conf/lang.h23
-rwxr-xr-xyhttpd-0.7.0/src/configure248
-rw-r--r--yhttpd-0.7.0/src/contrib/README5
-rw-r--r--yhttpd-0.7.0/src/contrib/xml/README504
-rw-r--r--yhttpd-0.7.0/src/contrib/xml/tinyxml.cpp1427
-rw-r--r--yhttpd-0.7.0/src/contrib/xml/tinyxml.h1368
-rw-r--r--yhttpd-0.7.0/src/contrib/xml/tinyxmlerror.cpp51
-rw-r--r--yhttpd-0.7.0/src/contrib/xml/tinyxmlparser.cpp1493
-rwxr-xr-xyhttpd-0.7.0/src/glob.h178
-rwxr-xr-xyhttpd-0.7.0/src/html.cpp129
-rwxr-xr-xyhttpd-0.7.0/src/html.h39
-rwxr-xr-xyhttpd-0.7.0/src/incl.h9
-rwxr-xr-xyhttpd-0.7.0/src/logd.cpp157
-rwxr-xr-xyhttpd-0.7.0/src/logd.h36
-rwxr-xr-xyhttpd-0.7.0/src/main.cpp159
-rw-r--r--yhttpd-0.7.0/src/maps/hmap.h100
-rw-r--r--yhttpd-0.7.0/src/maps/hmap.tmpl282
-rw-r--r--yhttpd-0.7.0/src/maps/mtools.h15
-rw-r--r--yhttpd-0.7.0/src/maps/mtools.tmpl11
-rw-r--r--yhttpd-0.7.0/src/maps/nmap.h25
-rw-r--r--yhttpd-0.7.0/src/maps/nmap.tmpl31
-rw-r--r--yhttpd-0.7.0/src/maps/smap.h56
-rw-r--r--yhttpd-0.7.0/src/maps/smap.tmpl211
-rwxr-xr-xyhttpd-0.7.0/src/modl.cpp161
-rwxr-xr-xyhttpd-0.7.0/src/modl.h37
-rw-r--r--yhttpd-0.7.0/src/msgs.h101
-rwxr-xr-xyhttpd-0.7.0/src/name.cpp51
-rwxr-xr-xyhttpd-0.7.0/src/name.h28
-rwxr-xr-xyhttpd-0.7.0/src/ncur/menu.cpp118
-rwxr-xr-xyhttpd-0.7.0/src/ncur/menu.h34
-rwxr-xr-xyhttpd-0.7.0/src/ncur/ncur.cpp263
-rwxr-xr-xyhttpd-0.7.0/src/ncur/ncur.h44
-rwxr-xr-xyhttpd-0.7.0/src/reqp.cpp297
-rwxr-xr-xyhttpd-0.7.0/src/reqp.h49
-rw-r--r--yhttpd-0.7.0/src/sock/Makefile23
-rw-r--r--yhttpd-0.7.0/src/sock/README1
-rwxr-xr-xyhttpd-0.7.0/src/sock/sock.cpp257
-rwxr-xr-xyhttpd-0.7.0/src/sock/sock.h69
-rw-r--r--yhttpd-0.7.0/src/stats.cpp102
-rw-r--r--yhttpd-0.7.0/src/stats.h36
-rwxr-xr-xyhttpd-0.7.0/src/thrd/pool.cpp206
-rwxr-xr-xyhttpd-0.7.0/src/thrd/pool.h77
-rwxr-xr-xyhttpd-0.7.0/src/thrd/thrd.cpp26
-rwxr-xr-xyhttpd-0.7.0/src/thrd/thrd.h28
-rw-r--r--yhttpd-0.7.0/src/thrd/thro.cpp45
-rw-r--r--yhttpd-0.7.0/src/thrd/thro.h30
-rwxr-xr-xyhttpd-0.7.0/src/time/timo.cpp36
-rwxr-xr-xyhttpd-0.7.0/src/time/timo.h22
-rwxr-xr-xyhttpd-0.7.0/src/time/timr.cpp167
-rwxr-xr-xyhttpd-0.7.0/src/time/timr.h63
-rw-r--r--yhttpd-0.7.0/src/tool/dir.cpp66
-rw-r--r--yhttpd-0.7.0/src/tool/dir.h33
-rw-r--r--yhttpd-0.7.0/src/tool/tool.cpp129
-rw-r--r--yhttpd-0.7.0/src/tool/tool.h93
-rwxr-xr-xyhttpd-0.7.0/src/wrap.cpp32
-rwxr-xr-xyhttpd-0.7.0/src/wrap.h67
62 files changed, 9937 insertions, 0 deletions
diff --git a/yhttpd-0.7.0/src/Makefile.in b/yhttpd-0.7.0/src/Makefile.in
new file mode 100755
index 0000000..262f3a6
--- /dev/null
+++ b/yhttpd-0.7.0/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-0.7.0/src/cli/cli.cpp b/yhttpd-0.7.0/src/cli/cli.cpp
new file mode 100755
index 0000000..f35f77c
--- /dev/null
+++ b/yhttpd-0.7.0/src/cli/cli.cpp
@@ -0,0 +1,265 @@
+#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;
+#ifdef DEBUG
+ cout << CLIPRMO << " (d)ebug - Starts debug routine (cli.cpp)" << endl;
+#endif
+ cout << CLIPRMO << " (e)cho VAR - Prints out configuration value of VAR" << endl
+ << CLIPRMO << " Wildcards can be used too, example: echo HTML*" << endl
+ << CLIPRMO << " (h)elp - Prints out this help!" << endl
+ << CLIPRMO << " (m)ysql - Runs MySQL client on yhttpd DB" << endl;
+#ifdef NCURSES
+ cout << CLIPRMO << " (q)uit - Quits CLI mode and respawns ncurses mode" << endl;
+#endif
+ cout << CLIPRMO << " (rel)oad - Reloads all modules" << 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
+ << CLIPRMO << " (unl)oad - Unloads all loaded modules" << endl
+ << CLIPRMO << " (u)nset VAR - Deltetes configuration value VAR" << endl
+ << CLIPRMO << " (v)ersion - Prints out version" << endl;
+ 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("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;
+ }
+ else if( s_input.compare("mysql") == 0 || s_input.compare("m") == 0 )
+ {
+ cout << CLIPRMO << CLIMSQL << endl;
+ system((wrap::CONF->get_elem("chat.system.mysqlclient") + " -p -h " +
+ wrap::CONF->get_elem("chat.database.serverhost") + " -u " +
+ wrap::CONF->get_elem("chat.database.user") ).c_str());
+ cout << CLIPRMO << CLIWELC << endl;
+ cout << CLIPRMI;
+ }
+#ifdef NCURSES
+ else if( s_input.compare("quit") == 0 || s_input.compare("q") == 0 )
+ {
+ return 0;
+ }
+#endif
+ else if( s_input.compare("reload") == 0 || s_input.compare("rel") == 0 )
+ {
+ cout << CLIPRMO;
+ wrap::MODL->reload_modules();
+ cout << CLIPRMI;
+ }
+#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("unl") == 0 || s_input.compare("unload") == 0 ) {
+ cout << CLIPRMO;
+ wrap::MODL->unload_modules();
+ 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;
+}
+
+#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-0.7.0/src/cli/cli.h b/yhttpd-0.7.0/src/cli/cli.h
new file mode 100755
index 0000000..2c37c17
--- /dev/null
+++ b/yhttpd-0.7.0/src/cli/cli.h
@@ -0,0 +1,54 @@
+#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
+
+using namespace std;
+
+class cli
+#ifndef NCURSES
+: public thro
+#endif
+{
+private:
+ int parse_input( string s_input );
+
+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-0.7.0/src/conf/conf.cpp b/yhttpd-0.7.0/src/conf/conf.cpp
new file mode 100755
index 0000000..99347e9
--- /dev/null
+++ b/yhttpd-0.7.0/src/conf/conf.cpp
@@ -0,0 +1,155 @@
+// class conf implementation.
+
+#ifndef CONF_CPP
+#define CONF_CPP
+
+#include <fstream>
+#include "conf.h"
+
+using namespace std;
+
+conf::conf( string s_conf, map<string,string>* p_start_params ) : nmap<string,string>::nmap(HMAPOCC), 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);
+
+ nmap<string,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_start_params->begin(); iter != p_start_params->end(); iter++ )
+ {
+ nmap<string,string>::del_elem_insecure(iter->first);
+ nmap<string,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(),"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
+
+ nmap<string,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
+ nmap<string,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);
+ }
+}
+
+#endif
diff --git a/yhttpd-0.7.0/src/conf/conf.h b/yhttpd-0.7.0/src/conf/conf.h
new file mode 100755
index 0000000..7508872
--- /dev/null
+++ b/yhttpd-0.7.0/src/conf/conf.h
@@ -0,0 +1,27 @@
+// class conf declaration. this class parses the server config file.
+
+#ifndef CONF_H
+#define CONF_H
+
+class conf;
+
+#include "../incl.h"
+#include "../maps/nmap.h"
+#include "../name.h"
+#include "../contrib/xml/tinyxml.h"
+
+using namespace std;
+
+class conf : public nmap<string,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 );
+ conf ( string s_conf, map<string,string>* p_start_params );
+ ~conf();
+};
+
+#endif
diff --git a/yhttpd-0.7.0/src/conf/lang.cpp b/yhttpd-0.7.0/src/conf/lang.cpp
new file mode 100755
index 0000000..04dd13b
--- /dev/null
+++ b/yhttpd-0.7.0/src/conf/lang.cpp
@@ -0,0 +1,67 @@
+#ifndef LANG_CPP
+#define LANG_CPP
+
+#include <fstream>
+#include "lang.h"
+
+using namespace std;
+
+lang::lang( string s_lang = "en" ) : nmap<string,string>::nmap(HMAPOCC), name::name( s_lang )
+{
+ parse( ); // parse the config file.
+}
+
+lang::~lang()
+{}
+
+void
+lang::parse()
+{
+ // wrap::system_message( CFILEOK + get_name() );
+
+ string filename(wrap::CONF->get_elem("LANGUAGE_DIR"));
+ filename.append(get_name()+".txt");
+
+ ifstream fs_conf( filename.c_str() );
+
+ if ( ! fs_conf )
+ {
+ // wrap::system_message( CFILEOFF + get_name() );
+ return;
+ }
+
+ char c_buf[READBUF];
+
+ while( fs_conf.getline( c_buf, READBUF ) )
+ {
+ string s_token( c_buf );
+ unsigned int ui_pos = s_token.find( "#", 0 );
+
+ // if line is commented out:
+ if ( ui_pos == 0 )
+ continue;
+
+ ui_pos = s_token.find( ";", 0 );
+
+ // if token has not been found.
+ if ( ui_pos == string::npos )
+ continue;
+
+ s_token = s_token.substr( 0 , --ui_pos );
+ ui_pos = s_token.find ( "\"", 0 );
+
+ if ( ui_pos == string::npos )
+ continue;
+
+ string s_val = s_token.substr( ui_pos+1, s_token.length() );
+ string s_key = s_token.substr( 0 , --ui_pos );
+
+ // fill the map.
+ nmap<string,string>::add_elem(s_val, s_key );
+ }
+
+ fs_conf.close();
+ fs_conf.~ifstream();
+}
+
+#endif
diff --git a/yhttpd-0.7.0/src/conf/lang.h b/yhttpd-0.7.0/src/conf/lang.h
new file mode 100755
index 0000000..6230e2f
--- /dev/null
+++ b/yhttpd-0.7.0/src/conf/lang.h
@@ -0,0 +1,23 @@
+#include "../incl.h"
+
+#ifndef LANG_H
+#define LANG_H
+
+#include "../name.h"
+#include "../maps/nmap.h"
+
+using namespace std;
+
+class lang : public nmap<string,string>, name
+{
+private:
+
+public:
+ // public methods:
+ lang ( string s_lang ); // standard constructor.
+ ~lang(); // standard destructor.
+
+ virtual void parse( ); // parses the config file.
+};
+
+#endif
diff --git a/yhttpd-0.7.0/src/configure b/yhttpd-0.7.0/src/configure
new file mode 100755
index 0000000..c68183c
--- /dev/null
+++ b/yhttpd-0.7.0/src/configure
@@ -0,0 +1,248 @@
+#!/bin/sh
+#
+# The yhttpd Project (2003 - 2004)
+#
+
+if ! which perl >/dev/null
+then
+ echo You need to have Perl in your PATH
+ 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"
+ );
+
+ my @libs = (
+ "libncurses.so"
+ );
+
+ 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;
+ }
+ }
+ }
+
+ 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;
+
+ my @headerpaths = (
+ $ENV{HOME}."/include",
+ $ENV{HOME}."/usr/include",
+ "/include",
+ "/usr/include",
+ "/usr/local/include",
+ "/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"
+ );
+
+ 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};
+ }
+
+ sub check {
+ my $deep = shift;
+
+ if ($deep == 0) {
+ print "Looking too deep! ($deepness)\n";
+ exit(1);
+ }
+
+ my $check = shift;
+ my $print = 1;
+ if ( $_[-1] eq "subsearch" ) {
+ $print = 0;
+ pop(@_);
+ }
+
+ print "Checking for $check... " if $print;
+ foreach (@_) {
+ if ( -f "$_/$check" ) {
+ print "OK\n";
+ return "" if $_ eq "/usr/lib" or $_ eq "/usr/include";
+ return $_;
+ }
+ }
+
+ foreach (@_) {
+ next unless -d $_;
+ opendir D, $_ or warn "$_: $!\n"; my @dir = readdir(D);
+ closedir D;
+ foreach 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";
+ exit(1);
+ }
+ return "";
+ }
+
+ map { $incadd{&check($deepness, $_, @headerpaths)}++ }
+ @headers;
+
+ map { $libadd{&check($deepness, $_, @libpaths)}++ }
+ @libs;
+
+ sub makeadd {
+ my $flag = shift;
+ my $add = shift;
+ my $ret = "";
+
+ foreach (keys %$add) {
+ next unless /.+/;
+ $ret .= "$flag$_ ";
+ }
+ return $ret;
+ }
+
+ my $incadd = &makeadd("-I", \%incadd);
+ my $libadd = &makeadd("-L", \%libadd);
+
+ foreach ( @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";
+ 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`;
+ chomp $uname;
+ 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 "";
+
+ foreach 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";
+ if ( $ofile =~ /contrib\/.+/ ) {
+ my $dirname = `dirname $ofile`;
+ print Fout "\t\@echo -n \"Compiling contributed class $ofile \"\n";
+ } else {
+ print Fout "\t\@echo -n \"Compiling base class $ofile \"\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";
+ foreach (@msgs) {
+ s/(UNAME)(.+)$/UNAME "$uname"/;
+ print F;
+ }
+ close F;
+
+ if ( -d "mods" ) {
+ chdir("mods");
+ my $cflags = "-fno-inline -fno-default-inline";
+ $cflags .= " -nostdlib" if $uname !~ /Linux/i;
+ system("echo $cflags > cflags.add");
+ system("./configure");
+ chdir("..");
+ }
+
+ exit(0);
+
+' `echo "$*" | sed "s/-//g"`
diff --git a/yhttpd-0.7.0/src/contrib/README b/yhttpd-0.7.0/src/contrib/README
new file mode 100644
index 0000000..105f25d
--- /dev/null
+++ b/yhttpd-0.7.0/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-0.7.0/src/contrib/xml/README b/yhttpd-0.7.0/src/contrib/xml/README
new file mode 100644
index 0000000..7da9dfd
--- /dev/null
+++ b/yhttpd-0.7.0/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-0.7.0/src/contrib/xml/tinyxml.cpp b/yhttpd-0.7.0/src/contrib/xml/tinyxml.cpp
new file mode 100644
index 0000000..dd1f471
--- /dev/null
+++ b/yhttpd-0.7.0/src/contrib/xml/tinyxml.cpp
@@ -0,0 +1,1427 @@
+/*
+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-0.7.0/src/contrib/xml/tinyxml.h b/yhttpd-0.7.0/src/contrib/xml/tinyxml.h
new file mode 100644
index 0000000..678bdb9
--- /dev/null
+++ b/yhttpd-0.7.0/src/contrib/xml/tinyxml.h
@@ -0,0 +1,1368 @@
+#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-0.7.0/src/contrib/xml/tinyxmlerror.cpp b/yhttpd-0.7.0/src/contrib/xml/tinyxmlerror.cpp
new file mode 100644
index 0000000..b04add7
--- /dev/null
+++ b/yhttpd-0.7.0/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-0.7.0/src/contrib/xml/tinyxmlparser.cpp b/yhttpd-0.7.0/src/contrib/xml/tinyxmlparser.cpp
new file mode 100644
index 0000000..f06d1cd
--- /dev/null
+++ b/yhttpd-0.7.0/src/contrib/xml/tinyxmlparser.cpp
@@ -0,0 +1,1493 @@
+/*
+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-0.7.0/src/glob.h b/yhttpd-0.7.0/src/glob.h
new file mode 100755
index 0000000..c134df5
--- /dev/null
+++ b/yhttpd-0.7.0/src/glob.h
@@ -0,0 +1,178 @@
+/*
+ Notice:
+
+ All #defines which start with an CONFIG can be edited through
+ gmake config in the main directory!
+*/
+
+
+#include <map>
+
+// global variables.
+#ifndef GLOB_H
+#define GLOB_H
+
+// Definition of boolean values.
+#define true 1
+#define false 0
+
+/* - CONFIG -
+ What should be the name of the config file?
+*/
+#define CONFILE "yhttpd.conf"
+
+/* - CONFIG -
+ In which prefix should yhttpd be installed if typing gmake inst-
+ all?
+*/
+#define PREFIX "/usr/local"
+
+
+/* - 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
+
+/* - CONFIG -
+ Please specify the maximum length of a line read from a socket
+ or a file. ( config-file, html-template )
+*/
+#define READSOCK 2048
+
+/* - CONFIG -
+ Please specify the size of a temporary buffer. (Will be used f-
+ or different tasks)
+*/
+#define READBUF 1024
+
+/* - CONFIG -
+ Please specify the maximum length of a HTTP post request.
+*/
+#define POSTBUF 512
+
+/* - CONFIG -
+ Please specify the maximum occupancy of the internal hash-map
+ data structures given in percentage. 0.9 means 90% iccupancy.
+*/
+#define HMAPOCC .9
+
+/* - 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 of if you have heavy server load.
+*/
+//#define VERBOSE
+
+/* - CONFIG -
+ 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 ncurses support?
+*/
+#define NCURSES
+
+/* - CONFIG -
+ Should yhttpd get compiled with comand line interface support?
+*/
+#define CLI
+
+
+/* - 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
+
+// Enables debugging options
+//#define DEBUG
+
+
+
+// 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 18
+#define NCUR_POOL_SIZE_X 22
+#define NCUR_POOL_SIZE_Y 18
+#define NCUR_POOL_RUNNING_X 23
+#define NCUR_POOL_RUNNING_Y 18
+
+#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;
+
+// some custom typedefs for datatypes which are needed often.
+typedef map<string, string> map_string;
+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-0.7.0/src/html.cpp b/yhttpd-0.7.0/src/html.cpp
new file mode 100755
index 0000000..7f1440d
--- /dev/null
+++ b/yhttpd-0.7.0/src/html.cpp
@@ -0,0 +1,129 @@
+#ifndef HTML_CPP
+#define HTML_CPP
+
+#include <fstream>
+#include "html.h"
+
+using namespace std;
+
+html::html( ) : smap<string,string>::smap(HMAPOCC)
+{
+ set_name( wrap::CONF->get_elem( "httpd.templatedir" ) );
+}
+
+html::~html( )
+{
+}
+
+void
+html::clear_cache( )
+{
+ make_empty();
+ wrap::system_message( CLRHTML );
+
+#ifdef NCURSES
+ print_cached( 0 );
+#endif
+}
+
+string
+html::parse( map_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 ( ! smap<string,string>::is_avail( s_file ) )
+ {
+ auto string s_path = get_name();
+ auto ifstream fs_templ( s_path.append( s_file ).c_str(), ios::binary );
+
+ if ( ! fs_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 );
+
+ }
+
+ auto char c_buf;
+ while( !fs_templ.eof() )
+ {
+ fs_templ.get( c_buf );
+ s_templ+=c_buf;
+ }
+
+ fs_templ.close();
+
+ wrap::system_message( TECACHE + s_path );
+
+ // cache file.
+ smap<string,string>::add_elem( s_templ, s_file );
+#ifdef NCURSES
+ print_cached( smap<string,string>::get_size() );
+#endif
+ }
+
+ else
+ {
+ s_templ = smap<string,string>::get_elem( s_file );
+ }
+
+ // find %%KEY%% token and substituate those.
+ auto unsigned int 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.
+ auto string s_key = s_templ.substr( pos[0], pos[1]-pos[0] );
+ auto 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.
+ auto int i_dif = s_val.length() - ( pos[1] - pos[0] + 4);
+
+ pos[1] += 2 + i_dif;
+
+ };
+
+ 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-0.7.0/src/html.h b/yhttpd-0.7.0/src/html.h
new file mode 100755
index 0000000..d8d2a16
--- /dev/null
+++ b/yhttpd-0.7.0/src/html.h
@@ -0,0 +1,39 @@
+// class html declaration. this class manages the html-template files.
+#include "incl.h"
+
+#ifndef HTML_H
+#define HTML_H
+
+#include "maps/smap.h"
+#include "name.h"
+
+using namespace std;
+
+class html : public smap<string, string>, name
+{
+private:
+
+public:
+ // public methods.
+ html( ); // simple constructor.
+ ~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 &map_params );
+
+#ifdef NCURSES
+ void print_cached( int i_docs );
+#endif
+};
+
+#endif
diff --git a/yhttpd-0.7.0/src/incl.h b/yhttpd-0.7.0/src/incl.h
new file mode 100755
index 0000000..d62a57f
--- /dev/null
+++ b/yhttpd-0.7.0/src/incl.h
@@ -0,0 +1,9 @@
+#include <iostream>
+#include <pthread.h>
+#include <string>
+#include "glob.h"
+#ifdef NCURSES
+#include <ncurses.h>
+#endif
+#include "msgs.h"
+#include "wrap.h"
diff --git a/yhttpd-0.7.0/src/logd.cpp b/yhttpd-0.7.0/src/logd.cpp
new file mode 100755
index 0000000..44c42e2
--- /dev/null
+++ b/yhttpd-0.7.0/src/logd.cpp
@@ -0,0 +1,157 @@
+#ifndef LOGD_CPP
+#define LOGD_CPP
+
+#include <fstream>
+#include "logd.h"
+
+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();
+ 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);
+ }
+
+ 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 request )
+{
+ string s_time = get_time_string();
+ string s_logstr = request["REMOTE_ADDR"] + " - - "+s_time+" \"" + request["QUERY_STRING"]+"\" 200 0 \""+request["request"]+"\" \""+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 )
+{
+ 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 int 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
diff --git a/yhttpd-0.7.0/src/logd.h b/yhttpd-0.7.0/src/logd.h
new file mode 100755
index 0000000..b91efe0
--- /dev/null
+++ b/yhttpd-0.7.0/src/logd.h
@@ -0,0 +1,36 @@
+#include "incl.h"
+
+#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 request );
+ void log_simple_line( string s_line );
+ void flush_logs();
+ static string remove_html_tags( string s_log );
+};
+
+
+#endif
diff --git a/yhttpd-0.7.0/src/main.cpp b/yhttpd-0.7.0/src/main.cpp
new file mode 100755
index 0000000..0948e63
--- /dev/null
+++ b/yhttpd-0.7.0/src/main.cpp
@@ -0,0 +1,159 @@
+/*
+ * yhttpd++; Contact: www.yhttpd.org; Mail@yhttpd.org
+ * Copyright (C) 2003 Paul C. Buetow, Volker Richter
+ * Copyright (C) 2004 Paul C. Buetow
+ * -----------------------------------------------------------------
+ *
+ * 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 <unistd.h>
+#include <signal.h>
+#include "incl.h"
+
+#ifndef NCURSES
+#ifdef CLI
+#include "cli/cli.h"
+#endif
+#endif
+
+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( "Usage: ./yhttpd {h|v}|{o confkey confvalue}\n" );
+ if ( string(argv[i]).find("o") != string::npos )
+ b_conf = 1;
+ }
+ }
+
+ if ( s_output.compare("") != 0 )
+ {
+ cout << s_output;
+ delete start_params;
+ exit(0);
+ }
+
+ return start_params;
+}
+
+int
+main(int argc, char* argv[])
+{
+ map<string,string>* p_start_params = parse_argc( argc, argv );
+
+ cout << tool::yhttpd_version() << endl
+ << DESCRIP << endl
+ << DESCRI2 << endl
+ << CONTACT << endl
+ << SEPERAT << endl;
+
+ // 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 );
+
+ // all the static data classes have to be initialized once. otherwise they will
+ // contain only empty pointers and the chat server won't work correctly.
+ // the order of the initializations is very importand. for example the s_html::init()
+ // invokations assumes an initialized s_conf class.
+ // begin to draw the ncurses amdin interface in a new pthread.
+
+ // init the dynamic wrapper (is needed to pass all wrapped objects through a single pointer).
+ wrap::WRAP = new dynamic_wrap;
+
+ // init the config manager.
+ wrap::WRAP->CONF = wrap::CONF = new conf( CONFILE, p_start_params );
+ delete p_start_params,
+
+
+ // init the statistic manager.
+ wrap::WRAP->STAT = wrap::STAT = new stats;
+
+ // init the html-template manager.
+ wrap::WRAP->HTML = wrap::HTML = new html;
+
+ // init the system message logd
+ wrap::WRAP->LOGD = wrap::LOGD = new logd( wrap::CONF->get_elem("httpd.logging.systemfile"),
+ wrap::CONF->get_elem("httpd.logging.systemlines") );
+
+
+ // init the socket manager.
+ wrap::WRAP->SOCK = wrap::SOCK = new sock;
+
+#ifdef NCURSES
+ wrap::WRAP->NCUR = wrap::NCUR = new ncur; // init the ncurses admin interface.
+ wrap::NCUR->run(); // run the thread
+
+ // wait until ncurses interface has been initialized.
+ while ( ! wrap::NCUR->is_ready() )
+ usleep(1000);
+#endif
+
+
+ // init the system timer.
+ wrap::WRAP->TIMR = wrap::TIMR = new timr;
+ wrap::TIMR->run(); // run the thread
+
+ // init the module-loader manager.
+ wrap::WRAP->MODL = wrap::MODL = new modl;
+
+
+#ifndef NCURSES
+#ifdef CLI
+ cli* p_cli = new cli;
+ p_cli->run();
+#endif
+#endif
+
+
+ // 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-0.7.0/src/maps/hmap.h b/yhttpd-0.7.0/src/maps/hmap.h
new file mode 100644
index 0000000..a0824ec
--- /dev/null
+++ b/yhttpd-0.7.0/src/maps/hmap.h
@@ -0,0 +1,100 @@
+#pragma warning(disable:4786)
+
+#include "../incl.h"
+
+#ifndef HMAP_H
+#define HMAP_H
+
+#include <vector>
+
+using namespace std;
+
+// void add_elem( obj_type x, key_type k ) --> Insert x
+// void del_elem( key_type k ) --> Remove x
+// obj_type get_elem( key_type k ) --> Return item that matches x
+// void make_empty( ) --> Remove all items
+
+template <class obj_type, class key_type>
+class hmap
+{
+protected:
+ enum entry_type
+ {
+ ACTIVE, EMPTY, DELETED
+ };
+
+ struct hash_entry
+ {
+ obj_type element;
+ key_type key;
+ entry_type info;
+ int hits;
+
+ hash_entry( const obj_type &e = obj_type( ), const key_type &k = key_type( ), entry_type i = EMPTY ) : element( e ), key( k ), info( i )
+ { }
+ }
+ ;
+
+ int occupied;
+
+ virtual bool is_active( int i_current_pos ) const;
+ virtual void rehash( );
+ virtual bool is_prime ( int n ) const;
+ virtual int next_prime( int n ) const;
+ double i_max_occupied_percentage;
+
+ int lookups;
+ virtual unsigned int hash( const string &key ) const;
+ vector<hash_entry> array;
+
+ int get_lookups()
+ {
+ return lookups;
+ };
+
+ int get_capacity()
+ {
+ return array.size();
+ };
+
+ double get_lambda()
+ {
+ return static_cast<double>(get_size())/static_cast<double>(get_capacity());
+ }
+
+ obj_type& operator[]( key_type &k )
+ {
+ return get_elem( k );
+ }
+
+ int find_pos ( const key_type &k );
+
+public:
+ hmap( double moc );
+ ~hmap( );
+
+ virtual int get_size();
+ virtual void make_empty( );
+ virtual void make_empty( void (*func)(key_type) );
+ virtual void del_elem ( const key_type &k );
+ virtual obj_type set_elem ( const obj_type &x, const key_type &k );
+
+ virtual void run_func( void (*func)(obj_type) );
+ virtual void run_func( void (*func)(obj_type, void*), void* v_arg );
+ virtual void run_func_on( void (*func)(obj_type), const key_type & k );
+ virtual vector<key_type>* get_key_vector( );
+
+ virtual void add_elem ( const obj_type &x, const key_type &k );
+
+ virtual bool is_avail( const key_type &k );
+ virtual obj_type pop_elem ( const key_type &k );
+ virtual obj_type get_elem ( const key_type &k );
+ virtual obj_type operator[]( const key_type &k ) {
+ return get_elem( k );
+ }
+
+};
+
+#include "hmap.tmpl"
+
+#endif
diff --git a/yhttpd-0.7.0/src/maps/hmap.tmpl b/yhttpd-0.7.0/src/maps/hmap.tmpl
new file mode 100644
index 0000000..10facac
--- /dev/null
+++ b/yhttpd-0.7.0/src/maps/hmap.tmpl
@@ -0,0 +1,282 @@
+#ifndef HMAP_CPP
+#define HMAP_CPP
+
+#include "hmap.h"
+
+using namespace std;
+
+bool is_prime( int n );
+int next_prime( int n );
+
+// Construct the hash table.
+template <class obj_type, class key_type>
+hmap<obj_type, key_type>::hmap( double mop )
+ : i_max_occupied_percentage(mop), array( next_prime( 101 ) )
+{
+ lookups = 0;
+ make_empty( );
+}
+
+template <class obj_type, class key_type>
+hmap<obj_type, key_type>::~hmap( )
+{
+ make_empty( );
+}
+
+// Insert item x into the hash table. If the item is
+// already present, do nothing
+template <class obj_type, class key_type>
+void hmap<obj_type, key_type>::add_elem( const obj_type &x, const key_type &k )
+{
+ // Insert x as active
+ int i_current_pos = find_pos( k );
+ if( is_active( i_current_pos ) )
+ return;
+
+ array[ i_current_pos ] = hash_entry( x, k, ACTIVE );
+ if( ++occupied > array.size( ) * i_max_occupied_percentage )
+ rehash( );
+}
+
+// Expand the hash table.
+template <class obj_type, class key_type>
+void hmap<obj_type, key_type>::rehash( )
+{
+ vector<hash_entry> old_array = array;
+
+ // Create new double-sized, empty table
+ array.resize( next_prime( 2 * old_array.size( ) ) );
+ for( int j = 0; j < array.size( ); j++ )
+ {
+ array[ j ].info = EMPTY;
+ }
+
+ // Copy table over
+ make_empty( );
+ for( int i = 0; i < old_array.size( ); i++ )
+ if( old_array[ i ].info == ACTIVE )
+ add_elem( old_array[ i ].element, old_array[ i ].key );
+}
+
+// Hash function, can only handle strings.
+// If you want to hash other objects you will have to
+// create a hash table for them
+template <class obj_type, class key_type>
+unsigned int hmap<obj_type, key_type>::hash( const string & key ) const
+{
+ unsigned int hash_value = 0;
+ // cout << key << "%";
+
+ for( size_t i = 0; i < key.size(); i++ )
+ hash_value = ( hash_value << 5 ) ^ key[ i ] ^ hash_value;
+
+ return hash_value;
+}
+
+// Method that performs quadratic probing resolution.
+// Return the position where the search for x terminates.
+template <class obj_type, class key_type>
+int hmap<obj_type, key_type>::find_pos( const key_type &k )
+{
+ int i_collision_num = 0;
+ int i_current_pos = hash( k ) % array.size( );
+ lookups++;
+
+ while( array[ i_current_pos ].info != EMPTY &&
+ array[ i_current_pos ].key != k )
+ {
+ lookups++;
+ i_current_pos += 2 * ++i_collision_num - 1; // Compute ith probe
+
+ if( i_current_pos >= array.size( ) )
+ i_current_pos -= array.size( );
+ }
+
+ return i_current_pos;
+}
+
+// Remove item x from the hash table.
+template <class obj_type, class key_type>
+void hmap<obj_type, key_type>::del_elem( const key_type & k )
+{
+ int i_current_pos = find_pos( k );
+ if( is_active( i_current_pos ) )
+ array[ i_current_pos ].info = DELETED;
+}
+
+// Finds item x and resets its value.
+template <class obj_type, class key_type>
+obj_type hmap<obj_type, key_type>::set_elem( const obj_type & x, const key_type & k )
+{
+ int i_current_pos = find_pos( k );
+ obj_type ret_elem;
+
+ if( is_active( i_current_pos ) )
+ {
+ ret_elem = array[ i_current_pos ].element;
+ array[ i_current_pos ].element = x;
+ }
+
+ else
+ {
+ add_elem( x, k );
+ }
+
+ return ret_elem;
+}
+
+// Find item x in the hash table.
+// Return a pointer to the matching item or 0 if not found
+template <class obj_type, class key_type>
+obj_type hmap<obj_type, key_type>::get_elem( const key_type &k )
+{
+ int i_current_pos = find_pos( k );
+ if( is_active( i_current_pos ) )
+ {
+ array[i_current_pos ].hits++;
+ return array[i_current_pos].element;
+ }
+
+ return NULL;
+}
+
+template <class obj_type, class key_type>
+obj_type hmap<obj_type, key_type>::pop_elem( const key_type &k )
+{
+ int i_current_pos = find_pos( k );
+ if( is_active( i_current_pos ) )
+ {
+ array[ i_current_pos ].info = DELETED;
+ return array[i_current_pos].element;
+ }
+
+ return NULL;
+}
+
+template <class obj_type, class key_type>
+bool hmap<obj_type, key_type>::is_avail( const key_type &k )
+{
+ int i_current_pos = find_pos( k );
+ if( is_active( i_current_pos ) )
+ return 1;
+ else
+ return 0;
+}
+
+// Make the hash table logically empty.
+template <class obj_type, class key_type>
+void hmap<obj_type, key_type>::make_empty( )
+{
+ occupied = 0;
+ for( int i = 0; i < array.size( ); i++ )
+ array[i].info = EMPTY;
+}
+
+template <class obj_type, class key_type>
+void hmap<obj_type, key_type>::make_empty( void (*func)(key_type) )
+{
+ occupied = 0;
+ for( int i = 0; i < array.size( ); i++ )
+ if ( array[ i ].info != EMPTY )
+ {
+ array[ i ].info = EMPTY;
+ ( *func ) ( array[ i ].key );
+ }
+}
+
+// Return true if i_current_pos exists and is active.
+template <class obj_type, class key_type>
+bool hmap<obj_type, key_type>::is_active( int i_current_pos ) const
+{
+ return array[ i_current_pos ].info == ACTIVE;
+}
+
+
+// Internal method to test if a positive number is prime.
+// Not an efficient algorithm.
+template <class obj_type, class key_type>
+bool hmap<obj_type, key_type>::is_prime( int n ) const
+{
+ if( n == 2 || n == 3 )
+ return true;
+
+ else if( n == 1 || n % 2 == 0 )
+ return false;
+
+ for( int i = 3; i * i <= n; i += 2 )
+ if( n % i == 0 )
+ return false;
+
+ return true;
+}
+
+// Internal method to return a prime number at least as large as n.
+// Assumes n > 0.
+template <class obj_type, class key_type>
+int hmap<obj_type, key_type>::next_prime( int n ) const
+{
+ if( n % 2 == 0 )
+ n++;
+
+ for( ; !is_prime( n ); n += 2 ) ;
+
+ return n;
+}
+
+template<class obj_type, class key_type>
+void
+hmap<obj_type, key_type>::run_func( void (*func)(obj_type) )
+{
+ for( int i = 0; i < array.size( ); i++ )
+ if ( array[i].info == ACTIVE )
+ ( *func ) ( array[i].element );
+}
+
+template<class obj_type, class key_type>
+void
+hmap<obj_type, key_type>::run_func( void (*func)(obj_type, void*), void* v_arg )
+{
+ for( int i = 0; i < array.size( ); i++ )
+ if ( array[i].info == ACTIVE )
+ ( *func ) ( array[i].element, v_arg );
+}
+
+template<class obj_type, class key_type>
+void
+hmap<obj_type, key_type>::run_func_on( void (*func)(obj_type), const key_type & k )
+{
+ int i_current_pos = find_pos( k );
+ if( is_active( i_current_pos ) )
+ ( *func ) ( array[i_current_pos].element );
+}
+
+
+template<class obj_type, class key_type>
+vector<key_type>*
+hmap<obj_type, key_type>::get_key_vector()
+{
+ vector<key_type>* p_vec = new vector<key_type>;
+ for( int i = 0; i < array.size( ); i++ )
+ if ( array[i].info == ACTIVE )
+ p_vec->push_back( array[i].key );
+
+ return p_vec;
+}
+
+
+template<class obj_type, class key_type> int
+hmap<obj_type, key_type>::get_size()
+{
+ int size = 0;
+ for( int j = 0; j < array.size( ); j++ )
+ if (array[ j ].info == ACTIVE)
+ size++;
+
+ return size;
+}
+
+
+
+
+#endif
+
diff --git a/yhttpd-0.7.0/src/maps/mtools.h b/yhttpd-0.7.0/src/maps/mtools.h
new file mode 100644
index 0000000..f32a49e
--- /dev/null
+++ b/yhttpd-0.7.0/src/maps/mtools.h
@@ -0,0 +1,15 @@
+#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-0.7.0/src/maps/mtools.tmpl b/yhttpd-0.7.0/src/maps/mtools.tmpl
new file mode 100644
index 0000000..dd3f89e
--- /dev/null
+++ b/yhttpd-0.7.0/src/maps/mtools.tmpl
@@ -0,0 +1,11 @@
+#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-0.7.0/src/maps/nmap.h b/yhttpd-0.7.0/src/maps/nmap.h
new file mode 100644
index 0000000..56d30f5
--- /dev/null
+++ b/yhttpd-0.7.0/src/maps/nmap.h
@@ -0,0 +1,25 @@
+#include "../incl.h"
+
+#ifndef NMAP_H
+#define NMAP_H
+
+#include "smap.h"
+
+template <class obj_type, class key_type>
+class nmap : public smap<obj_type, key_type>
+{
+ public:
+ nmap( double moc );
+ ~nmap();
+
+ // Override the get_elem method so that a new object
+ // will be returned if the required element is not in
+ // the map!
+ obj_type get_elem ( const key_type &k );
+};
+
+#include "nmap.tmpl"
+
+#endif
+
+
diff --git a/yhttpd-0.7.0/src/maps/nmap.tmpl b/yhttpd-0.7.0/src/maps/nmap.tmpl
new file mode 100644
index 0000000..6fdea2f
--- /dev/null
+++ b/yhttpd-0.7.0/src/maps/nmap.tmpl
@@ -0,0 +1,31 @@
+#ifndef NMAP_CPP
+#define NMAP_CPP
+
+#include "nmap.h"
+
+template <class obj_type, class key_type>
+nmap<obj_type, key_type>::nmap( double moc ) : smap<obj_type, key_type>::smap(moc)
+{
+}
+
+template <class obj_type, class key_type>
+nmap<obj_type, key_type>::~nmap()
+{
+}
+
+template <class obj_type, class key_type>
+obj_type nmap<obj_type, key_type>::get_elem ( const key_type &k ) {
+ // Create new object;
+ obj_type ret_val;
+
+ smap<obj_type, key_type>::lock_mutex();
+ int i_current_pos = find_pos( k );
+ if( smap<obj_type, key_type>::is_active( i_current_pos ) )
+ ret_val = smap<obj_type, key_type>::array[ i_current_pos ].element;
+ // else
+ // ret_val = new obj_type();
+ smap<obj_type, key_type>::unlock_mutex();
+ return ret_val;
+}
+
+#endif
diff --git a/yhttpd-0.7.0/src/maps/smap.h b/yhttpd-0.7.0/src/maps/smap.h
new file mode 100644
index 0000000..e056519
--- /dev/null
+++ b/yhttpd-0.7.0/src/maps/smap.h
@@ -0,0 +1,56 @@
+// smap := Syncronized hmap
+// nmap := Syncronized hmap which's get_elem returns a new obj_type
+// instance instead of NULL if for a specific key no value has
+// been found
+
+#include "../incl.h"
+
+#ifndef SMAP_H
+#define SMAP_H
+
+#include "hmap.h"
+
+template <class obj_type, class key_type>
+class smap : public hmap<obj_type, key_type>
+{
+
+ private:
+ pthread_mutex_t mut_smap;
+
+ protected:
+ void lock_mutex();
+ void unlock_mutex();
+
+ public:
+ smap( double moc );
+ ~smap();
+ int get_size();
+ void make_empty();
+ void make_empty( void (*func)(key_type) );
+ void add_elem ( const obj_type &x, const key_type &k );
+ obj_type set_elem ( const obj_type &x, const key_type &k );
+ void del_elem ( const key_type &k );
+ bool is_avail ( const key_type &k );
+ obj_type get_elem ( const key_type &k );
+ obj_type pop_elem ( const key_type &k );
+ void run_func( void (*func)(obj_type) );
+ void run_func( void (*func)(obj_type, void*), void* v_arg );
+ void run_func_on( void (*func)(obj_type), const key_type &k );
+ vector<key_type>* get_key_vector();
+
+ int get_size_insecure();
+ void make_empty_insecure();
+ void make_empty_insecure( void (*func)(key_type) );
+ void add_elem_insecure ( const obj_type &x, const key_type &k );
+ void del_elem_insecure ( const key_type &k );
+ bool is_avail_insecure ( const key_type &k );
+ obj_type get_elem_insecure ( const key_type &k );
+ obj_type pop_elem_insecure ( const key_type &k );
+ void run_func_insecure( void (*func)(obj_type) );
+ void run_func_insecure( void (*func)(obj_type, void*), void* v_arg );
+ vector<key_type>* get_key_vector_insecure();
+};
+
+#include "smap.tmpl"
+
+#endif
diff --git a/yhttpd-0.7.0/src/maps/smap.tmpl b/yhttpd-0.7.0/src/maps/smap.tmpl
new file mode 100644
index 0000000..3167504
--- /dev/null
+++ b/yhttpd-0.7.0/src/maps/smap.tmpl
@@ -0,0 +1,211 @@
+#ifndef SMAP_CPP
+#define SMAP_CPP
+
+#include "smap.h"
+
+template <class obj_type, class key_type>
+smap<obj_type, key_type>::smap( double moc ) : hmap<obj_type, key_type>::hmap(moc)
+{
+ pthread_mutex_init( &mut_smap , NULL);
+}
+
+template <class obj_type, class key_type>
+smap<obj_type, key_type>::~smap()
+{
+ pthread_mutex_destroy( &mut_smap );
+}
+
+
+template <class obj_type, class key_type> void
+smap<obj_type, key_type>::lock_mutex() {
+ pthread_mutex_lock( &mut_smap );
+}
+
+template <class obj_type, class key_type> void
+smap<obj_type, key_type>::unlock_mutex() {
+ pthread_mutex_unlock( &mut_smap );
+}
+
+template <class obj_type, class key_type> int
+smap<obj_type, key_type>::get_size()
+{
+ int i_size;
+ pthread_mutex_lock ( &mut_smap );
+ i_size = hmap<obj_type,key_type>::get_size();
+ pthread_mutex_unlock( &mut_smap );
+ return i_size;
+}
+
+template <class obj_type, class key_type> void
+smap<obj_type, key_type>::make_empty()
+{
+ pthread_mutex_lock ( &mut_smap );
+ hmap<obj_type,key_type>::make_empty();
+ pthread_mutex_unlock( &mut_smap );
+}
+
+template <class obj_type, class key_type>
+void smap<obj_type, key_type>::make_empty( void (*func)(key_type) )
+{
+ pthread_mutex_lock ( &mut_smap );
+ hmap<obj_type,key_type>::make_empty( func );
+ pthread_mutex_unlock( &mut_smap );
+}
+
+
+template <class obj_type, class key_type>
+void smap<obj_type, key_type>::add_elem( const obj_type &x, const key_type &k )
+{
+ pthread_mutex_lock ( &mut_smap );
+ hmap<obj_type,key_type>::add_elem( x, k );
+ pthread_mutex_unlock( &mut_smap );
+}
+
+template <class obj_type, class key_type>
+obj_type smap<obj_type, key_type>::set_elem( const obj_type &x, const key_type &k )
+{
+ pthread_mutex_lock ( &mut_smap );
+ hmap<obj_type,key_type>::set_elem( x, k );
+ pthread_mutex_unlock( &mut_smap );
+}
+
+template <class obj_type, class key_type> void
+smap<obj_type, key_type>::del_elem( const key_type & k )
+{
+ pthread_mutex_lock ( &mut_smap );
+ hmap<obj_type,key_type>::del_elem( k );
+ pthread_mutex_unlock( &mut_smap );
+}
+
+
+template <class obj_type, class key_type>
+obj_type smap<obj_type, key_type>::get_elem( const key_type &k )
+{
+ pthread_mutex_lock ( &mut_smap );
+ obj_type ret_val = hmap<obj_type,key_type>::get_elem( k );
+ pthread_mutex_unlock( &mut_smap );
+ return ret_val;
+}
+template <class obj_type, class key_type>
+obj_type smap<obj_type, key_type>::pop_elem( const key_type &k )
+{
+ pthread_mutex_lock ( &mut_smap );
+ obj_type ret_val = hmap<obj_type,key_type>::pop_elem( k );
+ pthread_mutex_unlock( &mut_smap );
+ return ret_val;
+}
+
+template <class obj_type, class key_type>
+bool smap<obj_type, key_type>::is_avail( const key_type &k )
+{
+ pthread_mutex_lock ( &mut_smap );
+ bool ret_val = hmap<obj_type,key_type>::is_avail( k );
+ pthread_mutex_unlock( &mut_smap );
+ return ret_val;
+}
+
+template<class obj_type, class key_type> void
+smap<obj_type, key_type>::run_func( void (*func)(obj_type) )
+{
+ pthread_mutex_lock ( &mut_smap );
+ hmap<obj_type,key_type>::run_func( func );
+ pthread_mutex_unlock( &mut_smap );
+}
+
+template<class obj_type, class key_type> void
+smap<obj_type, key_type>::run_func( void (*func)(obj_type, void*), void* v_arg )
+{
+ pthread_mutex_lock ( &mut_smap );
+ hmap<obj_type,key_type>::run_func( func, v_arg );
+ pthread_mutex_unlock( &mut_smap );
+}
+
+template<class obj_type, class key_type> void
+smap<obj_type, key_type>::run_func_on( void (*func)(obj_type), const key_type & k )
+{
+ pthread_mutex_lock ( &mut_smap );
+ hmap<obj_type,key_type>::run_func_on( func, k );
+ pthread_mutex_unlock( &mut_smap );
+}
+
+template<class obj_type, class key_type> vector<key_type>*
+smap<obj_type, key_type>::get_key_vector()
+{
+ pthread_mutex_lock ( &mut_smap );
+ vector<key_type>* p_ret_vector = hmap<obj_type,key_type>::get_key_vector();
+ pthread_mutex_unlock( &mut_smap );
+ return p_ret_vector;
+}
+
+// INSECURE METHODS
+
+template <class obj_type, class key_type> int
+smap<obj_type, key_type>::get_size_insecure()
+{
+ return hmap<obj_type,key_type>::get_size();
+}
+
+template <class obj_type, class key_type> void
+smap<obj_type, key_type>::make_empty_insecure()
+{
+ hmap<obj_type,key_type>::make_empty();
+}
+
+template <class obj_type, class key_type>
+void smap<obj_type, key_type>::make_empty_insecure( void (*func)(key_type) )
+{
+ hmap<obj_type,key_type>::make_empty( func );
+}
+
+
+template <class obj_type, class key_type>
+void smap<obj_type, key_type>::add_elem_insecure( const obj_type &x, const key_type &k )
+{
+ hmap<obj_type,key_type>::add_elem( x, k );
+}
+
+template <class obj_type, class key_type> void
+smap<obj_type, key_type>::del_elem_insecure( const key_type & k )
+{
+ hmap<obj_type,key_type>::del_elem( k );
+}
+
+template <class obj_type, class key_type>
+obj_type smap<obj_type, key_type>::get_elem_insecure( const key_type &k )
+{
+ return hmap<obj_type,key_type>::get_elem( k );
+}
+
+template <class obj_type, class key_type>
+obj_type smap<obj_type, key_type>::pop_elem_insecure( const key_type &k )
+{
+ return hmap<obj_type,key_type>::pop_elem( k );
+}
+
+template <class obj_type, class key_type>
+bool smap<obj_type, key_type>::is_avail_insecure( const key_type &k )
+{
+ return hmap<obj_type,key_type>::is_avail( k );
+}
+
+template<class obj_type, class key_type> void
+smap<obj_type, key_type>::run_func_insecure( void (*func)(obj_type) )
+{
+ hmap<obj_type,key_type>::run_func( func );
+}
+
+template<class obj_type, class key_type> void
+smap<obj_type, key_type>::run_func_insecure( void (*func)(obj_type, void*), void* v_arg )
+{
+ hmap<obj_type,key_type>::run_func( func, v_arg );
+}
+
+template<class obj_type, class key_type> vector<key_type>*
+smap<obj_type, key_type>::get_key_vector_insecure()
+{
+ return hmap<obj_type,key_type>::get_key_vector();
+}
+
+
+#endif
+
diff --git a/yhttpd-0.7.0/src/modl.cpp b/yhttpd-0.7.0/src/modl.cpp
new file mode 100755
index 0000000..ca620ce
--- /dev/null
+++ b/yhttpd-0.7.0/src/modl.cpp
@@ -0,0 +1,161 @@
+#ifndef MODL_CPP
+
+#define MODL_CPP
+
+#include <limits.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <stdio.h>
+
+#include "modl.h"
+#include "tool/dir.h"
+
+using namespace std;
+
+modl::modl( ) : smap<dynmod*,string>(HMAPOCC)
+{
+#ifdef NCURSES
+ print_cached( 0 );
+#endif
+
+ if ( wrap::CONF->get_elem( "httpd.modules.preloadcommands" ).compare( "true" ) == 0 )
+ preload_modules( wrap::CONF->get_elem("httpd.modules.commandsdir") );
+
+ if ( wrap::CONF->get_elem( "httpd.modules.preloadhtml" ).compare( "true" ) == 0 )
+ preload_modules( wrap::CONF->get_elem("httpd.modules.htmldir") );
+}
+
+modl::~modl()
+{
+ // dlclose all the_module's first!
+ run_func( &modl::dlclose_ );
+
+ // then clean the hash map.
+ unload_modules();
+}
+
+void
+modl::preload_modules( string s_path )
+{
+ dir* p_dir = new dir();
+ p_dir->open_dir( s_path );
+
+ p_dir->read_dir();
+
+ vector<string> dir_vec = p_dir->get_dir_vec();
+
+ if ( ! dir_vec.empty() )
+ {
+ vector<string>::iterator iter = dir_vec.begin();
+
+ do
+ {
+ if ( iter->length() >= 3 && iter->compare( iter->length()-3, 3, ".so" ) == 0 )
+ cache_module( s_path + *iter );
+ }
+ while ( ++iter != dir_vec.end() );
+ }
+
+ dir_vec.clear();
+
+ // This also closes the dir.
+ delete p_dir;
+}
+
+void
+modl::dlclose_( dynmod* mod )
+{
+ dlclose( mod->the_module );
+ free ( mod );
+}
+
+dynmod*
+modl::cache_module( string s_name )
+{
+ void *the_module = NULL;
+ function *the_func = NULL;
+
+ the_module = dlopen( s_name.c_str(), RTLD_LAZY );
+ //the_module = dlopen( s_name.c_str(), RTLD_NOW );
+
+ if ( the_module == NULL )
+ {
+ wrap::system_message( dlerror() );
+ return NULL;
+ }
+
+ the_func = (function*) dlsym( the_module, "extern_function" );
+
+ if ( the_func == NULL )
+ {
+ wrap::system_message( dlerror() );
+ return NULL;
+ }
+
+ wrap::system_message( MODULEC + s_name.substr( s_name.find_last_of("/")+1 ) );
+
+
+ dynmod *mod = new dynmod; // encapsulates the function and module handler.
+ mod->the_func = the_func ; // the function to execute
+ mod->the_module = the_module; // the module handler to close if function
+
+ // is not needed anymore.
+ add_elem( mod, s_name );
+
+ // DO NOT CLOSE AS LONG THERE EXIST A POINTER TO THE FUNCTION
+ // dlclose( module ); will be called in modl::~modl()!
+
+#ifdef NCURSES
+ print_cached( get_size() );
+#endif
+
+ return mod;
+}
+
+dynmod*
+modl::get_module( string s_name )
+{
+ wrap::system_message( MODULER + s_name.substr( s_name.find_last_of("/")+1 ) );
+ dynmod* mod = get_elem( s_name );
+ return ! mod ? cache_module( s_name ) : mod;
+}
+
+void
+modl::unload_modules()
+{
+ wrap::system_message( MODUNLO );
+
+ // dlclose all the_module's first!
+ run_func( &modl::dlclose_ );
+
+ // then clean the hash map.
+ make_empty();
+
+#ifdef NCURSES
+ print_cached( get_size() );
+#endif
+
+}
+
+void
+modl::reload_modules()
+{
+ unload_modules();
+
+ wrap::system_message( MODRELO );
+ preload_modules( wrap::CONF->get_elem("httpd.modules.commandsdir") );
+ preload_modules( wrap::CONF->get_elem("httpd.modules.htmldir") );
+}
+#ifdef NCURSES
+void
+modl::print_cached( int i_mods )
+{
+ if ( !wrap::NCUR->is_ready() )
+ return;
+
+ mvprintw( NCUR_CACHED_MODS_X, NCUR_CACHED_MODS_Y, "Mods: %d ", i_mods);
+ refresh();
+}
+#endif
+
+#endif
diff --git a/yhttpd-0.7.0/src/modl.h b/yhttpd-0.7.0/src/modl.h
new file mode 100755
index 0000000..50587cd
--- /dev/null
+++ b/yhttpd-0.7.0/src/modl.h
@@ -0,0 +1,37 @@
+#include "incl.h"
+
+#ifndef MODL_H
+#define MODL_H
+
+#include "maps/smap.h"
+
+using namespace std;
+
+class modl : private smap<dynmod*,string>
+{
+private:
+ static void dlclose_( dynmod* mod );
+ dynmod* cache_module ( string s_name );
+ void preload_modules( string s_path );
+
+#ifdef NCURSES
+ void print_cached( int i_mods );
+#endif
+
+public:
+ modl();
+ ~modl();
+
+ dynmod* get_module( string s_name );
+
+ vector<string>* get_mod_vector()
+ {
+ vector<string>* p_ret = get_key_vector();
+ return p_ret;
+ }
+
+ void unload_modules();
+ void reload_modules();
+};
+
+#endif
diff --git a/yhttpd-0.7.0/src/msgs.h b/yhttpd-0.7.0/src/msgs.h
new file mode 100644
index 0000000..5937e53
--- /dev/null
+++ b/yhttpd-0.7.0/src/msgs.h
@@ -0,0 +1,101 @@
+#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 CFILEOK "Parsing config file"
+#define CFILEFA "Failed opening config file!"
+#define CONTACT "Contact: http://www.yhttpd.org, Mail@yhttpd.org, ICQ: 11655527"
+#define CLRHTML "HTML: Cleared the template 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 conbbnection "
+#define DESCRIP "Copyright (C) 2003 Paul C. Buetow, Volker Richter"
+#define DESCRI2 "Copyright (C) 2004 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 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 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
+#define NCURADM "ADMINISTRATOR's MAIN MENU"
+#define NCURMSG "SERVER SYSTEM MESSAGES"
+#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 POOLERR "Pool: Malloc error "
+#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 SHELLER "Shell: Could not execute command"
+#define SHELLEX "Shell: Executing the following command:"
+#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 SOCKER2 "Sock: Unknown hostname "
+#define SOCKRDY "Sock: Server socket is ready "
+#define SSLINIT "SSL: Initializing OpenSSL"
+#define TECACHE "HTML: Caching template "
+#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 "yhttpd 0.7"
+#define BRANCH "RELEASE"
+#define BUILDNR 2798
+#define UNAME "FreeBSD 5.2.1-RELEASE-p10 i386"
+
+#endif
diff --git a/yhttpd-0.7.0/src/name.cpp b/yhttpd-0.7.0/src/name.cpp
new file mode 100755
index 0000000..646b4d9
--- /dev/null
+++ b/yhttpd-0.7.0/src/name.cpp
@@ -0,0 +1,51 @@
+// class name implementation.
+
+#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-0.7.0/src/name.h b/yhttpd-0.7.0/src/name.h
new file mode 100755
index 0000000..d5a67da
--- /dev/null
+++ b/yhttpd-0.7.0/src/name.h
@@ -0,0 +1,28 @@
+// class name declaration.
+#include "incl.h"
+
+#ifndef NAME_H
+#define NAME_H
+
+using namespace std;
+
+class name
+{
+protected:
+ // private members:
+ 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 );
+
+ // public methods:
+ name( );
+ name( string s_name ); // a standard constructor.
+ ~name( );
+
+};
+
+#endif
diff --git a/yhttpd-0.7.0/src/ncur/menu.cpp b/yhttpd-0.7.0/src/ncur/menu.cpp
new file mode 100755
index 0000000..c5734a5
--- /dev/null
+++ b/yhttpd-0.7.0/src/ncur/menu.cpp
@@ -0,0 +1,118 @@
+
+#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 ) /* High light the present choice */
+ {
+ 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-0.7.0/src/ncur/menu.h b/yhttpd-0.7.0/src/ncur/menu.h
new file mode 100755
index 0000000..7e4fc5b
--- /dev/null
+++ b/yhttpd-0.7.0/src/ncur/menu.h
@@ -0,0 +1,34 @@
+#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-0.7.0/src/ncur/ncur.cpp b/yhttpd-0.7.0/src/ncur/ncur.cpp
new file mode 100755
index 0000000..e9e7753
--- /dev/null
+++ b/yhttpd-0.7.0/src/ncur/ncur.cpp
@@ -0,0 +1,263 @@
+#ifndef NCUR_CPP
+#define NCUR_CPP
+
+#include "ncur.h"
+
+#ifdef CLI
+#include "../cli/cli.h"
+#endif
+
+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[] = {
+ "Unload all modules ",
+ "Reload all modules ",
+ "Clear template cache ",
+ " ",
+ "Show max res. set size ",
+ "Compile changed sources ",
+ "Recompile all sources ",
+ "Show source stats ",
+ "Command Line Interface ",
+#ifdef DATABASE
+#else
+#endif
+
+ " ",
+ "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( VERSION );
+
+
+ p_menu = new menu( 1, 1, 30, 19, NCURADM, choices, 11, COLOR_PAIR(1));
+
+ mvprintw( NCUR_SERVER_HEADER_X,NCUR_SERVER_HEADER_Y, "HTTP server:");
+ mvprintw( NCUR_POOL_HEADER_X,NCUR_POOL_HEADER_Y, "Thread pool:");
+#ifdef DATABASE
+#endif
+ mvprintw( NCUR_CACHED_HEADER_X,NCUR_CACHED_HEADER_Y, "Caching:");
+ wrap::HTML->print_cached(0);
+
+ is_ready( true );
+
+ 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 1:
+ wrap::MODL->unload_modules();
+ mvprintw( 20,2, "Unloaded all modules ");
+ refresh();
+ break;
+ case 2:
+ wrap::MODL->reload_modules();
+ mvprintw( 20,2, "Reloaded all modules ");
+ refresh();
+ break;
+ 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 */
+ 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
+ mvprintw( 21,2, "Good bye !");
+ close_ncurses();
+ exit(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_WHITE, COLOR_BLUE);
+ mvprintw( 0,2, (char*)(tool::yhttpd_version()).c_str());
+ 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-0.7.0/src/ncur/ncur.h b/yhttpd-0.7.0/src/ncur/ncur.h
new file mode 100755
index 0000000..692a48a
--- /dev/null
+++ b/yhttpd-0.7.0/src/ncur/ncur.h
@@ -0,0 +1,44 @@
+#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:
+ menu* p_menu;
+ WINDOW* p_serveroutput;
+ list<char*>* p_messagelist; // contains the messages for p_serveroutput!
+ pthread_mutex_t mut_messages; // for syncronization of 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_is_ready;
+
+public:
+ ncur( ); // a standard constructor.
+ ~ncur( );
+
+ void start( void *p_void );
+ virtual void print( char* c_print );
+ virtual void print( string s_msg );
+ virtual 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-0.7.0/src/reqp.cpp b/yhttpd-0.7.0/src/reqp.cpp
new file mode 100755
index 0000000..630e34c
--- /dev/null
+++ b/yhttpd-0.7.0/src/reqp.cpp
@@ -0,0 +1,297 @@
+#ifndef REQP_CPP
+#define REQP_CPP
+
+#include "reqp.h"
+#include "tool/tool.h"
+
+using namespace std;
+
+string reqp::HTTP_CODEOK = "HTTP/1.1 200 OK\r\n";
+string reqp::HTTP_SERVER = "Server: yhttpd (Unix)\r\n";
+string reqp::HTTP_CONTAC = "Contact: www.yhttpd.org\r\n";
+string reqp::HTTP_EXPIRE = "Expires: 0\r\n";
+string reqp::HTTP_CACHEC = "Cache-control: no-cache\r\nPragma: no-cache\r\n";
+string reqp::HTTP_CONNEC = "Connection: keep-alive\r\n";
+string reqp::HTTP_CHUNKE = "Transfer-Encoding: chunked\r\n";
+string reqp::HTTP_COTYPE = "Content-Type: ";
+
+reqp::reqp( )
+{}
+
+void
+reqp::get_request_parameters( string s_parameters, map_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) ] = s_tmp.substr( i_pos2+1 );
+
+ 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::iterator iter;
+ // for ( iter = map_params.begin(); iter != map_params.end(); ++iter )
+ // cout << ">>>" << iter->first << "=" << iter->second << endl;
+}
+
+string
+reqp::get_url( thrd* p_thrd, string s_req, map_string &map_params )
+{
+ 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 ( 13 < i_pos2 )
+ {
+ s_ret = url_decode( s_req.substr(6,i_pos2-7) );
+
+ int i_len = s_ret.length();
+ int i_len2 = s_req.length()-1;
+
+ s_req = s_req.substr( i_len < i_len2 ? i_len : i_len2 );
+
+ if ( (i_pos = s_req.find("event=")) == string::npos)
+ {
+ char c_req[POSTBUF];
+ i_len = read(p_thrd->get_sock(), c_req, POSTBUF);
+ s_req = c_req;
+ s_req = s_req.substr(0, i_len);
+
+ if ( (i_pos = s_req.find("event=")) != string::npos )
+ get_request_parameters( url_decode( s_req.substr(i_pos) ), map_params );
+ }
+ else
+ {
+ 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 &map_params )
+{
+ int pos = s_req.find("\n");
+
+ if (pos != string::npos)
+ {
+ map_params["QUERY_STRING"] = tool::trim(s_req.substr(0,pos-1));
+
+ do
+ {
+ string s_line( s_req.substr(0, pos) );
+ int 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 *s)
+{
+ int value;
+ int c;
+
+ c = s->at(0);
+
+ if( isupper(c) )
+ c = tolower(c);
+
+ value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
+
+ c = s->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_str )
+{
+ string s_dest = "";
+ int i_len = s_str.size();
+ int i_prv = i_len - 2;
+
+ for( int i = 0; i < i_len; ++i)
+ {
+ char ch = s_str.at(i);
+ if( ch == '+' )
+ {
+ s_dest += " ";
+ }
+
+ else if (ch == '%' && i < i_prv)
+ {
+ string s_tmp = s_str.substr(i+1, 2);
+ ch = (char) htoi(&s_tmp);
+ s_dest += ch;
+ i += 2;
+ }
+
+ else
+ {
+ s_dest += ch;
+ }
+ }
+
+ 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 "";
+
+ int 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( thrd* p_thrd, string s_req, map_string &map_params )
+{
+ // store all request informations in map_params. store the url in
+ // map_params["request"].
+ get_url( p_thrd, s_req, map_params );
+
+ parse_headers( s_req, map_params );
+ string s_event( map_params["event"] );
+
+ // create the http header.
+ string s_rep( HTTP_CODEOK );
+ s_rep.append( HTTP_SERVER );
+ s_rep.append( HTTP_CONTAC );
+ s_rep.append( HTTP_EXPIRE );
+ s_rep.append( HTTP_CACHEC );
+ s_rep.append( HTTP_CONNEC );
+
+ if ( s_event.compare("stream") == 0 )
+ s_rep.append( HTTP_CHUNKE );
+
+ s_rep.append( HTTP_COTYPE );
+ s_rep.append( get_content_type( map_params["request"] ) );
+ s_rep.append("\r\n\r\n");
+
+
+ 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 ) );
+ }
+
+ // return the parsed html-template.
+ return s_rep;
+}
+
+
+string
+reqp::remove_dots( string s_ret )
+{
+ // remove ".." from the request.
+ unsigned pos;
+
+ if( (pos = s_ret.find( ".." )) != string::npos)
+ return s_ret.substr(0, pos);
+
+ return s_ret;
+}
+
+#endif
diff --git a/yhttpd-0.7.0/src/reqp.h b/yhttpd-0.7.0/src/reqp.h
new file mode 100755
index 0000000..3a998b9
--- /dev/null
+++ b/yhttpd-0.7.0/src/reqp.h
@@ -0,0 +1,49 @@
+#include "incl.h"
+
+#ifndef REQP_H
+#define REQP_H
+
+#include <map>
+#include "thrd/thrd.h"
+
+using namespace std;
+
+typedef map<string, string, less<string> > map_string;
+
+class reqp
+{
+private:
+ static string HTTP_CODEOK,
+ HTTP_CODENF,
+ HTTP_EXPIRE,
+ HTTP_SERVER,
+ HTTP_CONTAC,
+ HTTP_CACHEC,
+ HTTP_CONNEC,
+ HTTP_CHUNKE,
+ HTTP_COTYPE;
+
+ // returns the request url from thr client's http request header
+ // until the first "?" and stores all request parameter values
+ // ( behind "?" ) into map_params.
+ virtual string get_url( thrd* p_thrd, string s_req, map_string &map_params );
+ // returns a specific value of the client's http request header.
+ // ( s.t. like the User-Agent, Referer etc... ).
+ virtual string get_from_header( string s_req, string s_hdr );
+
+ virtual int htoi( string *s );
+ // 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& map_params );
+
+public:
+ reqp( );
+ virtual string parse( thrd* p_thrd, string s_req, map_string &map_params );
+ virtual string url_decode ( string );
+ virtual string get_content_type( string );
+ virtual void parse_headers( string s_req, map_string &map_params );
+};
+
+#endif
diff --git a/yhttpd-0.7.0/src/sock/Makefile b/yhttpd-0.7.0/src/sock/Makefile
new file mode 100644
index 0000000..f5895f1
--- /dev/null
+++ b/yhttpd-0.7.0/src/sock/Makefile
@@ -0,0 +1,23 @@
+#CC=gcc33
+CC=g++
+INCLUDE=
+DEBUG=-D_GNU_SOURCE
+#CFLAGS=-Wall -O3 -s $(DEBUG) $(INCLUDE)
+#CFLAGS=-Wall -g -ansi -pedantic $(DEBUG) $(INCLUDE)
+CFLAGS=-Wall -g $(DEBUG) $(INCLUDE)
+LIBS=-lstdc++
+
+OBJECTS=main-test.o tcp-client.o exception.o
+PROGRAM=main-test
+
+all: $(PROGRAM)
+
+$(PROGRAM): $(OBJECTS)
+ $(CC) $(CFLAGS) -o $@ $(OBJECTS) $(LIBS)
+
+.cpp.o:
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+clean:
+ rm -f $(PROGRAM) $(OBJECTS)
+
diff --git a/yhttpd-0.7.0/src/sock/README b/yhttpd-0.7.0/src/sock/README
new file mode 100644
index 0000000..9d3aac9
--- /dev/null
+++ b/yhttpd-0.7.0/src/sock/README
@@ -0,0 +1 @@
+ossl.h not yet implemented (see header info)
diff --git a/yhttpd-0.7.0/src/sock/sock.cpp b/yhttpd-0.7.0/src/sock/sock.cpp
new file mode 100755
index 0000000..7dba4b7
--- /dev/null
+++ b/yhttpd-0.7.0/src/sock/sock.cpp
@@ -0,0 +1,257 @@
+#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->i_threads = 0;
+ this->req_parser = new reqp();
+ this->thrd_pool = new pool();
+ this->log_daemon = new logd( wrap::CONF->get_elem( "httpd.logging.accessfile" ),
+ wrap::CONF->get_elem( "httpd.logging.accesslines" ) );
+
+ pthread_mutex_init( &mut_threads, NULL );
+}
+
+sock::~sock()
+{
+ pthread_mutex_destroy( &mut_threads );
+}
+
+
+int
+sock::make_server_socket( int i_port )
+{
+ size_t sock;
+ struct sockaddr_in name;
+
+ // create the server socket.
+ sock = socket (PF_INET, SOCK_STREAM, 0);
+ if (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 optval=1;
+
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(int));
+
+ if (bind (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) );
+
+ return make_server_socket( i_port );
+ }
+
+ wrap::system_message( SOCKCRT + string("localhost:") + tool::int2string(i_port) );
+
+#ifdef NCURSES
+ mvprintw( NCUR_PORT_X,NCUR_PORT_Y, "Port: %d ", i_port);
+ refresh();
+#endif
+
+ return sock;
+}
+
+int
+sock::read_write( thrd* p_thrd, int i_sock )
+{
+ char c_req[READSOCK];
+ int i_bytes = read (i_sock, c_req, READSOCK);
+
+ if (i_bytes <= 0)
+ {
+ wrap::system_message( READERR );
+ }
+ else
+ {
+ // stores the request params.
+ map_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);
+
+ map_params["REMOTE_ADDR"] = inet_ntoa(client.sin_addr);
+ //map_params["REMOTE_PORT"] = ntohs(client.sin_port);
+
+ string s_rep = req_parser->parse( p_thrd, string( c_req ), map_params );
+
+ log_daemon->log_access(map_params);
+
+ // send s_rep to the client.
+ send( i_sock, s_rep.c_str(), s_rep.size(), 0 );
+
+ // dont need those vals anymore.
+ map_params.clear();
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+sock::start()
+{
+ wrap::system_message( SOCKSRV );
+
+#ifdef NCURSES
+ print_hits();
+ print_threads();
+ thrd_pool->print_pool_size();
+#endif
+
+ auto int i_port = tool::string2int( wrap::CONF->get_elem( "httpd.serverport" ) );
+
+ int sock;
+ fd_set active_fd_set, read_fd_set;
+ int i;
+ struct sockaddr_in clientname;
+ size_t size;
+
+
+ // create the server socket and set it up to accept connections.
+ sock = make_server_socket ( i_port );
+
+ if (listen (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 (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 == sock )
+ {
+ // connection request on original socket.
+ i_req++;
+#ifdef NCURSES
+ print_hits();
+#endif
+ int new_sock;
+ size = sizeof (clientname);
+ new_sock = accept (sock, (struct sockaddr *) &clientname, &size);
+
+ if (new_sock < 0)
+ {
+ wrap::system_message( ACCPERR );
+ close ( new_sock );
+ }
+
+ else
+ {
+#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 (new_sock, &active_fd_set);
+ }
+ }
+
+ else
+ {
+ thrd_pool->run( (void*) new thrd( i ) );
+ FD_CLR( i, &active_fd_set );
+ }
+ }
+ }
+}
+
+void
+sock::increase_num_threads()
+{
+ pthread_mutex_lock( &mut_threads );
+ i_threads++;
+ pthread_mutex_unlock( &mut_threads );
+
+#ifdef NCURSES
+ print_threads();
+#endif
+}
+
+void
+sock::decrease_num_threads()
+{
+ pthread_mutex_lock( &mut_threads );
+ i_threads--;
+ pthread_mutex_unlock( &mut_threads );
+
+#ifdef NCURSES
+ print_threads();
+#endif
+}
+
+#ifdef NCURSES
+void
+sock::print_threads()
+{
+ if ( wrap::NCUR->is_ready() )
+ {
+ mvprintw( NCUR_POOL_RUNNING_X,NCUR_POOL_RUNNING_Y, "In use: %d ", i_threads);
+ 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-0.7.0/src/sock/sock.h b/yhttpd-0.7.0/src/sock/sock.h
new file mode 100755
index 0000000..079dfd8
--- /dev/null
+++ b/yhttpd-0.7.0/src/sock/sock.h
@@ -0,0 +1,69 @@
+#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 "../thrd/pool.h"
+#include "../thrd/thrd.h"
+#include "../reqp.h"
+#include "../logd.h"
+
+using namespace std;
+
+class sock
+{
+private:
+ // total number of server requests.
+ unsigned long long int i_req;
+
+ bool b_run; // true while socket manager is running.
+ reqp* req_parser; // parses the http requests from clients.
+ pool* thrd_pool; // the thread pool.
+ logd* log_daemon; // the log daemon
+ char* c_buffer; // char buffer!
+
+ int i_threads; // total amount of threads inside the thread pool.
+ pthread_mutex_t mut_threads;
+ pthread_mutex_t mut_hits;
+
+
+public:
+ // creates a server socket.
+ int make_server_socket( int port );
+
+ // small inline methods:
+ bool get_run() const
+ {
+ return b_run;
+ }
+ bool set_run( bool b_run )
+ {
+ this->b_run = b_run;
+ }
+
+ // public methods.
+ explicit sock( ); // simple constructor.
+ ~sock( );
+ virtual int read_write( thrd* p_thrd, int filedes );
+ virtual int start();
+
+ // the chat stream there all the chat messages will sent through.
+
+ void increase_num_threads();
+ void decrease_num_threads();
+#ifdef NCURSES
+
+ void print_threads();
+ void print_hits();
+#endif
+
+};
+
+#endif
diff --git a/yhttpd-0.7.0/src/stats.cpp b/yhttpd-0.7.0/src/stats.cpp
new file mode 100644
index 0000000..63757b6
--- /dev/null
+++ b/yhttpd-0.7.0/src/stats.cpp
@@ -0,0 +1,102 @@
+#ifndef STATS_CPP
+#define STATS_CPP
+
+#include "stats.h"
+#include "tool/tool.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-0.7.0/src/stats.h b/yhttpd-0.7.0/src/stats.h
new file mode 100644
index 0000000..0ef60a2
--- /dev/null
+++ b/yhttpd-0.7.0/src/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>
+#include <iostream>
+
+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-0.7.0/src/thrd/pool.cpp b/yhttpd-0.7.0/src/thrd/pool.cpp
new file mode 100755
index 0000000..1db639d
--- /dev/null
+++ b/yhttpd-0.7.0/src/thrd/pool.cpp
@@ -0,0 +1,206 @@
+#ifndef POOL_CPP
+#define POOL_CPP
+
+#include "pool.h"
+#include "thrd.h"
+
+using namespace std;
+
+pool::pool()
+{
+ i_thrd_pool_size = tool::string2int( wrap::CONF->get_elem( "httpd.thread.poolsize" ) );
+ i_thrd_pool_queue = tool::string2int( wrap::CONF->get_elem( "httpd.thread.queuesize" ) );
+ tpool_init( &thread_pool, i_thrd_pool_size, i_thrd_pool_queue, 0 );
+}
+
+void
+pool::tpool_init( tpool_t *tpoolp, int num_worker_threads, int max_queue_size, int do_not_block_when_full )
+{
+ int i, rtn;
+ tpool_t tpool;
+
+ // allocate a pool data structure
+ if (( tpool = (tpool_t) malloc( sizeof( struct tpool ) ) ) == NULL )
+ {
+ wrap::system_message( POOLERR );
+ exit(-1);
+ }
+
+ // initialize th fields
+ tpool->num_threads = num_worker_threads;
+ tpool->max_queue_size = max_queue_size;
+ tpool->do_not_block_when_full = do_not_block_when_full;
+
+ if ( ( tpool->threads = (pthread_t*) malloc( sizeof( pthread_t ) *num_worker_threads ) ) == NULL )
+ {
+ wrap::system_message( POOLERR );
+ exit(-1);
+ }
+
+ tpool->cur_queue_size = 0;
+ tpool->queue_head = NULL;
+ tpool->queue_tail = NULL;
+ tpool->queue_closed = 0;
+ tpool->shutdown = 0;
+
+ if ( ( rtn = pthread_mutex_init( &(tpool->queue_lock), NULL ) ) != 0 )
+ {
+ string s_err( "pthread_mutex_init " );
+ s_err.append( strerror( rtn ) );
+
+ wrap::system_message( s_err );
+
+ exit(-1);
+ }
+ else if ( ( rtn = pthread_cond_init( &(tpool->queue_not_empty), NULL ) ) != 0 )
+ {
+ string s_err( "pthread_mutex_init " );
+ s_err.append( strerror( rtn ) );
+
+ wrap::system_message( s_err );
+
+ exit(-1);
+ }
+ else if ( ( rtn = pthread_cond_init( &(tpool->queue_not_full), NULL ) ) != 0 )
+ {
+ string s_err( "pthread_mutex_init " );
+ s_err.append( strerror( rtn ) );
+
+ wrap::system_message( s_err );
+
+ exit(-1);
+ }
+ else if ( ( rtn = pthread_cond_init( &(tpool->queue_empty), NULL ) ) != 0 )
+ {
+ string s_err( "pthread_mutex_init " );
+ s_err.append( strerror( rtn ) );
+
+ wrap::system_message( s_err );
+
+ exit(-1);
+ }
+ // create threads
+ for ( i = 0; i < num_worker_threads; i++ )
+ pthread_create( &(tpool->threads[i]) , NULL, tpool_thread, (void*)tpool );
+
+ *tpoolp = tpool;
+}
+
+void*
+pool::tpool_thread( void* arg )
+{
+ tpool_t tpool = (tpool_t) arg;
+ tpool_work_t *my_workp;
+
+ while( true )
+ {
+ pthread_mutex_lock( &(tpool->queue_lock) );
+
+ while ( (tpool->cur_queue_size == 0) && (!tpool->shutdown) )
+ pthread_cond_wait( &(tpool->queue_not_empty), &(tpool->queue_lock) );
+
+ if (tpool->shutdown)
+ {
+ pthread_mutex_unlock( &(tpool->queue_lock) );
+ pthread_exit( NULL );
+ }
+
+ my_workp = tpool->queue_head;
+ tpool->cur_queue_size--;
+
+ if ( tpool->cur_queue_size == 0)
+ tpool->queue_head = tpool->queue_tail = NULL;
+
+ else
+ tpool->queue_head = my_workp->next;
+
+ if ( ( ! tpool->do_not_block_when_full ) &&
+ ( tpool->cur_queue_size == ( tpool->max_queue_size - 1 ) ) )
+ pthread_cond_signal( &(tpool->queue_not_full) );
+
+ if ( tpool->cur_queue_size == 0 )
+ pthread_cond_signal( &(tpool->queue_empty) );
+
+ pthread_mutex_unlock( &(tpool->queue_lock) );
+ (*(my_workp->routine))(my_workp->arg);
+ free((void*)my_workp);
+ }
+}
+
+void pool::run_func( void *v_pointer )
+{
+ wrap::SOCK->increase_num_threads();
+
+ // recasting the client thread object.
+ thrd *t = (thrd*) v_pointer;
+
+ // start parsing the client request and sending response's back.
+ t-> run ();
+
+ // close the client socket.
+ t->~thrd();
+
+ wrap::SOCK->decrease_num_threads();
+
+ free(v_pointer);
+}
+
+int
+pool::tpool_add_work( tpool_t tpool, void(*routine)(void*), void* arg ) ///
+{
+ tpool_work_t *workp;
+ pthread_mutex_lock( &(tpool->queue_lock) );
+
+ if( ( tpool->cur_queue_size == tpool->max_queue_size ) &&
+ tpool->do_not_block_when_full )
+ {
+ pthread_mutex_unlock( &(tpool->queue_lock) );
+ return -1;
+ }
+
+ while( ( tpool->cur_queue_size == tpool->max_queue_size ) &&
+ ( ! ( tpool->shutdown || tpool->queue_closed ) ) )
+ pthread_cond_wait( &(tpool->queue_not_full), &(tpool->queue_lock) );
+
+ if( tpool->shutdown || tpool->queue_closed )
+ {
+ pthread_mutex_unlock( &tpool->queue_lock );
+ return -1;
+ }
+
+ // allocate work structure:
+ workp = (tpool_work_t*) malloc( sizeof( tpool_work_t ) );
+
+ workp->routine = routine;
+ workp->arg = arg;
+ workp->next = NULL;
+
+ if( tpool->cur_queue_size == 0 )
+ {
+ tpool->queue_tail = tpool->queue_head = workp;
+ }
+ else
+ {
+ (tpool->queue_tail)->next = workp;
+ tpool->queue_tail = workp;
+ }
+
+ pthread_cond_signal( &tpool->queue_not_empty );
+ tpool->cur_queue_size++;
+ pthread_mutex_unlock( &(tpool->queue_lock) );
+ return 1;
+}
+
+#ifdef NCURSES
+void
+pool::print_pool_size()
+{
+ if ( wrap::NCUR->is_ready() )
+ {
+ mvprintw( NCUR_POOL_SIZE_X,NCUR_POOL_SIZE_Y, "Size: %d %d", i_thrd_pool_size, i_thrd_pool_queue );
+ refresh();
+ }
+}
+#endif
+
+#endif
diff --git a/yhttpd-0.7.0/src/thrd/pool.h b/yhttpd-0.7.0/src/thrd/pool.h
new file mode 100755
index 0000000..a744133
--- /dev/null
+++ b/yhttpd-0.7.0/src/thrd/pool.h
@@ -0,0 +1,77 @@
+#include "../incl.h"
+
+#ifndef POOL_H
+#define POOL_H
+
+using namespace std;
+
+class pool
+{
+private:
+ typedef struct tpool_work
+ {
+ void (*routine)(void*); ///
+ void *arg;
+ struct tpool_work *next;
+ }
+ tpool_work_t;
+
+ typedef struct tpool
+ {
+ // pool characteristics:
+ int num_threads;
+ int max_queue_size;
+ int do_not_block_when_full;
+
+ // pool state
+ pthread_t *threads;
+ int cur_queue_size;
+
+ tpool_work_t *queue_head;
+ tpool_work_t *queue_tail;
+
+ pthread_mutex_t queue_lock;
+ pthread_cond_t queue_not_empty;
+ pthread_cond_t queue_not_full;
+ pthread_cond_t queue_empty;
+
+ int queue_closed;
+ int shutdown;
+ }
+ *tpool_t;
+
+ int i_thrd_pool_size;
+ int i_thrd_pool_queue;
+
+ tpool_t thread_pool;
+
+ void
+ tpool_init( tpool_t *tpoolp, int num_worker_threads, int max_queue_size, int do_not_block_when_full );
+
+ int
+ tpool_add_work( tpool_t tpool, void(*routine)(void*), void* arg );
+
+ // virtual void
+ // tpool_destroy( tpool_t tpoolp, int finish );
+
+ static void*
+ tpool_thread( void* arg);
+
+ static void
+ run_func( void *v_pointer );
+
+ // public methods:
+public:
+ pool( );
+
+ // inline (speed)!
+ void run( void *arg )
+ {
+ tpool_add_work( thread_pool, run_func, arg );
+ }
+#ifdef NCURSES
+ void print_pool_size();
+#endif
+};
+
+#endif
diff --git a/yhttpd-0.7.0/src/thrd/thrd.cpp b/yhttpd-0.7.0/src/thrd/thrd.cpp
new file mode 100755
index 0000000..63135a8
--- /dev/null
+++ b/yhttpd-0.7.0/src/thrd/thrd.cpp
@@ -0,0 +1,26 @@
+#ifndef THRD_CPP
+#define THRD_CPP
+
+#include "thrd.h"
+#include <sys/socket.h>
+
+using namespace std;
+
+thrd::thrd( int i_sock )
+{
+ this->i_sock = i_sock;
+}
+
+thrd::~thrd()
+{
+ shutdown ( get_sock() , 2 );
+ close ( get_sock() );
+}
+
+void
+thrd::run()
+{
+ wrap::SOCK->read_write( this, i_sock );
+}
+
+#endif
diff --git a/yhttpd-0.7.0/src/thrd/thrd.h b/yhttpd-0.7.0/src/thrd/thrd.h
new file mode 100755
index 0000000..7cd63b7
--- /dev/null
+++ b/yhttpd-0.7.0/src/thrd/thrd.h
@@ -0,0 +1,28 @@
+// class thrd declaration.
+#include "../incl.h"
+
+#ifndef THRD_H
+#define THRD_H
+
+using namespace std;
+
+class thrd
+{
+private:
+ int i_sock;
+
+public:
+
+ // small inline methods:
+ int get_sock()
+ {
+ return i_sock;
+ }
+
+ // public methods:
+ explicit thrd( int i_sock );
+ ~thrd(); // destructor.
+ virtual void run();
+};
+
+#endif
diff --git a/yhttpd-0.7.0/src/thrd/thro.cpp b/yhttpd-0.7.0/src/thrd/thro.cpp
new file mode 100644
index 0000000..f6acf53
--- /dev/null
+++ b/yhttpd-0.7.0/src/thrd/thro.cpp
@@ -0,0 +1,45 @@
+#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;
+ 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-0.7.0/src/thrd/thro.h b/yhttpd-0.7.0/src/thrd/thro.h
new file mode 100644
index 0000000..ef38793
--- /dev/null
+++ b/yhttpd-0.7.0/src/thrd/thro.h
@@ -0,0 +1,30 @@
+// Threaded Object (thro)
+
+#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-0.7.0/src/time/timo.cpp b/yhttpd-0.7.0/src/time/timo.cpp
new file mode 100755
index 0000000..c44ebae
--- /dev/null
+++ b/yhttpd-0.7.0/src/time/timo.cpp
@@ -0,0 +1,36 @@
+#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-0.7.0/src/time/timo.h b/yhttpd-0.7.0/src/time/timo.h
new file mode 100755
index 0000000..4eaecf8
--- /dev/null
+++ b/yhttpd-0.7.0/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();
+ void renew_timeout();
+};
+
+#endif
diff --git a/yhttpd-0.7.0/src/time/timr.cpp b/yhttpd-0.7.0/src/time/timr.cpp
new file mode 100755
index 0000000..91dc7f7
--- /dev/null
+++ b/yhttpd-0.7.0/src/time/timr.cpp
@@ -0,0 +1,167 @@
+#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_pointer )
+{
+// timr* p_timer = this; //static_cast<timr*>(this);
+
+ 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 )
+ {
+
+ // run every hour
+ if ( time_now.tm_hour % 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-0.7.0/src/time/timr.h b/yhttpd-0.7.0/src/time/timr.h
new file mode 100755
index 0000000..a327d5b
--- /dev/null
+++ b/yhttpd-0.7.0/src/time/timr.h
@@ -0,0 +1,63 @@
+#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_pointer );
+
+#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;
+ }
+
+ virtual int get_offset();
+ virtual double get_time_diff( time_t& clock_diff );
+};
+
+#endif
diff --git a/yhttpd-0.7.0/src/tool/dir.cpp b/yhttpd-0.7.0/src/tool/dir.cpp
new file mode 100644
index 0000000..392112a
--- /dev/null
+++ b/yhttpd-0.7.0/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()
+{
+ dir_vec.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;
+
+ dp = opendir( s_dir.c_str() );
+
+ if ( dp == NULL )
+ return false; // Could not open dir.
+
+ b_open = true;
+
+ return true; // Could open dir with success.
+}
+
+void
+dir::close_dir()
+{
+ if ( b_open && dp != NULL )
+ {
+ closedir( dp );
+ b_open = false;
+ }
+}
+
+void
+dir::read_dir()
+{
+ if ( dp != NULL )
+ while( ep = readdir( dp ) )
+ dir_vec.push_back( string( ep->d_name ) );
+}
+
+vector<string>
+dir::get_dir_vec()
+{
+ return dir_vec;
+}
+
+#endif
diff --git a/yhttpd-0.7.0/src/tool/dir.h b/yhttpd-0.7.0/src/tool/dir.h
new file mode 100644
index 0000000..cff265f
--- /dev/null
+++ b/yhttpd-0.7.0/src/tool/dir.h
@@ -0,0 +1,33 @@
+
+#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 *dp;
+ struct dirent *ep;
+ vector<string> dir_vec;
+
+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-0.7.0/src/tool/tool.cpp b/yhttpd-0.7.0/src/tool/tool.cpp
new file mode 100644
index 0000000..1da4a12
--- /dev/null
+++ b/yhttpd-0.7.0/src/tool/tool.cpp
@@ -0,0 +1,129 @@
+#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"
+
+string
+tool::trim( string s_str )
+{
+ if(s_str.empty())
+ return "";
+
+ char c_cur = s_str[0];
+ auto int pos=0;
+
+ // left trim
+ while (c_cur==' '|| c_cur == '\n' || c_cur == '\r')
+ {
+ s_str.erase(pos,1);
+ c_cur = s_str[++pos];
+ }
+
+ // right trim
+ 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(pos,1);
+ c_cur = s_str[--pos];
+ }
+
+ return s_str;
+}
+
+char*
+tool::clean_char( char* c_str )
+{
+ // Ralf:
+ char *c_pos;
+ for (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 int 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 pos = s_file.find_last_of(".");
+ if(pos != string::npos)
+ {
+ string s_ext=s_file.substr(pos+1, s_file.size()-(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 *buffer = new char[64];
+ sprintf(buffer, "%d", i_int);
+ return buffer;
+}
+
+string
+tool::shell_command( string s_command, method m_method )
+{
+ FILE *file;
+ char buffer[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(buffer, READBUF, file) == NULL)
+ break;
+ switch (m_method) {
+ case METH_NCURSES:
+ wrap::system_message( clean_char(buffer) );
+ break;
+ default:
+ s_ret.append("\n" + string(buffer));
+ } // switch
+ }
+ pclose(file);
+ }
+
+ return s_ret;
+}
+
+#endif
+
diff --git a/yhttpd-0.7.0/src/tool/tool.h b/yhttpd-0.7.0/src/tool/tool.h
new file mode 100644
index 0000000..a350c69
--- /dev/null
+++ b/yhttpd-0.7.0/src/tool/tool.h
@@ -0,0 +1,93 @@
+#ifndef TOOL_H
+#define TOOL_H
+
+#include "../incl.h"
+
+using namespace std;
+
+class tool
+{
+public:
+ static bool is_alpha_numeric( string &s_digit )
+ {
+ auto const char *digit = s_digit.c_str();
+ auto int i_len = strlen( digit );
+
+
+ for( int i=0; i<i_len; i++ )
+ {
+ if ( ! isalnum( *digit ) )
+ return false;
+ digit++;
+ }
+ return true;
+ }
+
+ 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 )
+ {
+ char buffer[64];
+ sprintf(buffer, "%d", i_int);
+ return string(buffer);
+ }
+
+ static long unixtime()
+ {
+ time_t clock;
+ return (long) time( &clock );
+ }
+
+ static int string2int( string s_digit )
+ {
+ auto const char *digit = s_digit.c_str();
+ int result = 0;
+
+ // Convert each digit char and add into result.
+ while (*digit >= '0' && *digit <='9')
+ {
+ result = (result * 10) + (*digit - '0');
+ digit++;
+ }
+
+ // Check that there were no non-digits at end.
+ if (*digit != 0)
+ {
+ return -1;
+ }
+
+ return result;
+ }
+ static void strip_html( string *s_str)
+ {
+ auto int i_pos;
+ if((i_pos=s_str->find("<",0))==string::npos)
+ return;
+ while(true)
+ {
+ s_str->replace(i_pos,1,"&lt;");
+ if((i_pos=s_str->find("<",0))==string::npos)
+ return;
+ }
+ }
+
+ static string get_extension( string s_file );
+ static string to_lower( string s )
+ {
+ string s_tmp("");
+ for(int i=0;i < s.size() ;i++)
+ s_tmp=s_tmp+(char)tolower(s.at(i));
+ return s_tmp;
+ }
+
+ static string shell_command( string s_command, method m_method );
+
+ static string yhttpd_version()
+ {
+ return string(VERSION) + "-" + string(BRANCH) + " Build " + int2string(BUILDNR);
+ }
+};
+
+#endif
diff --git a/yhttpd-0.7.0/src/wrap.cpp b/yhttpd-0.7.0/src/wrap.cpp
new file mode 100755
index 0000000..81c6679
--- /dev/null
+++ b/yhttpd-0.7.0/src/wrap.cpp
@@ -0,0 +1,32 @@
+#ifndef WRAP_CPP
+#define WRAP_CPP
+
+#include "wrap.h"
+
+using namespace std;
+
+
+conf* wrap::CONF;
+html* wrap::HTML;
+logd* wrap::LOGD;
+modl* wrap::MODL;
+#ifdef NCURSES
+ncur* wrap::NCUR;
+#endif
+sock* wrap::SOCK;
+stats* wrap::STAT;
+timr* wrap::TIMR;
+dynamic_wrap* wrap::WRAP;
+
+void
+wrap::system_message( string s_message )
+{
+#ifdef NCURSES
+ wrap::NCUR->print( s_message );
+#endif
+#ifdef SERVMSG
+ cout << s_message << endl;
+#endif
+ wrap::LOGD->log_simple_line( s_message + "\n" );
+}
+#endif
diff --git a/yhttpd-0.7.0/src/wrap.h b/yhttpd-0.7.0/src/wrap.h
new file mode 100755
index 0000000..1207f03
--- /dev/null
+++ b/yhttpd-0.7.0/src/wrap.h
@@ -0,0 +1,67 @@
+#ifndef WRAP_H
+#define WRAP_H
+
+#include "incl.h"
+
+#ifdef DATABASE
+#endif
+#include "conf/conf.h"
+#include "html.h"
+#include "logd.h"
+#include "modl.h"
+#ifdef NCURSES
+#include "ncur/ncur.h"
+#endif
+#include "sock/sock.h"
+#include "stats.h"
+#include "time/timr.h"
+
+using namespace std;
+
+class dynamic_wrap
+{
+ public:
+
+ conf* CONF;
+ html* HTML;
+ logd* LOGD;
+ modl* MODL;
+#ifdef NCURSES
+ ncur* NCUR;
+#endif
+ sock* SOCK;
+ stats* STAT;
+ timr* TIMR;
+};
+
+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 conf* CONF;
+ static html* HTML;
+ static logd* LOGD;
+ static modl* MODL;
+#ifdef NCURSES
+ static ncur* NCUR;
+#endif
+ static sock* SOCK;
+ static stats* STAT;
+ static timr* TIMR;
+ static dynamic_wrap* WRAP;
+};
+
+
+#endif